Oracle Text Context-Index使用通配符返回contains()查询的所有行

时间:2014-09-01 12:53:55

标签: sql oracle indexing full-text-search

我们在Oracle数据库(11.2.0.4.0)中使用Oracle Text对存储的文档以及数据库中的多个列执行全文搜索。

对于这些多列索引,我们注意到一些双面通配符查询返回错误的结果数:整个表!

我们的应用程序将用户的查询转换为双面通配符查询(例如“york” - >“%york%”)并将它们传递给contains运算符。 我们在数据库上重新运行它并可以重现它。

例如,考虑一个包含全文索引跨越所有列的城市的表:Zip-Code,Cityname,State和Country: select * from city where contains(cityname, '%york%')>0

以下查询参数似乎返回错误的结果数(所有行):

  • %S%
  • %I%
  • %d%
  • %C%

我已经检查了什么:

  • 有趣的是,非工作查询都是C语言中的格式参数。但我无法在Oracle Text文档中找到这些作为关键字或特殊运算符。
  • 我检查了停用词列表不包含这些查询。
  • 我设置了一个自定义词法分析器,并为其启用了“混合大小写”选项,这似乎解决了小写查询的问题,但大写查询仍然存在问题(%S%)。

score运算符为不匹配的行返回值6:

select cityname, state, zip, score(1) from city where contains(cityname, '%s%', 1)>0
---------------------------------
|Cityname  |State|Zip | Score(1)|
|-------------------------------|
|La Cibourg|NE   |2332| 6       | - WRONG
|Morlon    |FR   |1638| 6       | - WRONG
|Leuk Stadt|VS   |3953| 12      | - Correct row
---------------------------------

您是否知道可能导致此问题的任何(错误)配置?

更新 确切的版本是11.2.0.4.0,应用了补丁18842982。 创建表和索引的脚本如下:

drop table city_copy;

create table city_copy (
 city_nr number not null,
 zip_code varchar2(60),
 city_name varchar2(60),
 state varchar2(60)
 );

 insert into city_copy
 select 1, 2332, 'La Ciboug', 'NE' from dual
 union all
 select 2, 1638, 'Morlon', 'FR' from dual
 union all
 select 3, 3953, 'Leuk Stadt', 'VS' from dual;

 commit;

 exec   ctxsys.ctx_ddl.drop_preference('CITY_MULTI');
 exec   ctxsys.ctx_ddl.create_preference('CITY_MULTI', 'MULTI_COLUMN_DATASTORE');
 exec   ctxsys.ctx_ddl.set_attribute('CITY_MULTI', 'COLUMNS', 'ZIP_CODE, CITY_NAME, STATE');

 create index city_idx_ft on city_copy(zip_code)
 indextype is ctxsys.context parameters ('datastore CITY_MULTI sync (on commit)');

默认词法分析器的当前设置为:

DEFAULT_LEXER   COMPOSITE           GERMAN
DEFAULT_LEXER   MIXED_CASE          YES
DEFAULT_LEXER   ALTERNATE_SPELLING  GERMAN

我们的停止列表与default stoplist for German

保持不变

1 个答案:

答案 0 :(得分:2)

经过相当多的研究后......

我仍然不确定它是否是一个bug,但是虽然我的直觉说它是导致这种行为的词法分析器 - 但事实并非如此。

请在首选项中添加名为DELIMITER的属性,其值为NEWLINE

exec ctx_ddl.set_attribute('CITY_MULTI', 'DELIMITER', 'NEWLINE'); 

这可以解决您的问题。

默认分隔符是COLUMN_NAME_TAG,它可能与太短的参数冲突(它应该将您的数据视为XML,并且可能在Oracle如何连接文本中的某个地方有您正在寻找的单个字符)。

在我看来,对于多列数据存储Oracle Text构造,每行都有一个XML,其中包含列的名称,如:

<XML>
   <zip_code>2332</zip_code>
   <city_name>La Ciboug</city_name>
   <state>NE</state>
</XML>

并且正在索引XML(或与之类似的结构)。

当只查找S时,“状态”一词的s在每一行都会返回。

新行改变了构建文本的方式

2332
La Ciboug
NE

在您的情况和搜索方式上更好。

有关它的更多信息,请点击此处: http://docs.oracle.com/cd/B19306_01/text.102/b14218/cdatadic.htm#i1006391

祝你好运!