3

I'm using the official documentation: http://docs.basex.org/wiki/Commands#String_Syntax, and I haven't been able to locate a list of logical operators. I want to be able to query text contains 'A' or 'B'.

Along these same lines, I'm also trying to figure out how to limit the number of results returned, and I'm trying to find a good guide to creating relations tables in BaseX.

Here's what I am working with.... I've figured out how to do 'or', but I haven't figured out how to pass in variables for different targets, yet.

let $items := ('Creditcard', 'Money order')
for $item score $s in doc('xmark')//item
  [payment contains text "$items" using stemming using case sensitive]
order by $s descending
return <item ranking= '{ $s }'>{ $item/payment/text() }</item>

-Edit-

Now looking at this code, which is based off of the existing answer:

let $items := ('Creditcard', 'Money order')
for $item in descendant::*:$item | descendant-or-self::*[text() contains text "$item"] | .//item//payment[descendant-or-self::node()/@*:lang = "bnt"][descendant-or-self::node()/@*:lang = "afr"][descendant-or-self::node()/@*:lang = "eng"][descendant-or-self::node()/@*:lang = "chi"]
return <payment>{ .//item//payment/text() }</payment>
       <buyer_name>{ .//item//buyer/text() }</buyer_name>

-Edit-

Another attempt:

let $list := doc('xmark')
return for $p in $list/payments/item/payment-method[text() = 'Creditcard']
return $p//text()

Returns 0 results. Just trying to get 'Creditcard', the value of 'payment method', out of the text. Basically, I haven't been able to find and consistent or successful examples.

-Edit-

The most recent attempt is very close; however, when I apply it to the database I'm actually trying to access, rather than the BaseX sample database, I get a special brand of error:

via http://basex.org/products/live-demo/

doc('test') :=

<item>
<item_number>1171270</item_number>
<seller_info>
<seller_company_id>6356</seller_company_id>
<seller_rating>C31</seller_rating>
<seller_rating>T150 hr.</seller_rating>
</seller_info>
<product_info>
<unit>2022</unit>
<sinfo>55 cases</sinfo>
<sinfo>Yu-gi-oh trading card pack</sinfo>
<sinfo>.45kg per unit</sinfo>
<sinfo>24.7500kg shipment</sinfo>
</product_info>
<product_info>
<unit>9291</unit>
<sinfo>7 units</sinfo>
<sinfo>Naruto, Classic, action figure</sinfo>
<sinfo>1.8kg per unit</sinfo>
<sinfo>12.6kg shipment</sinfo>
</product_info>
</item>

0: write your own query... :=

let $doc := doc('test') 
for $v in $doc//item
where contains($v//seller_rating,'C31')
return $v//product_info/sinfo

Returns:

Error:
Stopped at line 3, column 39: [XPTY0004] Single item expected, (element seller_rating { ... }, element seller_rating { ... }) found.

I can't say I didn't expect to encounter a problem like this. Unfortunately, I didn't format the XML document, and it's all terribly formatted, like this, which is part of the reason I'm trying to access it (to restructure it). Next question coming up: "how do I target same-node-having values in XQuery"?

Community
  • 1
  • 1
Wolfpack'08
  • 3,982
  • 11
  • 46
  • 78
  • `[payment contains text 'Creditcard' using stemming using case sensitive or payment contains text 'Money order' using stemming using case sensitive]` works for or, but it's really wordy. Also, it limits my return values. I'd like to be able to return the `Creditcard` set as one variable and `Money order` as another. – Wolfpack'08 Sep 15 '12 at 10:12
  • It may be true that XQuery applies? – Wolfpack'08 Sep 15 '12 at 11:58
  • yes this questiono is fully XQuery related, I'll try to provide you with an answer soon :) – michael Sep 15 '12 at 14:24
  • @Michael Have you got any idea as to how I can use xquery via HTML or JavaScript? I'm trying to get a formatted list of query results based on an array of targets 'contains text' items. I don't want to have to use ROR or PHP or Node or anything. I'd really just like to use HTML. – Wolfpack'08 Sep 15 '12 at 14:26
  • I mean, if I could use Javascript, I could create a while loop on a CSV with my array, using this method: http://stackoverflow.com/questions/6861180/how-can-you-read-a-file-line-by-line-in-javascript, and I could then pass the variables into the `$items` positions in the script I've written in my example, right? – Wolfpack'08 Sep 15 '12 at 14:28
  • 1
    Wolfpack you could have a look at RestXQ (http://docs.basex.org/wiki/RESTXQ) it allows you to use XQuery as a server side language that outputs HTML (or XML for that matter) to the browser. – michael Sep 15 '12 at 15:03
  • @Michael I have been considering that. I actually am not very familiar with HTTP requests, so I'm not sure whether the link I've mentioned above would pull a CSV in from the server, or if it would try to get a CSV from a user's computer.... I'm hoping it would do the smart thing and look for it on the server. I'm trying to figure out how to loop through a CSV through EOF in JavaScript, and I haven't had any luck with that, so far. I'm sure I'll run into it, eventually, though... – Wolfpack'08 Sep 16 '12 at 06:57

1 Answers1

2

imho this most closely resembles your question:

let $results := 
( (: Prepare a sequence of results for each $keyword in $keywords :)
let $keywords := ('Money order', 'Creditcard', 'Personal Check')
for $keyword in $keywords
  (: see http://docs.basex.org/wiki/Full-Text#Scoring for information regarding
  scores :)
  for $item score $s in doc('xmark')//item[
    payment contains text {$keyword} all words using stemming using case sensitive
  ]
  order by $s descending
  return <item ranking= '{ $s }'>{ $item/payment/text() }</item>
)
(: now sort and group these results, grouping is done to eliminate duplicate payment
methods that have been matched by two or more keywords :)
for $result in $results
  group by $val := $result/text()
  order by $result[1]/@ranking descending
return $result[1]

Still, I think you might not be interested in the score but in the total number of distinct payment methods that contain your keywords, the following query will provide you with these data:

let $keywords := ('Cash', 'Personal Check')
for $keyword in $keywords 
return <keyword name="{$keyword}">
{
for $result in //item/payment
  group by $payment-method := $result/text()
  order by count($result) descending
return element {"item"} {
    attribute {"count"} {count($result)},
    $payment-method
  }[. contains text {$keyword} phrase]
}</keyword>

I hope this helps and answers your question, in case it does not feel free to ask for more help :)

michael
  • 1,577
  • 1
  • 12
  • 18
  • If I wanted to set $keywords to a `\n`-separated-value file, using JavaScript and XQuery..., would you happen to be able to tailor the script for that purpose? I will post my best effort in the question body, soon. – Wolfpack'08 Sep 16 '12 at 06:58
  • I actually was able to find that BaseX has a page dedicated to HTTP events! Tight, right? :D http://docs.basex.org/wiki/HTTP_Module – Wolfpack'08 Sep 16 '12 at 08:59
  • 1
    Exactly, yet the way to go was reading a little on RestXQ (-> http://docs.basex.org/wiki/RESTXQ) that allows you to use functions from our HTTP module :) – michael Sep 16 '12 at 11:20
  • minor addition to my comment: the HTTP module allows you to send request to URLs from inside XQuery (e.g. fetch an RSS feed). RestXQ in contrast allows you to write XQuery functions that output their results to a web browser, much like writing web applications in PHP. (hope this helped) – michael Sep 16 '12 at 11:26
  • Oh man. Thanks. You rock. If I come up with something kick***, I'll post it up. – Wolfpack'08 Sep 16 '12 at 11:39
  • http://codepad.org/Yzn90mRf; http://codepad.org/TssJhGOe. Multiple targets, multi-column result. – Wolfpack'08 Sep 17 '12 at 04:06
  • I think I'll just give you a checkmark for explaining how to input multiple values and move 'how to output multiple values' into a separate question. – Wolfpack'08 Sep 17 '12 at 06:46
  • 1
    Hi Wolfpack, I clarified my examples a litte, see here: https://gist.github.com/360afe2284ea89cf1f15 (sorry I could not edit on codepad) This already covers more advanced XQuery topics (grouping, looping over loops), I suggest you have a look at http://www.stylusstudio.com/xquery_primer.html for an introduction :) – michael Sep 17 '12 at 18:20
  • Yeah, I asked a new question because I feel that this one wasn't clear enough but served a purpose in its own way. I ran into this article: http://www.databasejournal.com/sqletc/article.php/3865201/Ten-Problems-with-XQuery-and-the-SQLXML-Standard.htm. Unfortunately, it's 2 years old, so I can't be sure about its accuracy. #9 says the select feature is glitch, though. – Wolfpack'08 Sep 17 '12 at 22:43
  • I've been through that tutorial, also. I'm reading through it again, but I don't believe it actually covers this kind of query. Multiple targets, multiple nests, multiple results. – Wolfpack'08 Sep 18 '12 at 01:16
  • Actually, I spent about an hour in the tutorial you mentioned, and I think it brought me a lot closer to the goal. Here's a sample query I'm looking at, now: `let $doc := . for $v in $doc//payment, $a in $doc//person/name where contains text ($a, 'Greg') and $v/buyer/@id = $a/../@id return $v/payment/amount`... I'm not sure if it will work, yet, of course. :) I'm going to try it using Saxon, but I haven't figured out how to name a scenario (sample.xquery, in the doc listed). – Wolfpack'08 Sep 18 '12 at 03:32
  • Feel free to use your Query with BaseX, this might be easy as well :) – michael Sep 18 '12 at 06:56
  • Actually, that poses a problem. :/ I tried to run my query in BaseX.... Guess what? IT FAILED! lol. It works with Stylus Studio, but I'm not allowed to return more than 64,000 results, so that errors out on me. I'm trying to work with Saxon. I'm not sure how to save a reusable script for Saxon with parameters, but I think I'm on my way. – Wolfpack'08 Sep 18 '12 at 07:44