假设我的Oracle Text索引中有2行,例如:
Row 1 'John Smith Bristol South West'
Row 2 'John James Smith London South East'
进行以下搜索的最佳方法是什么?
如果我提供搜索词: John Smith 或 Smith John ,则应返回两行,但鉴于搜索,第一行的得分应更高字词彼此靠近。
如果我提供搜索词: Joh Smit 或 Smit Jon ,则应返回两行,但鉴于搜索,第1行的得分应更高字词彼此靠近。
当前,我的SQL看起来像这样:
SELECT display_value
, score(1)
FROM my_indx_table
WHERE contains ( search_tokens, '%' || replace(replace( :SEARCH_STRING, '_', '\_' ), '-', '\-') || '%', 1 ) > 0
ORDER BY score( 1 ) desc;
但是它没有按我的预期工作。
在此先感谢您的帮助。
答案 0 :(得分:1)
欢迎来到黑暗,可怕的Oracle Text搜索世界。 (您可能想read the docs。)让我们从一些设置开始,以便我可以复制您的问题。
create table my_indx_table (display_value number, search_tokens varchar2(100));
create index my_indx on my_indx_table (search_tokens) indextype is ctxsys.context;
insert into my_indx_table values (1, 'John Smith Bristol South West');
insert into my_indx_table values (2, 'John James Smith London South East');
commit;
exec ctx_ddl.sync_index(idx_name => 'MY_INDX');
好的,这是您的查询。它仅返回第1行,因为该行的确切顺序为“ John Smith”。
SELECT display_value, score(1)
FROM my_indx_table
WHERE contains ( search_tokens, '%' || replace(replace( 'John Smith', '_', '\_' ), '-', '\-') || '%', 1 ) > 0
ORDER BY score( 1 ) desc;
DISPLAY_VALUE SCORE(1)
------------- ----------
1 3
如果您要使用一个CONTAINS调用一次进行多种搜索,则可能要使用Query Templates。
下一个示例使用查询重写和查询松弛。它首先尝试使用确切的短语“ John Smith”,然后搜索彼此靠近的两个单词。
SELECT display_value, score(1)
FROM my_indx_table
WHERE contains ( search_tokens,
'<query>
<textquery lang="ENGLISH" grammar="CONTEXT">' || 'John Smith' || '
<progression>
<seq><rewrite>transform((TOKENS, "{", "}", " "))</rewrite></seq>
<seq><rewrite>transform((TOKENS, "{", "}", " NEAR "))</rewrite></seq>
</progression>
</textquery>
<score datatype="FLOAT" algorithm="COUNT"/>
</query>',
1 ) > 0
ORDER BY score( 1 ) desc;
DISPLAY_VALUE SCORE(1)
------------- ----------
1 50.5
2 6.8908
第1行的得分高于第2行,这主要是因为它包含了确切的词组。
如果您删除第一行<seq></seq>
(或尝试使用“史密斯·约翰”),您会注意到,尽管行距不同,但两行的
现在让我们看一下fuzzy搜索,以解决拼写错误。此功能的默认相似性得分为60,但我将其降低为50,这样它将获得Smit = Smith。
SELECT display_value, score(1)
FROM my_indx_table
WHERE contains ( search_tokens,
'<query>
<textquery lang="ENGLISH" grammar="CONTEXT">' || 'Joh Smit' || '
<progression>
<seq><rewrite>transform((TOKENS, "{", "}", " "))</rewrite></seq>
<seq><rewrite>transform((TOKENS, "{", "}", " NEAR "))</rewrite></seq>
<seq><rewrite>transform((TOKENS, "fuzzy(", ", 50)", " "))</rewrite></seq>
<seq><rewrite>transform((TOKENS, "fuzzy(", ", 50)", " NEAR "))</rewrite></seq>
</progression>
</textquery>
<score datatype="FLOAT" algorithm="COUNT"/>
</query>',
1 ) > 0
ORDER BY score( 1 ) desc;
DISPLAY_VALUE SCORE(1)
------------- ----------
1 25.25
2 3.4454
我认为这很简单。这里最令人困惑的事情可能是查询重写语法。但是,您可以使用fuzzy
运算符进行很多调整,以使其能够处理您要处理的特定搜索。