使用Word1而不是Word2进行XQuery全文搜索

时间:2013-02-19 10:26:35

标签: full-text-search basex xquery-3.0

以下是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

此查询的结果是错误的。我的意思是,结果包含一些同时包含Tomjerry的文档。所以我将查询更改为 -

for $x in doc('Documents')/Docs/Doc[. contains text 'Tom' ftand ftnot 'jerry'] 
return $x/Name

这个查询给出了确切的结果,即;只有那些Tom而不是jerry的文档,但这些文档需要花费大量时间... 45秒,而前一个花了10秒!!

我使用的是BaseX 7.5 XML数据库。

需要专家评论:)

1 个答案:

答案 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

您甚至可以调整合并结果的顺序,以便在需要时保持较小的中间结果。