使用两个索引的MarkLogic光学查询没有返回结果

问题描述 投票:0回答:1

我想使用 MarkLogic optic API 来连接两个范围索引,但不知何故它们没有连接。是我写的查询错误还是我无法比较使用的索引?

我定义了两个索引:

  • 元素属性范围索引 x/@refid
  • 范围字段索引'id'

两者都是字符串类型,并且定义了相同的排序规则。这两个索引都有我可以使用 cts:values() 函数检索的数据。两者都是巨大的索引,我想使用光学连接它们,所以我构建了以下查询:

import module namespace op="http://marklogic.com/optic"
at "/MarkLogic/optic.xqy";

let $subfrag := op:fragment-id-col("subfrag") 
let $notfrag := op:fragment-id-col("notfrag") 

let $query :=
cts:and-query((
  cts:collection-query("latest")
))

let $subids := op:from-lexicons(
   map:entry("subid", cts:field-reference("id")), (), $subfrag) => op:where($query)

let $notids := op:from-lexicons(
   map:entry("notid", cts:element-attribute-reference(xs:QName("x"), xs:QName("refid"))),
   (),
       $notfrag)
    
return $subids
   => op:join-cross-product($notids)
   => op:where(op:eq($notfrag, $subfrag))
   => op:result() 

此查询使用连接叉积,当我删除 op:where 子句时,我会得到左右所有值。我验证了,有些是相等的,所以该子句应该只过滤我真正感兴趣的那些行。但不知何故它不起作用,我得到一个空结果。另外,如果我用字符串值替换 op:eq 中的值之一,它不会返回结果。

当我在 op:eq 运算符中使用相同的变量时(例如 op:eq($notfrag, $notfrag)),我会返回结果,因此该语句可以正常工作。只是不是两个指标之间的比较。

我还使用了 join-inner 和 left-outer-join 的变体,但它们也没有返回任何结果。

我是否比较了两个不可比较的索引,或者我是否遗漏了一些声明(因为文档/示例有点薄)。

(当然我可以不使用光学来解决,但在这种情况下它是完美的选择)

[更新]

我最终通过更改最终声明使其工作:

return $subids
=> op:join-cross-product($notids)
=> op:where(op:eq(op:col('subid'), op:col('notid')))
=> op:result() 

因此,您无法在条件中使用片段定义。之后,我用 join-inner 结构替换了 join-cross-product,这应该会更高效一些。

为了完整起见,我最初使用了此处找到的 MarkLogic 文档中的示例(https://docs.marklogic.com/guide/app-dev/OpticAPI#id_87356),特别是他们使用片段的最后一个示例列定义用作 join-inner 语句中的参数,但在我的情况下不起作用。

xquery marklogic marklogic-optic-api
1个回答
1
投票

叉积通常仅适用于小行集。

将两个引用放在同一个 from-lexicons() 访问器中会执行隐式联接,这意味着引擎通过构造为每个文档索引的值的本地叉积来形成行。

这样的查询可以表达为:

op:from-lexicons(
   map:entry("subid", cts:field-reference("id"))
   =>map:with("notid", cts:element-attribute-reference(xs:QName("x"),
     xs:QName("refid")))
=>op:where(cts:collection-query("latest"))
=>op:result() 

可以通过以下方式显式进行连接:

let $subids := op:from-lexicons(
   map:entry("subid", cts:field-reference("id")), (), $subfrag)
   => op:where($query)

let $notids := op:from-lexicons(
   map:entry("notid", cts:element-attribute-reference(xs:QName("x"),
       xs:QName("refid"))),
   (),
   $notfrag)

return $subids
   => op:join-inner($notids, op:on($notfrag, $subfrag))
   => op:result() 

希望有帮助,

© www.soinside.com 2019 - 2024. All rights reserved.