环境:eXist-DB 4.4 / Xquery 3.1
我有数百个tei:xml文档,其中编码了名为实体persName
和placeName
的实体。文件在
collection("db/fooapp/data")
persName
和placeName
的每个实例都有一个属性@nymRef
,该属性包含一个引用主文档中的xml:id
的值:
db/fooapp/data/codes_persons.xml
db/fooapp/data/codes_places.xml
这些主文档除其他外,还包含每个人或每个地方的规范名称。
例如,我经常对某个单一名称进行单一查询
let $x := some @nymRef
let $y := doc(db/fooapp/data/codes_places.xml)//tei:place[@xml:id=$x]//tei:placeName/text()
return $y
但是,有时候我需要这样做,遍历庞大的列表。例如,在所有文档中,我需要为id
输出一个seg
,并且它有一个(或多个)子元素placeName/@nymRef
:
<seg xml:id="fooref">some text<placeName nymRef="fooplace"/>some text</seg>
任务是获取所有seg/@xml:id
,然后查找并在其下面输出任何placeName/@nymRef
的规范名称。这会导致大量往返过程确实效率低下,但是我不知道在eXist-DB中执行此操作的任何其他方法。昂贵的往返行程以let $c
表示,并在return
之间循环:
let $coll := collection("db/fooapp/data")
for $a in $coll//seg
for $b in $a//placeName
let $c := $doc("db/fooapp/data/codes_places.xml")//tei:place[@xml:id=$b/data(@nymRef)]//tei:placeName/text()
return
<tr>
<td>{$a/@xml:id}</td>
<td>{$c}</td>
</tr>
单个表输出最多可以增加数百次往返行程。
我不反对在必要时将任务重组为多个功能。
非常感谢。
答案 0 :(得分:1)
请向我们提供输入xml和所需的输出,否则无法重写您的查询。我们还需要查看您的索引配置。
关于避免往返的一些一般建议:
首先,请参阅我的previous answer,以回答关于使用
ft:query()
。当做[@xml:id=$b/data(@nymRef)]
存在时,使用
索引还是您强迫它不进行字符串比较
在该字符串上配置了索引?
id()
是查找xml:id
值的最快方法
distinct-values
是您的朋友,只能查找每个
键:值对一次。
使用单个for循环来避免对同一数据进行多次迭代 次。
尽可能使用限制性更强的XPath表达式,//
可能会将大量不必要的数据加载到内存中。
所有这些以及更多内容都可以在documentation
中找到