MarkLogic cts:element-查询误报?

MarkLogic cts:element-query false positives?

鉴于此文件 :-

<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 努力给我期望的结果,如果我有更多或更好的索引,我就不太可能得到错误的结果正匹配。

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

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

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

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

除了@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启用这个returns测试文件。启用仓位后,查询returns nothing.

如@wst 所述,cts:search() 默认情况下过滤运行,而 cts:uris()(例如 xdmp:estimate() 仅在未过滤的情况下运行。

HTH!