MarkLogic cts.search中的路径表达式

时间:2019-03-21 15:28:40

标签: marklogic

我的印象是MarkQuery中的XQuery和服务器端JavaScript API在很大程度上是等效的。但是cts:searchcts.search似乎有很大的不同。在cts:search中,我可以指定要搜索和返回的元素。例如,我可以从食谱书中检索使用肉桂粉作为成分的所有食谱:

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>

4 个答案:

答案 0 :(得分:5)

这样做有技术原因。 XQuery中的cts:search函数实际上不是函数,而是具有函数语法的特殊形式。这意味着第一个参数实际上没有得到评估,然后传递给函数(如果您考虑一下,那将是一种非常低效的处理方式!)。在Javascript中,cts.search函数是一个实函数。为了避免效率低下,我们删除了第一个参数,因此您需要从结果中拉出您所关心的部分。

如果要将结果集限制为元素recipe中的结果,请用cts:element-query(xs:QName("recipe"), $your-query)包裹查询

答案 1 :(得分:3)

这应该使您更近

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,..)

答案 2 :(得分:2)

鉴于cts:search()的javascript版本缺少xquery版本的第一个参数-我看不到它如何能返回文档节点以外的任何内容。 cts:search和cts.search使用的索引优化具有“片段”(通常是文档)的粒度-旨在查找可能无界集合中的少数匹配文档。从那里您需要遍历文档的结构。 XQuery尤其擅长于此-路径遍历是语言的本机,JavaScript并不是很多。

我建议您使用search.search而不是cts:search-它是一个高级API,旨在使此类任务更加轻松。

答案 3 :(得分:1)

基于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参数的方法。我可能已经错过了,因为我还没有使用过。

更多读数:

Query Options Reference search:search