使用StructuredQueryBuilder指定动态排序顺序

时间:2015-07-01 13:19:20

标签: java marklogic

将MarkLogic 7与Java Client API一起使用时,我目前正在将查询定义从StringQueryDefinition移动到StructuredQueryDefinition,从而允许我以编程方式构造和操作查询。

使用字符串查询,我能够成功使用带有sort:{my-sort-order}的排序运算符,而后者又引用查询选项(https://docs.marklogic.com/guide/search-dev/query-options#id_30002)中指定的预定义顺序的名称,但找不到API docs一个相关的方法,允许我使用结构化查询构建器指定排序顺序。

使用StructuredQueryDefinition时如何指定排序顺序的推荐方法是什么?

更新 根据Erik的建议,这就是代码片段目前的样子,但它并没有解决问题,因为operator-state必须作为query元素的子代。而不是search元素上的孩子:

    RawStructuredQueryDefinition queryDef = qb.build(qb.and(qb.term(..), qb.rangeConstraint(...)));
    String sorting = "<operator-state><operator-name>sort</operator-name><state-name>" + orderBy + "</state-name></operator-state>";
    String combi = "<search xmlns='http://marklogic.com/appservices/search'>" + queryDef.toString() + sorting + "</search>";
    RawCombinedQueryDefinition combinedQueryDef = queryManager.newRawCombinedQueryDefinition(new StringHandle(combi), OPTIONS);
    // DOES NOT WORK, but will lead to MarkLogicIOException "Could not construct search results: parser error"
    // Possible solution is to modify the queryDef DOM your own

5 个答案:

答案 0 :(得分:2)

我们使用了发送到服务器的<options>元素的<search>标记。 这需要一个丑陋的字符串连接,但除了sort属性上的索引之外,它不需要任何服务器端。

有关XML的格式,请参阅此链接或search.xsd: http://docs.marklogic.com/guide/rest-dev/appendixb#id_33716

我们的想法是生成类似这样的XML:

<search xmlns='http://marklogic.com/appservices/search'>
  <query xmlns="http://marklogic.com/appservices/search">
    <collection-query>
      <uri>a_collection</uri>
    </collection-query>
  </query>
  <options>
    <sort-order type="xs:dateTime" direction="descending">
      <json-property>a_field</json-property>
    </sort-order>
  </options>
</search>

我们这样做了:

  1. 首先,构建StructuredQueryDefinition

    StructuredQueryDefinition queryDef = sb.collection("my_collection);
    
  2. 构建上面显示的<options>元素

    String xmlSortNode =
            "  <options>" +
            "    <sort-order type=\"xs:dateTime\" direction=\"descending\">" +
            "      <json-property>a_field</json-property>" +
            "    </sort-order>" +
            "  </options>";
    
  3. 构建完整的search元素

    String searchXml="<search xmlns='http://marklogic.com/appservices/search'>"
      + queryDef.serialize()
      + xmlSortNode
      + "</search>";
    
  4. 执行查询

    queryManager.newRawCombinedQueryDefinition(new StringHandle(searchXml),"all");
    

答案 1 :(得分:1)

目前,StructuredQueryBuilder仅构建标准。您必须使用排序顺序引用持久查询选项,或者使用条件和选项发送组合搜索。

答案 2 :(得分:1)

我们正在跟踪此on GitHub。请随时在那里添加信息。

答案 3 :(得分:1)

这是我最终得到的解决方案,基本上我使用编程方式构建一个StructuredQueryBuilder的查询,然后注入operator-state,在我的选项中引用预定义的排序顺序( OPTIONS_ALL):

org.jdom2.Document doc = new SAXBuilder().build(new StringReader(queryDef.serialize()));
if (!StringUtils.isEmpty(orderBy)) {
    Element operatorState = new Element("operator-state", NAMESPACE_SEARCH);
    operatorState.addContent(new Element("operator-name", NAMESPACE_SEARCH).setText("sort"));
    operatorState.addContent(new Element("state-name", NAMESPACE_SEARCH).setText(orderBy));
    doc.getRootElement().addContent(operatorState);
}
RawStructuredQueryDefinition rawQueryDef =
                queryManager.newRawStructuredQueryDefinition(new JDOMHandle(doc), OPTIONS_ALL);
// ~~
SearchHandle resultsHandle = new SearchHandle();
queryManager.search(rawQueryDef, resultsHandle, start);

使用

public static final Namespace NAMESPACE_SEARCH = Namespace.getNamespace("http://marklogic.com/appservices/search");

答案 4 :(得分:0)

排序顺序被视为运营商。看看operator-state,您将在结构化查询中找到排序示例。