eXist-db 集合排序
eXist-db collection sort
从 开始使用 pos
:
在 eXist 4.7 中,我在 myapp/data/
中有一个集合,其中包含数千个 TEI XML 文档。我使用 Martin Honnen 的以下解决方案来获取某个文档之前和之后的文档
let $data := myapp/data
let $examples := $data/tei:TEI[@type="example"]
for $example at $pos in $examples
where $example/@xml:id = 'TC0005'
return (
$examples[$pos - 1],
$example
$examples[$pos + 1]
)
我希望 $examples[$pos - 1]
生成文档 'TC0004',$examples[$pos + 1]
生成 'TC0006'(基于 eXide 集合导航视图中看到的排序顺序)例子)。他们不这样做,而是产生相反的结果。
Honnen 和 Michael Kay 回应说
ordering of documents within a collection is very much processor-dependent
应用 order by $example/@xml:id ascending
子句并没有使结果变得更好。
所以,问题是我怎样才能对 $data
施加字母数字顺序?
非常感谢。
您似乎可以在 XQuery 级别将 let $examples := $data/tei:TEI[@type="example"]
更改为
let $examples := sort($data/tei:TEI[@type="example"], (), function($e) { $e/@xml:id })
(假设 XQuery/XPath 3.1 高阶 sort
函数可用)或
let $examples := for $e in $data/tei:TEI[@type="example"] order by $e/@xml:id return $e
使用 order by
子句。
我不知道 exist-db 是否有某种方法可以在创建或选择集合期间强加顺序。
根据旧版 eXist 的经验,经过循环时的 $pos 值不是排序后的位置顺序。是穿越时的位置。
您首先要做的是创建一个有序列表,然后从您要查找的列表中获取三个项目。
let $data := myapp/data[tei:TEI/@type eq 'example']
let $examples := for $e in $data order by $e/@xml:id ascending return $e
let $pos := index-of($examples/@xml:id, 'TC0005')
return if (count($pos) eq 1) then (
if ($pos gt 1) then $examples[$pos - 1] else (),
$examples[$pos]
$examples[$pos + 1]
) else ()
这种方法的一个潜在问题是您每次都必须对所有项目进行排序。创建一个排序的缓存列表可以缓解这个问题,并且还可以实现更高效的查询,您可以在查询结果中使用 preceding-sibling
和 following-sibling
。
如果 ID 的命名约定一致,另一种可能的解决方案是查询前后 ID。
检查 $pos 中是否有一项是为了防止 @xml:id 不唯一的情况(是的,这违反规范,但它发生在现实世界的数据中) 或不存在任何项目。请记住,index-of
returns 索引数组 - 0 或更多。
从 pos
:
在 eXist 4.7 中,我在 myapp/data/
中有一个集合,其中包含数千个 TEI XML 文档。我使用 Martin Honnen 的以下解决方案来获取某个文档之前和之后的文档
let $data := myapp/data
let $examples := $data/tei:TEI[@type="example"]
for $example at $pos in $examples
where $example/@xml:id = 'TC0005'
return (
$examples[$pos - 1],
$example
$examples[$pos + 1]
)
我希望 $examples[$pos - 1]
生成文档 'TC0004',$examples[$pos + 1]
生成 'TC0006'(基于 eXide 集合导航视图中看到的排序顺序)例子)。他们不这样做,而是产生相反的结果。
Honnen 和 Michael Kay 回应说
ordering of documents within a collection is very much processor-dependent
应用 order by $example/@xml:id ascending
子句并没有使结果变得更好。
所以,问题是我怎样才能对 $data
施加字母数字顺序?
非常感谢。
您似乎可以在 XQuery 级别将 let $examples := $data/tei:TEI[@type="example"]
更改为
let $examples := sort($data/tei:TEI[@type="example"], (), function($e) { $e/@xml:id })
(假设 XQuery/XPath 3.1 高阶 sort
函数可用)或
let $examples := for $e in $data/tei:TEI[@type="example"] order by $e/@xml:id return $e
使用 order by
子句。
我不知道 exist-db 是否有某种方法可以在创建或选择集合期间强加顺序。
根据旧版 eXist 的经验,经过循环时的 $pos 值不是排序后的位置顺序。是穿越时的位置。
您首先要做的是创建一个有序列表,然后从您要查找的列表中获取三个项目。
let $data := myapp/data[tei:TEI/@type eq 'example']
let $examples := for $e in $data order by $e/@xml:id ascending return $e
let $pos := index-of($examples/@xml:id, 'TC0005')
return if (count($pos) eq 1) then (
if ($pos gt 1) then $examples[$pos - 1] else (),
$examples[$pos]
$examples[$pos + 1]
) else ()
这种方法的一个潜在问题是您每次都必须对所有项目进行排序。创建一个排序的缓存列表可以缓解这个问题,并且还可以实现更高效的查询,您可以在查询结果中使用 preceding-sibling
和 following-sibling
。
如果 ID 的命名约定一致,另一种可能的解决方案是查询前后 ID。
检查 $pos 中是否有一项是为了防止 @xml:id 不唯一的情况(是的,这违反规范,但它发生在现实世界的数据中) 或不存在任何项目。请记住,index-of
returns 索引数组 - 0 或更多。