在 MarkLogic 中比较同一文档的两个元素
Compare two elements of the same document in MarkLogic
我有一个 MarkLogic 8 数据库,其中的文档有两个日期时间字段:
created-on
active-since
我正在尝试编写一个 Xquery 来搜索 active-since
的值小于 created-on
[= 的值的所有文档17=]
目前我正在使用以下 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
用于上述两个日期时间字段,但此处未使用它们。 cts-element-query 函数只将一个元素与一组原子值进行比较。就我而言,我正在尝试比较同一文档的两个元素。
我觉得这个问题应该有更好更优化的解决方案。
如果有适合这种情况的任何搜索功能或任何其他方法,请告诉我。
这对你来说可能足够有效了。
取其中一个值并为每个值构建一个范围查询。这都使用范围索引,所以从这个意义上说,它是高效的。但是,在某些时候,我们构建了一个大型查询。它读起来类似于 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)
您可以尝试使用 cts:tuple-values()
。传入三个引用:active-since
、created-on
和 URI 引用。然后迭代结果以查找 active-since
小于 created-on
的结果,您将获得文档的 URI。
这不是最漂亮的代码,但它会让所有数据都来自 RAM,因此它应该可以很好地扩展。
抱歉没有足够的声誉,因此我需要在这里评论你的回答。为什么你认为ML不会return(2,3)和(4,2)。我相信我们正在使用一个 Or-query,它会将任何单个查询视为 true 并且 return 文档。
我现在使用以下脚本来获取 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
)
我有一个 MarkLogic 8 数据库,其中的文档有两个日期时间字段:
created-on
active-since
我正在尝试编写一个 Xquery 来搜索 active-since
的值小于 created-on
[= 的值的所有文档17=]
目前我正在使用以下 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
用于上述两个日期时间字段,但此处未使用它们。 cts-element-query 函数只将一个元素与一组原子值进行比较。就我而言,我正在尝试比较同一文档的两个元素。
我觉得这个问题应该有更好更优化的解决方案。
如果有适合这种情况的任何搜索功能或任何其他方法,请告诉我。
这对你来说可能足够有效了。
取其中一个值并为每个值构建一个范围查询。这都使用范围索引,所以从这个意义上说,它是高效的。但是,在某些时候,我们构建了一个大型查询。它读起来类似于 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)
您可以尝试使用 cts:tuple-values()
。传入三个引用:active-since
、created-on
和 URI 引用。然后迭代结果以查找 active-since
小于 created-on
的结果,您将获得文档的 URI。
这不是最漂亮的代码,但它会让所有数据都来自 RAM,因此它应该可以很好地扩展。
抱歉没有足够的声誉,因此我需要在这里评论你的回答。为什么你认为ML不会return(2,3)和(4,2)。我相信我们正在使用一个 Or-query,它会将任何单个查询视为 true 并且 return 文档。
我现在使用以下脚本来获取 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
)