I am getting an invalid map error when trying to get the percentage of a record based on a certain condition to the total count of another record.
Can you please help to identify the issue here in my code.
The below code is trying to get the percentage of the count of all 6 months old AncillaryQuote price to the total no of Shipments References when the Ancillary quote price is greater than 0 . I am taking Booking Date to calculate the 6 months old date range.
Here is my optic query which I am trying -
xquery version "1.0-ml";
import module namespace op="http://marklogic.com/optic" at "/MarkLogic/optic.xqy";
import module namespace ofn="http://marklogic.com/optic/expression/fn" at "/MarkLogic/optic/optic-fn.xqy";
import module namespace osql="http://marklogic.com/optic/expression/sql" at "/MarkLogic/optic/optic-sql.xqy";
declare option xdmp:mapping "false";
let $view := op:from-view("GTM2_Shipment", "Shipment_View")
let $Var1 := op:view-col("Shipment_View", "Ancillary_QuotePrice")
let $Var2 := op:view-col("Shipment_View", "Shipment_Ref")
let $Var3 := op:view-col("Shipment_View", "BookingCreateDt")
return $view
=> op:group-by("transMode",(op:count("Var2", $Var2),op:count("Var1", $Var1)))
=> op:where(op:and((
op:gt($Var1, 0),op:gt(ofn:format-dateTime($Var3, '[Y0001]-[M01]-[D01]'),osql:dateadd('month',-6, ofn:format-dateTime(fn:current-dateTime(),'[Y0001]-[M01]-[D01]')))
))
)
=>op:select(op:as("multiply", op:divide(op:col("Var1"), op:col("Var2"))))
=>op:select($Var3,op:as("percentage", op:multiply(100, op:col("multiply"))))
=> op:result()
Here is the error I am getting -
[1.0-ml] XDMP-AS: (err:XPTY0004) $qualifier as xs:string? -- Invalid coercion: map:map(<map:map xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" .../>) as xs:string
Stack Trace
In /MarkLogic/optic.xqy on line 685
In xdmp:eval("xquery version "1.0-ml";
import module namespace o...", (), <options xmlns="xdmp:eval"><database>16857865358322067141</database>...</options>)
In xdmp:eval("xquery version "1.0-ml";
import module namespace o...", (), <options xmlns="xdmp:eval"><database>16857865358322067141</database>...</options>)
The error is telling you that the $qualifier parameter is a map and cannot be converted to xs:string.
If you look at the signature of the op:select function:
op:select(
$plan as map:map,
$columns as columnIdentifier*,
[$qualifier as xs:string?]
) as map:map
You will see that $qualifier is the third parameter.
When using the =>, the plan is being set as the first parameter for you. The columns for the op:select() are the second parameter. However, you need to provide those columns as a sequence (wrap with ()). Otherwise, it appears that you are specifying $Var3 as the columns to select, and then the percentage column as the $qualifier.
Change:
=> op:select($Var3, op:as("percentage", op:multiply(100, op:col("multiply"))))
to:
=> op:select( ($Var3,op:as("percentage", op:multiply(100, op:col("multiply")))) )
Related
I am trying to declare the column in a variable and want to call that variable inside my program.
Here is my optic query code which returns me - Column not found.
Please help to understand the problem in my query.
xquery version "1.0-ml";
import module namespace op="http://marklogic.com/optic" at "/MarkLogic/optic.xqy";
import module namespace ofn="http://marklogic.com/optic/expression/fn" at "/MarkLogic/optic/optic-fn.xqy";
import module namespace osql="http://marklogic.com/optic/expression/sql" at "/MarkLogic/optic/optic-sql.xqy";
declare option xdmp:mapping "false";
let $view := op:from-view("GTM2_Shipment", "Shipment_View")
let $count := op:view-col("Shipment_View", "Ancillary_QuotePrice")
return $view
=> op:where(op:and((
op:gt(op:col("$count"), 0)
))
)
=> op:group-by("transMode", op:count("QuotePrice", "$count"))
=> op:result()
here is the result I get -
[1.0-ml] SQL-NOCOLUMN: Column not found: $count
Stack Trace
At line 1 column 2:
In sem:execute(plan:sparql(" * { sample(transMode) AS transMode) count($count) AS QuotePrice) { FILTER ($count gt xs:integer("0") and fn:format-dateTime(xs:dateTime(BookingCreateDt), xs:string("[Y0001]-[M01]-[D01]")) gt sql:dateadd(xs:string("month"), xs:int("-6"), fn:format-dateTime(xs:dateTime("2022-06-30T10:42:50.2654743+01:00"), xs:string("[Y0001]-[M01]-[D01]")))) } GROUP BY transMode }"), (), ()
I have also tried to declare the column like this-
let $count := op:col("Ancillary_QuotePrice")
And it doesnot recognize the column from the view and gives the same error.
Once $count is defined as an op:view-col(), then just use it as a variable. See suggestions below:
op:gt(op:col("$count"), 0) ---change to--> op:gt($count, 0)
op:count("QuotePrice", "$count") ---change to--> op:count("QuotePrice", $count)
I am trying to find the percentage of a certain record based on a condition to the total no of that record . I am using optic query to get the result.
To be specific on the requirement :
Give a percentage of a certain record, when there is a condition, with the total number of that record available in the template view.
Here is my optic query which I am trying -
xquery version "1.0-ml";
import module namespace op="http://marklogic.com/optic" at "/MarkLogic/optic.xqy";
import module namespace ofn="http://marklogic.com/optic/expression/fn" at "/MarkLogic/optic/optic-fn.xqy";
import module namespace osql="http://marklogic.com/optic/expression/sql" at "/MarkLogic/optic/optic-sql.xqy";
declare option xdmp:mapping "false";
let $view := op:from-view("GTM2_Shipment", "Shipment_View")
let $Ancillary_QuotePrice := op:view-col("Shipment_View", "Ancillary_QuotePrice")
return $view
=> op:group-by((),(op:count("TotcountOfColumn", $Ancillary_QuotePrice),op:count("percentageCount", $Ancillary_QuotePrice)))
=> op:select(
op:as("CountOnCond", op:where(op:and((
op:gt($Ancillary_QuotePrice, 0),op:gt(ofn:format-dateTime(op:col('BookingCreateDt'), '[Y0001]-[M01]-[D01]'),osql:dateadd('month',-6, ofn:format-dateTime(fn:current-dateTime(),'[Y0001]-[M01]-[D01]')))
))
)
),
op:as("Percentage",op:divide(op:col("CountOnCond"),op:col("TotcountOfColumn")))
)
=> op:result()
It gives me this error -
1.0-ml] XDMP-TOOFEWARGS: (err:XPST0017) op:where(op:and((op:gt($countOfColumn, 0), op:gt(ofn:format-dateTime(op:col("BookingCreateDt"), "[Y0001]-[M01]-[D01]"), osql:dateadd("month", -6, ofn:format-dateTime(fn:current-dateTime(), "[Y0001]-[M01]-[D01]")))))) -- Too few args, expected 2 but got 1
Also please check if my query logic is correct or not.
xquery version "1.0-ml";
import module namespace op="http://marklogic.com/optic" at "/MarkLogic/optic.xqy";
import module namespace ofn="http://marklogic.com/optic/expression/fn" at "/MarkLogic/optic/optic-fn.xqy";
import module namespace osql="http://marklogic.com/optic/expression/sql" at "/MarkLogic/optic/optic-sql.xqy";
declare option xdmp:mapping "false";
let $view := op:from-view("GTM2_Shipment", "Shipment_View")
let $Var1 := op:view-col("Shipment_View", "Ancillary_QuotePrice")
let $Var2 := op:view-col("Shipment_View", "Shipment_Ref")
return $view
=> op:group-by((),(op:count("Var2", $Var2),op:count("Var1", $Var1)))
=>op:select(op:as("multiply", op:divide(op:col("Var1"), op:col("Var2"))))
=>op:select(op:as("percentageFinal", op:multiply(100, op:col("multiply"))))
=> op:result()
Above is the straightforward percentage found for Var1 with total of Var2.
I want the condition of the Var1 to be added in the code. Where can I add the where condition please.
op:where() expect the first parameter to be the $plan. Typically, when chaining calls from a plan using => it is set as that first parameter for you, and you are then providing the subsequent parameters starting from the second parameter with what is explicitly set in the function call.
So, when attempting to apply op:where() as the expression for op:as() to bind to:
op:as("CountOnCond", op:where(op:and((
op:gt($Ancillary_QuotePrice, 0),op:gt(ofn:format-dateTime(op:col('BookingCreateDt'), '[Y0001]-[M01]-[D01]'),osql:dateadd('month',-6, ofn:format-dateTime(fn:current-dateTime(),'[Y0001]-[M01]-[D01]')))
))
)
the op:and() parameter being specified is the one and only parameter being specified, but op:where() has two required parameters.
That is why it throws the XDMP-TOOFEWARGS error.
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 ... :)
};
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!
I have the following module
xquery version "1.0-ml";
declare variable $datasets as map:map external;
...
I want to call this so I do an xdmp:invoke like this
...
let $update := xdmp:invoke("/app/lib/my-module.xqy", (xs:QName("datasets"), $map), <options xmlns="xdmp:eval">
<modules>{xdmp:modules-database()}</modules>
</options>)
...
$map is of type map:map.
Running this gives me the following error
[1.0-ml] XDMP-ARG: xdmp:invoke("/app/lib/20140527-0916-copy-y-axis-labels-from-chart-to-dataset-...", fn:QName("", "datasets"), <options xmlns="xdmp:eval"><modules>0</modules></options>) -- Invalid argument
Why is that?
It's hard to know for sure from the limited code samples you've posted, but I think that your $map variable is bound to the empty sequence (the rough analogue of null in XPath/XQuery).
I've created the following main module, that simply returns the external variable $datasets:
xquery version "1.0-ml";
declare variable $datasets as map:map external;
$datasets
Invoking it as follows works correctly:
let $map := map:entry("key", "value")
return
xdmp:invoke("/test.xqy",
(xs:QName("datasets"), $map),
<options xmlns="xdmp:eval">
<modules>{xdmp:modules-database()}</modules>
</options>)
This results in the "invalid argument" error:
let $map := ()
return
xdmp:invoke("/test.xqy",
(xs:QName("datasets"), $map),
<options xmlns="xdmp:eval">
<modules>{xdmp:modules-database()}</modules>
</options>)
XQuery flattens sequences (they don't nest like s-expressions), so when $map is the empty sequence, the <options/> element becomes the value of the $datasets param, which is an invalid value for the external variable.
Update: Doh! #mblakele's comments below explain the error conditions ...
TL;DR: () is not an instance of map:map.