更新:
我应该注意到您的示例无效 XQuery:return element root { $i, $j }
将是有效的。此外,您不应该使用/text()
节点选择器,因为它的行为可能违反直觉。您可以直接在 XPath 谓词 ( [enrolleIndividualId/id eq $i/individual/id]
) 中比较元素。如果您需要将元素的内容作为字符串,请使用/fn:string()
代替。在直接比较单个元素时,/text()
我还建议使用原子相等运算符eq
代替序列相等运算符。=
原答案:
在 MarkLogic 中实现联接有多种方法,但我首先要质疑您的数据模型。从示例查询中的元素名称来看,您似乎正在使用关系模型 ( individuals
have memberships
)。MarkLogic 是一个文档数据库,它针对非规范化文档进行了优化。您将更好地处理您的数据并生成individual
每个包含相关membership
数据的新文档。
话虽如此,以下是加入文档的方法:
首先,您将需要范围索引来编写高性能连接。如果id
您的示例查询中的元素对个人来说不是唯一的,您将需要在 和 上的路径范围索引enrolledIndividualId/id
,individual/id
否则,一个简单的元素范围索引就可以了id
。
MarkLogic 中最常见的连接模式使用“shotgun-OR”查询;首先从支持范围索引的词典中检索值,然后从这些值构造一个或查询以检索相关文档。这在您的情况下不会直接起作用,因为您想检索联接的双方。您可以对每对文档运行搜索,或者对一侧运行单个搜索,然后为每个文档读取一个附加文档。
对:
for $value in cts:values(cts:path-reference("individual/id"))
return
cts:search(/,
cts:or-query((
cts:and-query((
cts:collection-query("demographic"),
cts:path-range-query("individual/id", "=", $value))),
cts:and-query((
cts:collection-query("membership"),
cts:path-range-query("enrolledIndividualId/id", "=", $value))))),
"unfiltered")
霰弹枪或加迭代:
for $doc in
cts:search(/,
cts:and-query((
cts:collection-query("demographic"),
cts:path-range-query("individual/id", "=",
cts:values(cts:path-reference("individual/id"))))),
"unfiltered")
return
cts:search(/,
cts:and-query((
cts:collection-query("membership"),
cts:path-range-query("enrolledIndividualId/id", "=", $doc/individual/id))),
"unfiltered")
如您所见,每种方法都需要与您要加入的文档/值的数量成比例的 I/O。如果您只需要shotgun-OR(即,根据其他文档的条件查询文档),您只需要发出两个请求,第一次cts:values()
调用从词典中检索值,以及cts:search()
使用构建的查询调用那些价值观。
注意:cts:query
这些示例中使用的对象可以通过该search:resolve()
函数与 Search API 结合使用。
鉴于您明显的数据模型,通过将数据处理成单独的、非规范化的文档,您将获得更好的服务。