I have written this code in the scheduled task XQuery -
xquery version "1.0-ml";
declare namespace grp = "http://marklogic.com/xdmp/group";
declare namespace c = 'http://iddn.icis.com/ns/core';
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";
declare variable $task-file-path := "/var/tmp/Projects/update-malformed-ids-task.xqy";
declare variable $string-starting-with-new-line-pattern := "
*";
declare variable $string-starting-with-space-pattern := " *";
declare variable $LIVE-ASSET-COLLECTION := "live-collection";
declare variable $batch-size := 100;
declare function local:is-migration-needed()
{
(
fn:exists(cts:element-value-match(xs:QName("c:id"), $string-starting-with-space-pattern, (), cts:collection-query($LIVE-ASSET-COLLECTION))) or
fn:exists(cts:element-value-match(xs:QName("c:id"), $string-starting-with-new-line-pattern, (), cts:collection-query($LIVE-ASSET-COLLECTION)))
)
};
declare function local:migrate()
{
if(local:is-migration-needed())
then (: do task here :)
else ()
}
local:migrate()
But this code is not working in scheduled task. The error which is logged in error logs says XDMP-ARG: cts:element-value-match(xs:QName("c:id"), " *", (), cts:collection-query("live-collection")) -- arg2 is invalid
I tried the same query on QConsole. It is working fine. I also tried using xdmp:spawn on the same file which also worked fine.
I also tried firing the simple cts:element-value-match without any pattern or wildcards. Looks like cts:element-value-match is not supported in scheduled tasks.
Is there something else need to be done to run this code from a scheduled task?
It seems like cts:element-value-match doesn't work in the scheduled tasks of MarkLogic. I did the desired task using cts:element-word-query instead.
Now the updated code in the task file, which worked for me, looks like -
xquery version "1.0-ml";
declare namespace grp = "http://marklogic.com/xdmp/group";
declare namespace c = 'http://iddn.icis.com/ns/core';
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";
declare variable $task-file-path := "/var/tmp/Projects/update-malformed-ids-task.xqy";
declare variable $string-pattern-for-new-line-and-space as xs:string* := (" *","
*");
declare variable $LIVE-ASSET-COLLECTION := "live-collection";
declare function local:is-migration-needed()
{
fn:count(cts:search(
fn:collection($LIVE-ASSET-COLLECTION),
cts:element-word-query(
xs:QName("c:id"),
$string-pattern-for-new-line-and-space,
("whitespace-sensitive", "wildcarded")
)
))>0
};
declare function local:migrate()
{
if(local:is-migration-needed())
then (: do task here :)
else ()
}
local:migrate()
Related
I'm using baseX in a REST environment and I'm quite stuck trying to run an .xq script with an undefined number of GET variables (could be 1 but could be 10)
I'd like to make my xq script generic about that and construct my query independently.
Is there a way to achieve that, playing with array or sending differently my variables, or I dunno how ?
here is my API call
http://basex:8984/rest/?run=WEB-INF/data/test.xq&$tag=p&value=sciences&tag2=p&value2=test&tag3=testdzq
here is my text.xq
declare variable $tag external;
declare variable $value external;
declare variable $tag2 external;
declare variable $value2 external;
<documents>
{for $doc in collection("testdb2")
where $doc//*[name() eq $tag]/text()[matches(., $value )]
and $doc//*[name() eq $tag2]/text()[matches(., $value2 )]
return <doc>{$doc//titleStmt/title/text()}</doc>
}
</documents>
Thanks !
found this here (see http-params function) https://www.balisage.net/Proceedings/vol18/print/Murray01/BalisageVol18-Murray01.html
(: BaseX example :)
(: In the controller ... :)
module namespace c = "http://balisage.net/ns/Bal2016murr0319/controller";
import module namespace request = "http://exquery.org/ns/request";
import module namespace item = "http://balisage.net/ns/Bal2016murr0319/views/item" at "views/item.xqm";
(:~ Returns a map containing the HTTP request parameters. :)
declare function c:http-params()
as map(*)
{
map:merge(
for $name in request:parameter-names()
let $value := request:parameter($name)
return map:entry($name, $value)
)
};
(:~ Calls the appropriate view, based on user input. :)
declare function c:get-view()
as element(html)
{
(: get HTTP request parameters :)
let $params := c:http-params()
return
if (map:get($params, "id")) then
(: the presence of "id" indicates that the user is requesting the item-level page for this unique identifier :)
(: call the item-level view :)
item:get-html($params)
else if ... (: call some other view :)
else if ... (: call some other view :)
else (: call the view for the home page ... :)
};
How to call a custom xquery function in exist-db using the REST API ?
Is it possible to have more than 1 function in the xquery file ?
declare function local:toto() as node() {
return doc("/db/ProjetXML/alice.xml")/raweb/identification/projectName)
};
declare function local:pomme() as node() {
return doc("/db/ProjetXML/carmen.xml")/raweb/identification/projectSize);
};
If I call it using :
http://localhost:8080/exist/rest/db/ProjetXML/orange.xqy?_query=local:toto()
I get the following error :
err:XPST0017 Call to undeclared function: local:toto [at line 1, column 1, source: local:toto()]
Your help is appreciated.
You have syntax errors in your XQuery:
You have two functions named local:toto(). Each function must have a distinct name.
There is no semicolon following the function definition, i.e. } should be };.
Also you should remove the return expression, as there is no preceding binding.
Another option would be to parameterize the input file, e.g.:
import module namespace request="http://exist-db.org/xquery/request";
declare function local:toto($name as xs:string) as node() {
let $doc :=
if($name eq "carmen")then
doc("/db/ProjetXML/carmen.xml")
else
doc("/db/ProjetXML/alice.xml")
return
$doc/raweb/identification/projectName);
};
local:toto(request:get-parameter("name", "alice"))
You can then call this via the REST Server using a URL like:
http://localhost:8080/exist/rest/db/ProjetXML/orange.xqy?name=carmen
I have the following query, where i want to form a string of values from a list and i want to use that comma separated string as an or-query but it does not give any result, however when i return just the concatenated string it gives the exact value needed for the query.
The query is as follows:
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
declare variable $docURI as xs:string external ;
declare variable $orQuery as xs:string external ;
let $tags :=
<tags>
<tag>"credit"</tag>
<tag>"bank"</tag>
<tag>"private banking"</tag>
</tags>
let $docURI := "/2012-10-22_CSGN.VX_(Citi)_Credit_Suisse_(CSGN.VX)__Model_Update.61198869.xml"
let $orQuery := (string-join($tags/tag, ','))
for $x in cts:search(doc($docURI)/doc/Content/Section/Paragraph, cts:or-query(($orQuery)))
let $r := cts:highlight($x, cts:or-query($orQuery), <b>{$cts:text}</b>)
return <result>{$r}</result>
The exact query that i want to run is :
cts:search(doc($docURI)/doc/Content/Section/Paragraph, cts:or-query(("credit","bank","private banking")))
and when i do
return (string-join($tags/tag, ','))
it gives me exactly what i require
"credit","bank","private banking"
But why does it not return any result in or-query?
The string-join step should not need to be string-join. That passes in a literal string. In xQuery, sequences are your friend.
I think you want to do something like this:
let $tags-to-search := ($tags/tag/text()!replace(., '^"|"$', '') ) (: a sequence of tags :)
cts:search(doc($docURI)/doc/Content/Section/Paragraph, cts:word-query($tags-to-search))
cts:word-query is the default query used for parameter 2 of search if you pass in a string. cts:word query also returns matches for any items in a sequence if presented with that.
https://docs.marklogic.com/cts:word-query
EDIT: Added the replace step for the quotes as suggested by Abel. This is specific to the data as presented by the original question. The overall approach remains the same.
Maybe do you need something like this
let $orQuery := for $tag in $tags/tag return cts:word-query($tag)
I used fn:tokenize instead it worked perfectly for my usecase
its because i was trying to pass these arguments from java using XCC api and it would not return anything with string values
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
declare variable $docURI as xs:string external ;
declare variable $orQuery as xs:string external ;
let $input := "credit,bank"
let $tokens := fn:tokenize($input, ",")
let $docURI := "2012-11-19 0005.HK (Citi) HSBC Holdings Plc (0005.HK)_ Model Update.61503613.pdf"
for $x in cts:search(fn:doc($docURI), cts:or-query(($tokens)))
let $r := cts:highlight($x, cts:or-query(($tokens)), <b>{$cts:text}</b>)
return <result>{$r}</result>
I have been trying to insert triples in Marklogic using this query
xquery version "1.0-ml";
import module namespace sem = "http://marklogic.com/semantics"
at "/MarkLogic/semantics.xqy";
declare variable $TRIPLE as xs:string external ;
declare variable $GRAPHNAME as xs:string external ;
let $TRIPLE:="sem:triple(sem:iri('http://smartlogic.com/document#testForTriples.xml'),sem:iri('http://www.smartlogic.com/schemas/docinfo.rdf#type'),'document')"
let $GRAPHNAME :="sem:iri('testGraph')"
let $r :=
sem:graph-insert($GRAPHNAME, $TRIPLE)
return <result>{$r}</result>
Unfortunately, that returns a coercion error:
XDMP-AS: (err:XPTY0004) $graphname as sem:iri -- Invalid coercion: "sem:iri('testGraph')" as sem:iri
What am I doing wrong?
You should not put quotes around sem:triple and sem:iri, they are type cast functions:
xquery version "1.0-ml";
import module namespace sem = "http://marklogic.com/semantics"
at "/MarkLogic/semantics.xqy";
let $TRIPLE := sem:triple(sem:iri('http://smartlogic.com/document#testForTriples.xml'),sem:iri('http://www.smartlogic.com/schemas/docinfo.rdf#type'),'document')
let $GRAPHNAME := sem:iri('testGraph')
let $r := sem:graph-insert($GRAPHNAME, $TRIPLE)
return <result>{$r}</result>
If you are trying to create the triples dynamically, pass through a sem:triple or sem:iri objects from external, or pass through the string values, and cast them inside the code.
HTH!
Is is-node-in-sequence-deep-equal in XQuery? I'm wondering because I've seen the function at xqueryfunctions.com, but I'm not being able to use it.
That function is part of the FunctX XQuery library. There are two methods to use this function:
You download the whole library (select the download which corresponds to your version of XQuery), save it in the same directory as your XQuery program/file and then import the module in your XQuery file, e.g.:
import module namespace functx = "http://www.functx.com" at "functx-1.0-doc-2007-01.xq";
(: Insert your code here and call the is-node-in-sequence-deep-equal function as seen below :)
functx:is-node-in-sequence-deep-equal($node, $seq)
Instead of downloading the whole library with all functions you can also simply copy paste the specific function which you need as shown on the page you linked to:
declare namespace functx = "http://www.functx.com";
declare function functx:is-node-in-sequence-deep-equal
( $node as node()? ,
$seq as node()* ) as xs:boolean {
some $nodeInSeq in $seq satisfies deep-equal($nodeInSeq,$node)
} ;
(: Insert your code here and call the 'is-node-in-sequence-deep-equal' function as seen below :)
functx:is-node-in-sequence-deep-equal($node, $seq)
In both examples you simply replace $node and $seq with your variables.