我的 xpath 查询无法使用范围索引。我究竟做错了什么?

My xpath query fails to use the range index. What am I doing wrong?

我通过它的 id 找到一个相关元素,存储在引用元素的 href 中,如下所示:

let $item := ($doc//(map|question|theory|reading|glossgroup))[@id = $ref/@href]

阅读 ExistDB 的文档,我很确定一个简单的 <create qname="@ID" type="xs:string" /> 索引就足够了,甚至应该是自动生成的。但是查看分析器,我的查询没有使用任何索引。

我什至试过了

let $item := $doc//map[@id = $ref/@href]

并像这样用 id 字段创建了一个索引

<index>
    <range>
        <create qname="map" type="xs:string">
            <field name="map-id" match="@id" type="xs:string" />
        </create>
    </range>
</index>

但似乎没有任何效果。

我是 ExistDB 的新手.. 可能做了一些明显的错误,所以如果有人能指出我正确的方向:)?

示例XML:

<root>
  <map id="ide931fee3-6a45-4435-a8d2-f018ae2ca2ea">
    <mapref href="f80cc8c8-6b6d-4005-b2e9-85eac2ee2fbf.1.36" />
  </map>
  <map id="f80cc8c8-6b6d-4005-b2e9-85eac2ee2fbf.1.36">
    <topicref href="47aed1dd-62f7-4fb6-ae76-dbfcde0a4bab.1.9" />
  </map>
  <question id="47aed1dd-62f7-4fb6-ae76-dbfcde0a4bab.1.9">
    ...
  </question>
</root>

如果可以,我建议切换到 xml:id 属性。这是由 exist-db 自动索引的。然后您可以删除索引定义并使用 id() 函数检索元素。

示例

$doc/id($ref/@href)

Use fn:id to lookup xml:id attributes

eXist-db automatically indexes all xml:id attributes and other attributes with type ID as declared in a DTD (if validation is enabled). This automatic index is used by the standard id functions and provides a fast way to look up an element. For example, id("sect1")/head works through a fast index lookup.

However, the equivalent expression //section[@xml:id = 'sect1']/head will not use the id index.

Some users have reported that larger xml:id values have a negative performance impact.

source

如果你还想坚持@id:

创建范围索引:

<index>
    <range>
        <create match="@id" type="xs:string" />
    </range>
</index>

这应该会告诉您基本的索引用法。

重写您的查询可能会进一步提高性能(完全优化):

$doc//(map|question|theory|reading|glossgroup)/@id[. = $ref/@href]/..

对于任何对我最终选择的解决方案感兴趣的人。不幸的是,列出的答案并没有真正使我的查询更快,也没有让我知道如何重写它。

所以我这样做了:

let $item := $doc//map[@id = $ref/@href]
let $item := if ($item) then $item else $doc//question[@id = $ref/@href]
let $item := if ($item) then $item else $doc//theory[@id = $ref/@href]
let $item := if ($item) then $item else $doc//reading[@id = $ref/@href]
let $item := if ($item) then $item else $doc//glossgroup[@id = $ref/@href]

并分别创建了相应的索引

<create qname="map" type="xs:string">
    <field name="map-id" match="@id" type="xs:string" />
</create>
<create qname="question" type="xs:string">
    <field name="question-id" match="@id" type="xs:string" />
</create>
<create qname="theory" type="xs:string">
    <field name="theory-id" match="@id" type="xs:string" />
</create>
<create qname="reading" type="xs:string">
    <field name="reading-id" match="@id" type="xs:string" />
</create>
<create qname="glossgroup" type="xs:string">
    <field name="glossgroup-id" match="@id" type="xs:string" />
</create>