1

我在一列上使用 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 Release 11.2.0.2.0 - 64bit Production

4

1 回答 1

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 运算符搜索包含至少一次出现的任何查询词的文档。累积运算符根据文档的总词项权重对文档进行排序。以下查询返回包含词条狗、猫和小狗的所有文档,对包含所有三个词条的文档给出最高分:

'狗,猫,小狗'

要修复您的搜索,您需要将搜索的字符串括在大括号之间:

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

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; 

另请参阅以下链接:

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

于 2014-06-26T05:44:17.700 回答