比较MarkLogic中同一文档的两个元素

时间:2016-05-28 10:50:27

标签: xquery marklogic marklogic-8

我有一个MarkLogic 8数据库,其中有两个日期时间字段的文档:

  1. created-on
  2. active-since
  3. 我正在尝试编写一个Xquery来搜索active-since 的值小于 created-on的值

    的所有文档

    目前我正在使用以下FLWOR排名:

        for $entity in fn:collection("entities")
    
        let $id := fn:data($entity//id)
        let $created-on := fn:data($entity//created-on)
        let $active-since := fn:data($entity//active-since)
    
        where $active-since < $created-on
    
        return 
          (
            $id,
            $created-on,
            $active-since
          )
    

    上述查询执行时间过长,并且随着文档数量的增加,此查询的执行时间也将增加。

    另外,我有 element-range-index用于上述两个dateTime字段,但这里没有使用它们。 cts-element-query函数仅将一个元素与一组原子值进行比较。在我的情况下,我试图比较同一文档的两个元素。

    我认为应该有一个更好的优化解决方案来解决这个问题。

    如果有任何搜索功能或任何其他方法适用于此方案,请告诉我。

4 个答案:

答案 0 :(得分:5)

这对你来说可能足够有效。

获取其中一个值并按值构建范围查询。这都使用范围索引,因此从这个意义上讲,它是有效的。但是,在某些时候,我们构建了一个大型查询。它读起来与flword语句类似。如果真的想要提高效率,可以找出哪些元素的唯一值(索引大小)较少,并将其用于迭代 - 从而构建较小的查询。此外,您将注意到在元素值调用中,我还将其约束到您的集合。这是为了防止您碰巧在集合之外的文档中包含该元素。这使列表仅保留您知道的集合中的值:

let $q := cts:or-query(
        for $created-on in cts:element-values(xs:QName("created-on"), (), cts:collection-query("entities"))
            return cts:element-value-range-query(xs:Qname("active-since"), "<" $created-on)
    )


return
    cts:search(
        fn:collection("entities"),
        $q
    )

所以,让我们用一个简单的例子解释一下发生了什么:
假设我有元素A和B - 每个元素都定义了一个范围索引。

让我们在5个文件中假装我们有这样的组合:
A,B
2,3
4,2
2,7
5,4
2,9

let $ := cts:or-query(
        for $a in cts:element-values(xs:QName("A"))
            return cts:element-value-range-query(xs:Qname("B"), "<" $a)
    )

这将创建以下查询:

cts:or-query(
    (
       cts:element-value-range-query(xs:Qname("B"), "<" 2),
       cts:element-value-range-query(xs:Qname("B"), "<" 4),
       cts:element-value-range-query(xs:Qname("B"), "<" 5)
    )
 )

在上面的示例中,唯一的匹配是具有组合的文档:(5,4)

答案 1 :(得分:4)

您可以尝试使用cts:tuple-values()。传递三个引用:active-sincecreated-on和URI引用。然后迭代结果,查找active-since小于created-on的结果,并且您将获得doc的URI。

这不是最漂亮的代码,但它会让所有数据都来自RAM,所以它应该很好地扩展。

答案 2 :(得分:1)

我现在使用以下脚本来获取active-since的值小于created-on的值的文档数:

fn:sum(
    for $value-pairs in cts:value-tuples(
        (
            cts:element-reference(xs:QName("created-on")), 
            cts:element-reference(xs:QName("active-since"))
        ),
        ("fragment-frequency"),
        cts:collection-query("entities")
    )

    let $created-on := json:array-values($value-pairs)[1]
    let $active-since := json:array-values($value-pairs)[2]

    return
      if($active-since lt $created-on) then cts:frequency($value-pairs) else 0
    )

答案 3 :(得分:0)

很抱歉没有足够的声誉,所以我需要在这里评论你的答案。为什么你认为ML不会返回(2,3)和(4,2)。我相信我们正在使用Or-query,它将任何单个查询视为true并返回文档。