环境: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
但是,有时我需要这样做,在巨大的列表中循环。例如,在所有文档中,我需要为seg
输出一个id
,并且它有一个(或多个(子元素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>
对于单个表输出,这可能会导致数百次往返。
如有必要,我不反对将这项任务改组为多项职能。
非常感谢。
请为我们提供一个输入xml和所需的输出,否则无法重写您的查询。我们还需要查看您的索引配置。
避免往返的一些一般建议:
-
首先,请参阅我之前对您关于使用
ft:query()
。当执行[@xml:id=$b/data(@nymRef)]
时,使用索引还是强制它进行字符串比较是否在该字符串上配置了索引? -
id()
是查找xml:id
值的最快方法 -
distinct-values
是你的朋友只查找每一个不同的key:值对一次。 -
使用单个for循环以避免在同一数据上重复多次时间。
-
只要可能,请使用限制性更强的XPath表达式
//
可能会将大量不必要的数据加载到内存中。
所有这些以及更多信息都可以在文档中找到