MarkLogic: binding cts:search expression to a variable

558 views Asked by At

In MarkLogic, is it possible to bind a cts:search expression to a variable and then use that variable elsewhere in the XQuery?

I want to do something like this:

let $query := cts:search(doc(),
                               cts:and-query((
                                  cts:element-attribute-word-query(
                                    xs:QName("para"),
                                    xs:QName("role"),
                                      "intro") ,

                                  cts:element-attribute-word-query(
                                    xs:QName("title"),
                                    xs:QName("role"),
                                      "inline")
                                       ))
                                     )


let $number-of-results := xdmp:estimate($query)

return $number of results

But, I'm not sure how to pass the expression itself, rather than what it returns.

3

There are 3 answers

0
grtjn On BEST ANSWER

XQuery 3 support in MarkLogic might help with this, but otherwise no. You can put the cts:query part in $query like this though:

let $query := cts:and-query((
                              cts:element-attribute-word-query(
                                xs:QName("para"),
                                xs:QName("role"),
                                  "intro") ,

                              cts:element-attribute-word-query(
                                xs:QName("title"),
                                xs:QName("role"),
                                  "inline")
                                   ))

let $number-of-results := xdmp:estimate(cts:search(doc(), $query))
let $results := cts:search(doc(), $query)

return $number-of-results

HTH!

0
mblakele On

Geert's answer is correct and practical: reuse the cts:query item, not the database access expression. Use the cts:query to query the database as needed.

But in some cases it can be useful to "pass the expression itself" as in the original question. That might seem difficult because XQuery 1.0 doesn't really allow for metaprogramming. Variable bind to sequences of items, which are the result of evaluating expressions. Variables don't bind to unevaluated expressions.

MarkLogic offers a way around this, using functions like http://docs.marklogic.com/xdmp:path or http://docs.marklogic.com/xdmp:value or http://docs.marklogic.com/xdmp:eval for generic expression evaluation. In most cases it's better to bind the cts:query instead, as in Geert's answer. But if you really need metaprogramming, you can build expressions as strings and evaluated them on demand.

let $query := 'cts:search(doc(),
                           cts:and-query((
                              cts:element-attribute-word-query(
                                xs:QName("para"),
                                xs:QName("role"),
                                  "intro") ,

                              cts:element-attribute-word-query(
                                xs:QName("title"),
                                xs:QName("role"),
                                  "inline")
                                   ))
                                 )'
return xdmp:value('xdmp:estimate('||$query||')')
0
hunterhacker On

In the general case you can do exactly what you want, it's just that xdmp:estimate() is a special case that requires an inline searchable expression and not a variable to a searchable expression. That's why xdmp:estimate(cts:search(doc(), $query)) works.