【问题标题】:Combining XPath and Search Queries结合 XPath 和搜索查询
【发布时间】:2019-06-03 11:57:25
【问题描述】:

要求:

cts/search 查询与 XPath 查询相结合。 XPath 是未知的用户输入字符串。

search:resolve 函数采用“一个 cts:query 对象、序列化的 cts:query 或结构化查询 (search:query)”。 (Source)

问题:

是否有将 XPath 转换为 cts 或结构化查询的 api,以便我可以结合 XPath 和其他搜索查询?

不工作的例子:

xquery version "1.0-ml";
let $doc := 
  <test>
    <name>Mike</name>
    <age>20</age>
  </test>
return xdmp:document-insert('mike.xml', $doc);

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

let $xpath := '/test[name="Mike"]'
let $cts-query := cts:and-query(
   xpathToCts($xpath), (: Somehow convert XPath to cts query here :)
   cts:element-value-query(xs:QName("age"), "20")
)

return search:resolve($cts-query)

如果目前没有办法将 XPath 字符串转换为search 兼容格式,有没有其他方法可以结合 XPath 和 cts/search 查询?

任何帮助将不胜感激!

更新 1

我尝试使用建议的searchable-expression 选项,但将它与extract-document-data 结合时遇到了另一个问题:

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

search:resolve(
  cts:element-value-query(xs:QName("name"), "Mike"),
  <options xmlns="http://marklogic.com/appservices/search">
    <searchable-expression>/test[age = 20]</searchable-expression>
    <extract-document-data>
      <extract-path>/test/name</extract-path>
    </extract-document-data>
  </options>
)

此查询确实返回以下提取的数据:

<search:extracted-none>
</search:extracted-none>

虽然没有可搜索的表达式,但我得到了预期:

<search:extracted kind="element">
   <name>Mike</name>
</search:extracted>

如果我没记错的话,searchable-expression 的行为与cts:search 的第一个参数相同。阅读它说的文档:

例如,如果指定 //p,则 p 匹配搜索的元素 返回条件。

因此,生成的节点仅限于可搜索表达式和下面的所有节点,这不是我想要的。

【问题讨论】:

    标签: marklogic


    【解决方案1】:

    您可以将该 XPath 传递到 &lt;search:options&gt; 中的 &lt;searchable-expression&gt; 元素中,它实际上将与您的 cts:query 进行“与”运算。在底层,所有 XPath 表达式都被转换为优化的查询计划,就像 cts:queries 一样(除了 XPath 表达式将始终被过滤以防止返回误报,而 cts 表达式的过滤是可选的)。

    但我应该指出,评估用户 XPath 是极其危险的,不加以检查是注入攻击的巨大漏洞。您应该验证或清理查询以防止这种情况和/或确保查询无法运行更新,即:/x/y/z[xdmp:directory-delete('/')]。查询顶部的类似内容是一个好的开始:declare option xdmp:update "false";

    【讨论】:

    • +1。最好的方法是避免 XPath 用于查询,原因有两个 Will 引用:XPath 的表达能力太强,无法保证转换为基于索引的高效、未过滤的查询,并且 XPath 难以清理以确保安全性。如果必须支持分层查询,最好使用层次结构的 JSON 或 XML 表示并转换为组合的 cts.jsonPropertyScope() 或 cts.elementQuery() 查询。
    • 我添加了一个更新,其中我参考了您的答案。可悲的是,我不能使用可搜索表达式,因为它将结果节点更改为可搜索表达式中给出的节点。因此,我正在进一步寻找一种将 XPath 查询转换为 cts/search 兼容格式的方法。不过感谢您的回答!
    • @WagnerMichael 是的,表达式选择 XPath 中表示的节点,但您可以修改其他 XPath 以适应更改,即&lt;extract-path&gt;/name&lt;/extract-path&gt; - 或者如果路径可能选择不同级别的节点, &lt;extract-path&gt;/ancestor-or-self::test/name&lt;/extract-path&gt;。一个内务记录 - 通常,将问题的内容更改这么多会更好地用作新问题。 Q&A 之间的所有变化和交流让未来的 SO 用户难以理解。
    • @wst 你说得对,我可以调整提取路径,但我可以看到其他限制。想象一下像/test/details[age=20] 这样的可搜索表达式(我将年龄移到那里的元素细节中)。现在名称的element-value-query 不再起作用,因为上下文在details 中。另一方面,可搜索表达式/test[details/age = 20] 仍然可以工作。所以这意味着我必须期望我的用户“不切换搜索上下文”,这作为最后的手段是可行的,但有点令人失望。希望这是有道理的。
    • @WagnerMichael 我认为您没有阅读我的完整评论。更改搜索上下文可以通过在您的提取表达式中使用ancestor-or-self:: XPath 轴来处理(并且该约束也可以重写为不更改上下文,即/test[details/age=20])。如果您强制 Search API 使用 &lt;search-option&gt;unfiltered&lt;/search-option&gt; 在文档/片段级别进行查询,则此方法有效。
    猜你喜欢
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    相关资源
    最近更新 更多