MarkLogic cts:元素查询误报?

Posted

技术标签:

【中文标题】MarkLogic cts:元素查询误报?【英文标题】:MarkLogic cts:element-query false positives? 【发布时间】:2016-09-20 18:09:33 【问题描述】:

鉴于这份文件:-

<items>
  <item><type>T1</type><value>V1</value></item>
  <item><type>T2</type><value>V2</value></item>
</items>

不出所料,我发现这会拉回cts:uris() 中的页面:-

cts:and-query((
  cts:element-query(xs:QName('item'),
    cts:element-value-query(xs:QName('type'),'T1')
    ),
  cts:element-query(xs:QName('item'),
    cts:element-value-query(xs:QName('value'),'V2')
    )
  ))

但有点令人惊讶(至少对我来说)我也发现这也会:-

cts:element-query(xs:QName('item'),
  cts:and-query((
    cts:element-value-query(xs:QName('type'),'T1'),
    cts:element-value-query(xs:QName('value'),'V2')
    ))
  )

这似乎不对,因为没有单个项目具有 type=T1value=V2。 对我来说,这似乎是一个误报。

我是否误解了cts:element-query 的工作原理? (不得不说,这方面的文档不是特别清楚)。

或者这是 MarkLogic 努力为我提供预期结果的地方,如果我有更多或更好的索引,我得到误报匹配的可能性就会降低。

【问题讨论】:

【参考方案1】:

除了@wst 的回答,你只需要开启element value positions 就可以从未过滤的搜索中得到准确的结果。这里有一些代码来展示这一点:

xdmp:document-insert("/items.xml", <items>
  <item><type>T1</type><value>V1</value></item>
  <item><type>T2</type><value>V2</value></item>
</items>);

cts:search(collection(),
  cts:element-query(xs:QName('item'),
    cts:and-query((
      cts:element-value-query(xs:QName('type'),'T1'),
      cts:element-value-query(xs:QName('value'),'V2')
    ))
  ), 'unfiltered'
)

如果不启用element value positions,这将返回测试文档。启用职位后,查询不返回任何内容。

正如@wst 所说,cts:search() 默认运行过滤,而 cts:uris()(例如 xdmp:estimate() 仅运行未过滤。

HTH!

【讨论】:

这更符合我的预期。谢谢。【参考方案2】:

是的,我认为这是对查询工作原理的轻微误解。在cts:search 中,默认行为是启用filtered 选项。在这种情况下,ML 将仅使用索引来评估查询,然后一旦选择了候选文档,它就会将它们加载到内存中,检查并过滤掉误报。这更耗时,但更准确。

cts:uris 是一个词典函数,因此传递给它的查询只能通过索引解析,并且没有过滤误报的选项。

通过索引处理此查询的简单方法是更改​​架构,使文档基于&lt;item&gt; 而不是&lt;items&gt;。然后每个项目将有一个单独的索引条目,并且在过滤之前不会混合结果。

另一种不涉及更新文档的方法是将您希望在cts:near-query 中的同一元素中出现的查询包装起来。这将阻止一个&lt;item&gt; 中的&lt;type&gt; 与另一个&lt;item&gt; 中的&lt;value&gt; 匹配。我建议阅读文档,因为您可能需要为 cts:near-query 启用一个或多个基于位置的索引才能准确。

【讨论】:

我了解搜索和过滤器之间的区别,并且我确实有时会预料到误报,只是它们很少见。我所期望的是,两个 cts:element-value-query 在同一个 cts:element-query 中的事实意味着它们的匹配项必须在元素的同一个实例(命名项目)内,而不仅仅是在任何名为 item 的旧元素。语法确实表明我给出的两个示例意图不同。我不知道 cts:near-query 是否是一般情况下的答案,实际上事实类型和值可能相距甚远。 @AndyKey 在第一种情况下,这只会在过滤搜索中成立。索引的分辨率仅在文档级别。索引不会“看到”这些值在不同的项目中,只是它们对文档中的某些项目返回 true。通过启用位置索引并使用cts:near-query,您可以解决这个问题。 接受为答案。但是,检查类型和值是否存在于项目之下似乎很奇怪(而不是仅仅返回所有类型和值匹配的文档,而不管它们是否在项目之下),但没有检查匹配发生在 same 项下方。 @AndyKey 这是一种简化,但考虑索引原语的一种方法是作为键/值对,其中键是元素 QName,并且只要它与您的查询相关,则该项目不具有与其名称不同的身份。身份实际上只存在于文档/片段级别,这就是为什么它不区分同名元素的原因,即使对于像这样的嵌套查询也是如此。

以上是关于MarkLogic cts:元素查询误报?的主要内容,如果未能解决你的问题,请参考以下文章

MarkLogic:在 SPARQL 查询中使用聚合函数

Marklogic Json Xquery 无法查询

使用 XQuery 从查询控制台读取 MarkLogic 日志

如何避免 SQL 查询检查 IS NULL 的误报?

MarkLogic LDAP身份验证

MarkLogic 8 和服务器端 JavaScript - 调试支持