Reputation: 55739
let $s := ('foo', 'bar')
for $d in collection('mycollection')
where ($d/Id/text() in $s)
return <p>{$d//Name} ({$d//Id})</p>
Returns
[1.0-ml] XDMP-UNEXPECTED: (err:XPST0003) Unexpected token syntax error, unexpected In_, expecting Comma_ or Rpar_ or SemiColon_
Pointing to:
where ($d/Id/text() in $s)
What is the correct syntax here?
Upvotes: 0
Views: 370
Reputation: 191
It's not a good habit to think of text()
as equivalent to string. They're not strings, they're nodes that atomize as strings. Treating them as the same can lead to subtle, hard to diagnose bugs. A better formulation is this:
let $s := ('foo', 'bar')
for $d in collection('mycollection')
where $d/Id/fn:string() = $s
return <p>{$d/Name} ({$d/Id})</p>
That being said, because text() nodes atomize as strings, and elements atomize as the concatenated values of their children, you can usually (when an element has simple text content) simply compare the element to a string (or sequence of strings):
let $s := ('foo', 'bar')
for $d in collection('mycollection')
where $d/Id = $s
return <p>{$d/Name} ({$d/Id})</p>
Another good practice is to place the selection criteria in the for
expression where possible, rather than in a where
clause. This often makes the intent more clear, but more importantly it can also make it easier for the processor to optimize. For example
let $s := ('foo', 'bar')
for $d in collection('mycollection')[Id = $s]
return <p>{$d/Name} ({$d/Id})</p>
This is not only simpler and more expressive, a processor like MarkLogic can convert collection('mycollection')[Id = $s]
into an efficient xdml:element-value-query
. Using the where
form could result in a brute-force check of every document in the collection.
Upvotes: 2
Reputation: 55739
The =
operator should be used.
let $s := ('foo', 'bar')
for $d in collection('mycollection')
where $d/Id/text() = $s
return <p>{$d/Name} ({$d/Id})</p>
Upvotes: 0