繁体   English   中英

使用OR在MarkLogic上进行Xquery

[英]Xquery on MarkLogic using OR

这是一个新手MarkLogic问题。 想象一下像这样的xml结构,这是我真正的业务问题的凝结:

<Person id="1">
  <Name>Bob</Name>
  <City>Oakland</City>
  <Phone>2122931022</Phone>
  <Phone>3123032902</Phone>
</Person>

请注意,文档可以并且将具有多个Phone元素。

我要求从每个文档中返回信息,该文档的Phone元素与电话号码列表中的任何一个匹配。 该列表中可能包含几十个电话号码。

我试过这个:

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元素。 我的目标是为每个匹配的文档返回所有NameCity元素以及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的列表然后在循环中查询每个文档是不高效的。 谢谢!

你的方法没有你想象的那么糟糕。 只需进行一些更改即可使其按您的喜好工作。

首先,你最好使用cts:element-value-query而不是cts:word-query 它允许您将搜索到的值限制为特定元素。 当您为该元素添加元素范围索引时,它表现最佳,但不是必需的。 它也可以依赖于始终存在的单词索引。

其次,不需要cts:or-query cts:word-querycts:element-value-query函数(以及所有其他相关函数)都接受多个搜索字符串作为一个序列参数。 它们被自动视为or-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>

祝你好运。

这就是我要做的事情:

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-queryvalue-query及其兄弟时,会有一个隐式OR,并且可以从索引中更有效地解析此查询,所以尽可能这样做。

其次,个人可能会匹配多个电话号码,因此您需要额外的内部循环才能有效地按个人分组。

我不会为此创建一个范围索引 - 没有必要,并且它不一定更快。 默认情况下,元素值有索引,因此您可以利用元素值查询

您可以使用SearchAPI和一点XSLT完成所有这些操作。 这样可以轻松地在单个查询中开始组合名称和数字以及其他条件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM