我有一个 Oracle数据库表来存储人员。 E.g:
|-------------|---------|
| Name | Data |
|-------------|---------|
| Marton | XYZ |
| Márton | XYZ |
|-------------|---------|
我在name
列上使用Oracle进行模糊搜索。问题是,当我搜索Márton
时,我得到2个条目(这很好),但是当我搜索Marton
时,我只得到一个不是我期望的条目。
以下是我尝试做的完整示例:
CREATE TABLE persons (
NAME VARCHAR(256) NOT NULL,
DATA VARCHAR(256) NOT NULL
);
INSERT INTO persons VALUES('Marton', '42');
INSERT INTO persons VALUES('Márton', '42');
begin
--ctx_ddl.drop_preference('my_store');
ctx_ddl.create_preference('my_store', 'MULTI_COLUMN_DATASTORE');
ctx_ddl.set_attribute('my_store', 'columns', 'NAME');
--ctx_ddl.drop_preference('my_lexer');
ctx_ddl.create_preference('my_lexer', 'BASIC_LEXER');
ctx_ddl.set_attribute('my_lexer','index_stems','NONE');
--ctx_ddl.drop_preference('my_wordlist');
ctx_ddl.create_preference('my_wordlist', 'BASIC_WORDLIST');
ctx_ddl.set_attribute('my_wordlist','fuzzy_match','GENERIC');
ctx_ddl.set_attribute('my_wordlist','stemmer','NULL');
end;
/
--DROP INDEX MY_FUZZY_IDX;
CREATE INDEX MY_FUZZY_IDX ON persons(NAME) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('datastore my_store section group ctxsys.auto_section_group lexer my_lexer wordlist my_wordlist stoplist ctxsys.empty_stoplist');
-- Returns only 1 entry! Not OK!
select * from persons where contains(NAME, '(fuzzy(Marton, 65, 100, W) within NAME)', 0) > 0;
-- Returns both entries! OK!
select * from persons where contains(NAME, '(fuzzy(Márton, 65, 100, W) within NAME)', 0) > 0;
我是否构建了错误的索引,或者我是否使用模糊搜索错误?
答案 0 :(得分:0)
我今天找到了解决问题的方法。 BASIC_LEXER
有一个名为base_letter
的选项,默认为NO
。如果您将其设置为YES
,则Oracle会将所有字词转换为基本字母(因此á
将变为a
)并且模糊搜索会按预期工作。
CREATE TABLE persons (
NAME VARCHAR(256) NOT NULL,
DATA VARCHAR(256) NOT NULL
);
INSERT INTO persons VALUES('Marton', '42');
INSERT INTO persons VALUES('Márton', '42');
begin
--ctx_ddl.drop_preference('my_store');
ctx_ddl.create_preference('my_store', 'MULTI_COLUMN_DATASTORE');
ctx_ddl.set_attribute('my_store', 'columns', 'NAME');
--ctx_ddl.drop_preference('my_lexer');
ctx_ddl.create_preference('my_lexer', 'BASIC_LEXER');
ctx_ddl.set_attribute('my_lexer','index_stems','NONE');
-- THE FIX!
ctx_ddl.set_attribute('my_lexer','base_letter','YES');
--ctx_ddl.drop_preference('my_wordlist');
ctx_ddl.create_preference('my_wordlist', 'BASIC_WORDLIST');
ctx_ddl.set_attribute('my_wordlist','fuzzy_match','GENERIC');
ctx_ddl.set_attribute('my_wordlist','stemmer','NULL');
end;
/
--DROP INDEX MY_FUZZY_IDX;
CREATE INDEX MY_FUZZY_IDX ON persons(NAME) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('datastore my_store section group ctxsys.auto_section_group lexer my_lexer wordlist my_wordlist stoplist ctxsys.empty_stoplist');
-- Returns both entries! OK!
select * from persons where contains(NAME, '(fuzzy(Marton, 65, 100, W) within NAME)', 0) > 0;
select * from persons where contains(NAME, '(fuzzy(Márton, 65, 100, W) within NAME)', 0) > 0;
有关详情,请参阅https://web.stanford.edu/dept/itss/docs/oracle/10g/text.101/b10730/cdatadic.htm。