Oracle Text包含带分隔符的数字和数字

时间:2014-06-02 15:15:20

标签: sql oracle oracle11g lexer oracle-text

我在一列上使用ctxsys.context索引来方便Oracle Text全文 搜索功能。但在索引由','或'。'分隔的数值时遇到问题。

我创建了索引,如:

create index my_index on my_table(my_column)
indextype is ctxsys.context parameters ('SYNC (ON COMMIT)');

然后我插入四个文本文档:

insert into my_table (id, doc) values (1, 'FOO 300 BAR');
insert into my_table (id, doc) values (2, 'FOO 300 BAR 1,000.00');
insert into my_table (id, doc) values (3, 'FOO1FOO');
insert into my_table (id, doc) values (4, '1 FOO');

现在我想使用contains运算符搜索'FOO 300 BAR','1,000.00'以及两者的组合:

select score(1), id from my_table where contains(doc, 'FOO 300 BAR', 1) > 0;
select score(1), id from my_table where contains(doc, '1,000.00', 1) > 0;
select score(1), id from my_table where contains(doc, 'FOO 300 BAR 1,000.00', 1) > 0;

第一个按预期工作,结果我得到id 1和2。虽然当我尝试使用1,000.00时,我得到0行。

正如我从文档中读到的那样,它默认使用BASIC_LEXER。我还尝试在词法分析器上明确指定分隔符并将其应用于索引。

begin
ctx_ddl.create_preference('my_lex', 'BASIC_LEXER');
ctx_ddl.set_attribute('my_lex', 'numjoin', '.');
ctx_ddl.set_attribute('my_lex', 'numgroup', ',');
end;

create index my_index on my_table(doc)
indextype is ctxsys.context parameters ('SYNC (ON COMMIT) LEXER my_lex');

但我经历了和以前一样的行为。

有人可以解释Oracle Text如何使用分隔符处理数字以及如何配置索引以便将分隔的数字视为单个单词?

我正在使用Oracle Database 11g Express Edition 11.2.0.2.0版 - 64位生产

1 个答案:

答案 0 :(得分:1)

我使用的是Oracle 10g,我遇到的问题与您描述的问题相同,只有一点不同。

我用过这个脚本:

    begin
      ctx_ddl.create_preference('my_lexer', 'BASIC_LEXER');
      ctx_ddl.set_attribute('my_lexer', 'numjoin', '.');
      ctx_ddl.set_attribute('my_lexer', 'numgroup', ','); 
      ctx_ddl.set_attribute('my_lexer', 'printjoins', '-/"_'); 
      ctx_ddl.set_attribute('my_lexer', 'index_text', 'YES'); 

    end;

这就是创建索引:

Create Index my_table_TIX01 ON my_table (doc) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS('lexer my_lexer SYNC (ON COMMIT)')

此查询在我的情况下返回1行:

select score(1), id, doc from my_table where contains(doc, '1,000.00', 1) > 0;

SCORE(1),ID,DOC
2,4,1 FOO

问题是如何解析您搜索的字符串中的标记。基本上1,000.00分为多个令牌:1然后000.00。您可以通过插入以下行来试验:

insert into my_table (id, doc) values (5, '00 FOO');
insert into my_table (id, doc) values (6, '000.00 FOO');
commit; -- Dont' forget to commit the data you insert otherwise the index is not updated!

然后运行此查询:

select score(1), id, doc from my_table where contains(doc, '1,000.00', 1) > 0;

它回来了:

SCORE(1),ID,DOC
3,4,1 FOO
3,6,000.00 FOO

逗号与ACCUM相同。这来自文档(参见底部的链接):

  

ACCUM,使用ACCUM运算符搜索包含的文档   至少出现一个任何查询词。累积   运营商根据a的总期限权对文档进行排名   文献。以下查询返回包含该文件的所有文档   术语狗,猫和小狗给予最高分   包含所有三个术语的文档:

     

'狗,猫,小狗'

要修复搜索,您需要将您在大括号中搜索的字符串括起来:

这两个查询将返回您期望的数据:

select score(1), id, doc from my_table where contains(doc, '{1,000.00}', 1) > 0;
select score(1), id, doc from my_table where contains(doc, 'FOO 300 BAR {1,000.00}', 1) > 0;

还有一点需要注意的是,如果您搜索300 FOO,即运行此查询:

select score(1), id, doc from my_table where contains(doc, '300 FOO', 1) > 0;

它不会带回任何东西。您必须使用放松模板或使用AND或&: 例子:

select score(1), id, doc from my_table where contains(doc, '300 and FOO', 1) > 0;

select score(1), id, doc from my_table where contains(doc, '
    <query>
       <textquery lang="ENGLISH" grammar="CONTEXT">
         <progression>
           <seq>300 f00</seq>
           <seq>300 NEAR f00</seq>
           <seq>300 AND foo</seq>       
         </progression>
       </textquery>
       <score datatype="INTEGER" algorithm="COUNT"/>
    </query>
    ', 1) > 0; 

另见这些链接:

我认为我们非常习惯于搜索谷歌,但这并不像谷歌那样......