Xquery Where clause not working when using nested query - xquery

Good Day,
I'm new to xquery.
I'm trying to execute xquery with a where clause that returns the values greater than a value returned from a nested query as show below. It runs but returns values that are not greater than the returned value
If I use the where clause directly with the value it works fine. I'm using BaseX to execute my query. Appreciate any feedback, I believe the parser may be reading my subquery wrong.
for $y in doc("url.xml")/taxi_stations/stand
where $y/taxis>=
(
for $x in doc("url.xml")/taxi_stations/stand
where $x/name="Jacksonville"
return data($x/taxis)
)
return ($y/taxis,$y/name)

What is the value of $taxis? It's possible your comparisons are happening on strings, not numbers.
In your nested return, you call data() on $x/taxis - assuming that correctly returns a number value, then $y/taxis in your outer where clause should probably also be wrapped in data().
However, if there is no schema on your document, then data() will simply return a string. In that case you should convert your taxis element to a number using fn:number() or directly casting it like $y/taxis/xs:integer(.).

Related

Custom sorting issue in MarkLogic?

xquery version "1.0-ml";
declare function local:sortit(){
for $i in ('a','e','f','b','d','c')
order by $i
return
element Result{
element N{1},
element File{$i}
}
};
local:sortit()
the above code is sample, I need the data in this format. This sorting function is used multiple places, and I need only element N data some places and only File element data at other places.
But the moment I use the local:sortit()//File. It removes the sorting order and gives the random output. Please let me know what is the best way to do this or how to handle it.
All these data in File element is calculated and comes from multiple files, after doing all the joins and calculation, it will be formed as XML with many elements in it. So sorting using index and all is not possible here. Only order by clause can be used.
XPath expressions are always returned in document order.
You lose the sorting when you apply an XPath to the sequence returned from that function call.
If you want to select only the File in sorted order, try using the simple mapping operator !, and then plucking the F element from the item as you are mapping each item in the sequence:
local:sortit() ! File
Or, if you like typing, you can use a FLWOR to iterate over the sequence and return the File:
for $result in local:sortit()
return $result/File

Displaying the same value in SQL case statement

This might be a simple question but I am unable to find a solution for this, I have a SQL case statement of some form, for example:
CASE
WHEN table_1.col_1 IS NULL THEN 'NULL'
ELSE table_1.col_1
END as 'col_1'
col_1 is of TEXT data type. What I am trying to achieve is that I want NULL to be written wherever the value is NULL and then I want the original value to be displayed if it is not NULL.
I checked the rest of the query it is fine. Making the ELSE statement to 'table_1.col_1' results in all the NOT NULL values as 'table_1.col_1'.
Making the ELSE statement to 'table_1.col_1' results in all the NOT
NULL values as 'table_1.col_1'
Don't use single quotes because you get a string literal 'table_1.col_1' and not the value of the column table_1.col_1.
In the CASE expression that you posted though there are not single quotes around table_1.col_1 so it should work fine, but this logic can be expressed with COALESCE() like this:
COALESCE(table_1.col_1, 'NULL') AS col_1
Also don't use single quotes for aliases. If needed use backticks or square brackets.

Dynamic predicate in XQuery

I notice one fact that when predicate has dynamic field to compare then it doesn't work.
For example:
db:open("library")//book[$filterFields = $pattern]
for this I get 0 results,
but when I put for example category instead of $filterField then I have some results.
How can I use variable in predicate as field?
If $filterFields is supposed to contain a list of element names, you can possibly use the following query:
db:open("library")//book
[*[name() = $filterFields] = $pattern]

An XDMP-NOTANODE error using xquery in marklogic

I'm getting the XDMP-NOTANODE error when I try to run an XQuery in MarkLogic. When I loaded my xml documents I loaded meta data files with them. I'm a student and I don't have experience in XQuery.
error:
[1.0-ml] XDMP-NOTANODE: (err:XPTY0019) $article/article/front/article-meta/title-group/article-title -- xs:untypedAtomic("
") is not a node
Stack Trace
At line 3 column 77:
In xdmp:eval("(for $article in fn:distinct-values(/article/text()) &#1...", (), <options xmlns="xdmp:eval"><database>4206169969988859108</database> <root>C:\mls-projects\pu...</options>)
$article := xs:untypedAtomic("
")
1. (for $article in fn:distinct-values(/article/text())
2.
3. return (fn:distinct-values($article/article/front/article-meta/title-group/article-title)
4.
5.
Code:
(
for $article in fn:distinct-values(/article/text())
return (
fn:distinct-values($article/article/front/article-meta/title-group/article-title/text())
)
)
Every $article is bound to an atomic value (fn:distinct-values() returns a sequence of atomic values). Then you try to apply a path expression (using the / operator) on $article. Which is forbidden, as the path operator requires its LHS operator to be nodes.
I am afraid your code does not make sense enough for me to suggest you an actual solution. I can only pinpoint where the error is.
Furthermore, using text() at the end of a path is most of the time a bad idea. And if /article is a complex document, it is certainly not what you want. One of the text nodes you select (most likely the first one) is simply one single newline character.
What do you want to achieve?
Your $article variable is bound to an atomic value, not a node() from the article document. You can only use an XPath axis on a node.
When you apply the function distinct-values() in the for statement, it returns simple string values, not the article document or nodes from it.
You can probably make things work by using the values in a predicate filter like this:
for $article-text in fn:distinct-values(/article/text())
return
fn:distinct-values(/article[text()=$article-text]/front/article-meta/title-group/article-title/text())
Note: The above XQuery should avoid the XDMP-NOTANODE error, but there are likely easier (and more efficient) solutions for achieving your goal. If you were to post a sample of your document and describe what you are trying to achieve, we could suggest alternatives.
Bit of a wild guess, but you have two distinct-values in your code. That makes me think you want a unique list of articles, and then finally a unique list of article-title's. I would hope you already have unique articles in your database, unless you are explicitly attempting to de-duplicate them.
In case you just want the overall unique list of article titles, I would do something like:
distinct-values(
for $article in collection()/article
return
$article/front/article-meta/title-group/article-title
)
HTH!

Xquery version of "NOT IN" clause not working as expected

I have an xml file which can be downloaded in the following link:
http://expirebox.com/download/483d465091802df68da10feddc1ec98c.html
I am trying to select all those movies without the styles of "live action" and "camp" in my movies.xml. To achieve this I am using the following query
for $movie in db:open("movies","movies.xml")/movies/movie
where $movie/styles/style!=("noir","anthology")
return $movie
However, all nodes in movies are getting selected. What is going wrong in my query?
Some experts are pointing out the inability of the standard not equal operator not working in this case due to the semantics of XQuery involved. However, my intention is to find a corresponding query of an SQL feature and not just understand the semantics.
!= uses set comparison logic.
For values that are not in that sequence, such as "foo", the expression "foo" != ("noir", "anthology") returns true However, the expression "noir" != ("noir", "anthology") would also return true. This is because "noir" does not equal one of the items in the sequence, "anthology", even though it also equals one of the items in the sequence as well. The expression "noir" = ("noir", "anthology") returns true because "noir" is equal to one of the items in the sequence, "noir".
Refer to the specification:
https://www.w3.org/TR/1999/REC-xpath-19991116/#booleans
NOTE: If $x is bound to a node-set, then $x="foo" does not mean the same as not($x!="foo"): the former is true if and only if some node in $x has the string-value foo; the latter is true if and only if all nodes in $x have the string-value foo.
Use:
where not($movie/styles/style=("noir","anthology"))
or:
where $movie/styles/style[not(.=("noir","anthology"))]

Resources