这是一个新手MarkLogic问题。想象一下像这样的xml结构,这是我真正的业务问题的缩影:
<Person id="1">
<Name>Bob</Name>
<City>Oakland</City>
<Phone>2122931022</Phone>
<Phone>3123032902</Phone>
</Person>
请注意,文档可以并且将包含多个电话元素。
我要求从 EVERY 文档中返回信息,该文档的电话元素与电话号码列表 ANY 匹配。该列表中可能包含几十个电话号码。
我试过这个:
let $a := cts:word-query("3738494044")
let $b := cts:word-query("2373839383")
let $c := cts:word-query("3933849383")
let $or := cts:or-query( ($a, $b, $c) )
return cts:search(/Person/Phone, $or)
可以正确执行查询,但它会在Results元素中返回一系列 Phone 元素。我的目标是为每个匹配的文档返回所有名称和城市元素以及Person元素的id属性。例如:
<results>
<match id="18" phone="2123339494" name="bob" city="oakland"/>
<match id="22" phone="3940594844" name="mary" city="denver"/>
etc...
</results>
所以我认为我需要某种形式的cts:search
允许这种布尔功能,但也允许我指定返回每个文档的哪个部分。那时我可以用XPATH
进一步处理结果。我需要有效地执行此操作,例如,我认为返回文档uri的列表然后在循环中查询每个文档是不高效的。谢谢!
答案 0 :(得分:5)
你的方法没有你想象的那么糟糕。只需要进行一些更改就可以让它按照您的喜好工作。
首先,您最好使用cts:element-value-query
代替cts:word-query
。它允许您将搜索到的值限制为特定元素。当您为该元素添加元素范围索引时,它的效果最佳,但不是必需的。它也可以依赖于始终存在的单词索引。
其次,不需要cts:or-query
。 cts:word-query
和cts:element-value-query
函数(以及所有其他相关函数)都接受多个搜索字符串作为一个序列参数。它们会自动视为或查询。
第三,结果中的电话号码是您的“主键”,因此返回所有匹配的电话元素列表 的方式。您只需要意识到生成的Phone元素仍然知道它们来自何处。您可以轻松使用XPath
导航到父母和兄弟姐妹。
第四,没有什么可以阻止搜索结果的循环。这可能听起来有点奇怪,但它不会花费太多额外的性能。实际上,在MarkLogic Server中它几乎可以忽略不计。当您尝试返回许多结果(超过几千个)时,大多数性能可能会丢失,在这种情况下,大部分时间都会在序列化时丢失。如果您可能需要处理大量搜索结果,那么立即开始使用分页是明智的。
要获得您的要求,您可以使用以下代码:
<results>{
for $phone in
cts:search(
doc()/Person/Phone,
cts:element-value-query(
xs:QName("Phone"),
("3738494044", "2373839383", "3933849383")
)
)
return
<match id="{data($phone/../@id)}" phone="{data($phone)}" name="{data($phone/../Name)}" city="{data($phone/../City)}"/>
}</results>
祝你好运。
答案 1 :(得分:3)
这就是我要做的事情:
let $numbers := ("3738494044", "2373839383", "3933849383")
return
<results>{
for $person in cts:search(/Person, cts:element-value-query(xs:QName("Phone"),$numbers))
return
<match id="{data($person/@id)}" name="{data($person/Name)}" city="{data($person/City)}">
{
for $phone in $person/Phone[cts:contains(.,$numbers)]
return element phone {$phone}
}
</match>
}
首先,在将多个值传递给 word-query 和 value-query 及其兄弟时,会出现隐式OR,并且可以更有效地从索引中解析此查询,所以你可以这样做。
其次,个人可能会匹配多个电话号码,因此您需要额外的内部循环才能有效地按个人分组。
我不会为此创建范围索引 - 不需要,而且不一定更快。默认情况下,元素值有索引,因此您可以利用元素值查询的索引。
您可以使用SearchAPI
和一点XSLT
完成所有这些操作。这样可以很容易地在单个查询中开始组合名称和数字以及其他条件。