以下是XML结构 -
<Docs>
<Doc>
<Name>Doc 1</Name>
<Notes>
<specialNote>
This is a special note section.
<B>This B Tag is used for highlighting any text and is optional</B>
<U>This U Tag will underline any text and is optional</U>
<I>This I Tag is used for highlighting any text and is optional</I>
</specialNote>
<generalNote>
<P>
This will store the general notes and might have number of paragraphs. This is para no 1. NO Child Tags here
</P>
<P>
This is para no 2
</P>
</generalNote>
</Notes>
<Desc>
<P>
This is used for Description and might have number of paragraphs. Here too, there will be B, U and I Tags for highlighting the description text and are optional
<B>Bold</B>
<I>Italic</I>
<U>Underline</U>
</P>
<P>
This is description para no 2 with I and U Tags
<I>Italic</I>
<U>Underline</U>
</P>
</Desc>
</Doc>
将有1000个Doc
标签。我想为用户提供搜索条件,他可以搜索WORD1
而不是WORD2
。以下是查询 -
for $x in doc('Documents')/Docs/Doc[Notes/specialNote/text() contains text 'Tom'
ftand ftnot 'jerry' or
Notes/specialNote/text() contains text 'Tom' ftand ftnot 'jerry' or
Notes/specialNote/B/text() contains text 'Tom' ftand ftnot 'jerry' or
Notes/specialNote/I/text() contains text 'Tom' ftand ftnot 'jerry' or
Notes/specialNote/U/text() contains text 'Tom' ftand ftnot 'jerry' or
Notes/generalNote/P/text() contains text 'Tom' ftand ftnot 'jerry' or
Desc/P/text() contains text 'Tom' ftand ftnot 'jerry' or
Desc/P/B/text() contains text 'Tom' ftand ftnot 'jerry' or
Desc/P/I/text() contains text 'Tom' ftand ftnot 'jerry' or
Desc/P/U/text() contains text 'Tom' ftand ftnot 'jerry']
return $x/Name
此查询的结果是错误的。我的意思是,结果包含一些同时包含Tom
和jerry
的文档。所以我将查询更改为 -
for $x in doc('Documents')/Docs/Doc[. contains text 'Tom' ftand ftnot 'jerry']
return $x/Name
这个查询给出了确切的结果,即;只有那些Tom
而不是jerry
的文档,但这些文档需要花费大量时间... 45秒,而前一个花了10秒!!
我使用的是BaseX 7.5 XML数据库。
需要专家评论:)
答案 0 :(得分:4)
第一个查询分别测试文档中的每个文本节点,因此<P><B>Tom</B> and <I>Jerry</I></P>
会匹配,因为第一个文本节点包含 Tom 但不包含 Jerry 。
在第二个查询中,对Doc
元素的所有文本内容执行全文搜索,就好像它们被连接成一个字符串一样。这不能(当前)由BaseX's fulltext index回答,{{3}}分别为每个文本节点编制索引。
解决方案是分别对每个术语执行全文搜索并最终合并结果。这可以分别为每个文本节点完成,因此可以使用索引:
for $x in (doc('Documents')/Docs/Doc[.//text() contains text 'Tom']
except doc('Documents')/Docs/Doc[.//text() contains text 'Jerry'])
return $x/Name
上述查询由查询优化器重写为使用两个索引访问的等效查询:
for $x in (db:fulltext("Documents", "Tom")/ancestor::*:Doc
except db:fulltext("Documents", "Jerry")/ancestor::*:Doc)
return $x/Name
您甚至可以调整合并结果的顺序,以便在需要时保持较小的中间结果。