我的印象是MarkLogic中的XQuery和服务器端JavaScript API在很大程度上是等效的。但是cts:search
和cts.search
似乎有很大差异。在cts:search
中,我能够指定要搜索和返回的元素。例如,我可以使用cinnaomon作为食谱书中的成分来检索所有食谱:
cts:search(//recipe, cts:element-word-query(xs:QName('ingredients'), 'cinnamon'))
而cts.search
不接受路径表达式并将返回整个食谱书文档:
cts.search(cts.elementWordQuery(xs.QName('ingredients'), 'cinnamon'))
MarkLogic邮件列表中也提出了同样的问题,但我没有看到答案:https://developer.marklogic.com/pipermail/general/2015-March/016508.html
以下是一个最小的例子:
<book>
<recipe>
<ingredients>cinnamon, peppermint</ingredients>
<instruction/>
</recipe>
<recipe>
<ingredients>sugar, peppermint</ingredients>
<instruction/>
</recipe>
<recipe>
<ingredients>coconut oil</ingredients>
<instruction/>
</recipe>
</book>
xquery将是:
cts:search(//recipe, cts:element-word-query(xs:QName('ingredients'), 'cinnamon'))
和回应:
<recipe>
<ingredients>cinnamon, peppermint</ingredients>
<instruction></instruction>
</recipe>
建立在DALDEI的答案上,您可以使用搜索API来仅返回配方元素:
const search = require('/MarkLogic/appservices/search/search');
let options = fn.head(xdmp.unquote(`
<options xmlns="http://marklogic.com/appservices/search">
<return-results>true</return-results>
<searchable-expression>//recipe</searchable-expression>
<extract-document-data>all</extract-document-data>
<additional-query>
<cts:element-word-query xmlns:cts="http://marklogic.com/cts">
<cts:element>ingredients</cts:element>
<cts:text xml:lang="en">cinnamon</cts:text>
</cts:element-word-query>
</additional-query>
</options>`)).root;
search.search("", options) // returns a Sequence of search:response
.toArray()[0] // get the first result
.getElementsByTagName("recipe") // find all recipe elements
此代码返回配方元素的NodeList。您提供的书的结果将是此单个元素节点:
<recipe xmlns:search="http://marklogic.com/appservices/search">
<ingredients>cinnamon, peppermint</ingredients>
<instruction/>
</recipe>
这不是一个很好的解决方案(在快速和简单方面),但它可能作为一种解决方法。
我也尝试使用jsearch函数,但没有找到传递searchable-expression
参数的方法。我可能错过了,因为我还没有使用过这个。
进一步阅读:
有这样的技术原因。 XQuery中的cts:search
函数实际上不是函数,而是具有函数语法的特殊形式。这意味着第一个参数实际上没有被评估,然后传递给函数(如果你考虑它,这将是一个非常低效的方法继续!)。在Javascript中,cts.search
函数是一个真正的函数。为了避免效率低下,我们删除了第一个参数,因此您需要从结果中拉出您关心的部分。
如果要将结果集约束到元素recipe
中的结果集,请使用cts:element-query(xs:QName("recipe"), $your-query)
包装查询
这应该让你更接近
https://docs.marklogic.com/cts.elementQuery
根据需要应用cts.andQuery。
JS和XQuery接口在功能上是等价的,但是有一些地方(这是一个)语言本身不直接支持等价。另一个是XQuery序列,它在JS中没有本机等价物 - 所以通过额外的JS类提供。
任何cts(复杂)查询都可以用原始cts查询对象/方法构造。 XQuery cts :: search()中的第一个参数是“可搜索表达式” - 它与约束范围基本相同 - 可以与cts.andQuery结合使用以产生相同的效果(在XQuery和JS中)。根据您在XQuery中使用的确切表达式,您需要为JS(或xquery)找到它的等效cts.query。
因此cts.elementQuery类似于cts :: search(// element-name,..)
鉴于cts:search()的javascript版本缺少xquery的版本'第一个参数 - 我没有看到它如何返回除文档节点之外的任何内容。 cts:search和cts.search使用的索引优化具有“片段”(通常是文档)的粒度 - 旨在查找可能无界集的少数匹配文档。从那里你需要遍历文档的结构。 XQuery在这方面特别擅长 - 路径遍历本身就是语言,而不是JavaScript。
我建议你使用search.search而不是cts:search - 它是一个更高级别的API,旨在使这样的任务更容易。