在 MarkLogic 中将 XQuery 搜索 API 存储桶生成转换为 JSearch

Convert XQuery Search API bucket generation to JSearch in MarkLogic

我想 "convert" 我的一个旧 XQuery 示例,它使用 bucket(分桶搜索)到 JSearch:

import module namespace search = 
  "http://marklogic.com/appservices/search"
  at "/MarkLogic/appservices/search/search.xqy";

declare variable $options := <options xmlns="http://marklogic.com/appservices/search">
  <constraint name="height">
    <range type="xs:double" facet="true">
      <bucket ge="1.9" name="supertall">1.90m + </bucket>
      <bucket lt="1.9" ge="1.7" name="tall">1.70m - 1.90m</bucket>
      <bucket lt="1.7" ge="1.2" name="normalish">1.20m - 1.70m</bucket>
      <bucket lt="1.2" name="short">0m - 1.20m</bucket>
      <facet-option>limit=20</facet-option>
      <json-property>height</json-property>
    </range>
  </constraint>
</options>;

let $results := search:search("height:short", $options)
for $facet in $results/search:facet
return $results;

上面允许定义桶,也允许使用 'height' 作为搜索语法的一部分,这意味着像 search:search('height:short') 这样的搜索也能正常工作。

不幸的是我无法使用 JSearch 版本,这是我尝试过的:

var jsearch = require('/MarkLogic/jsearch');
jsearch.documents(
  jsearch.facet('Height', 'height').groupInto([
    jsearch.bucketName('short'), 1.60,
    jsearch.bucketName('normal'), 1.90,
    jsearch.bucketName('tall'), 4.00
  ]))
.where(cts.parse('height:short'))
.result();

以上代码returns:

{ "results":空, "estimate": 0 }

我也尝试添加对 JSON 属性 'height' 的引用,但这也没有用:

var jsearch = require('/MarkLogic/jsearch');
var reference = { height: cts.jsonPropertyReference('height') };
jsearch.documents(
  jsearch.facet('Height', 'height').groupInto([
    jsearch.bucketName('short'), 1.60,
    jsearch.bucketName('normal'), 1.90,
    jsearch.bucketName('tall'), 4.00
  ]))
.where(cts.parse('height:short', reference))
.result();

然而,当我删除 .where() 约束时,我的存储桶生成得很好。有什么建议吗?

我相信我已经找到了解决办法。高度的值是数字,在我的 JSearch 查询中,我试图将字符串 'short' 与这些数字相匹配。为了克服这个问题,我不得不使用此页面上记录的回调函数 http://docs.marklogic.com/cts.parse

基本上解决方案是使用一组 cts 查询构造函数(cts.andQuery 和 cts.jsonPropertyRangeQuery)创建我自己的查询。解决方案现在看起来像这样:

var jsearch = require('/MarkLogic/jsearch');

var short = 1.60;
var normal = 1.80;
var tall = 1.90;

var refCallback = function(operator, values, options) {
  if (values === 'short') {
    return  cts.jsonPropertyRangeQuery('height', '<=', short)
  } else if (values === 'normal') {
    return cts.andQuery([
      cts.jsonPropertyRangeQuery('height', '>=', normal),
      cts.jsonPropertyRangeQuery('height', '<', tall)
    ])
  } else {
    return cts.jsonPropertyRangeQuery('height', '>=', tall)
  }
};
var reference = { height: refCallback };

jsearch.documents(
  jsearch.facet('height').groupInto([
    jsearch.bucketName('short'), short,
    jsearch.bucketName('normal'), normal,
    jsearch.bucketName('tall'), tall
  ]))
.where(cts.parse('height:tall', reference))
.result();

请注意,我还必须外部化变量声明,因为现在我可以在存储桶定义和回调函数中重用它们。