Question

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"?

Was it helpful?

Solution

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 :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top