SQL-Server全文索引意外结果

时间:2018-02-14 13:55:17

标签: sql-server full-text-search

MS SQL SERVER 2012

我在数据库上配置了全文索引,主要部分似乎正常运行。我有一个关键字字段,其中包含以下文本:

 Veterinary Products Beaphar Fiprotec Spot On Small Dog 67mg x 1 235_ldzr_2 Beaphar 87112311437_ldzr_2

当尝试选择行时,我会得到意想不到的结果

select * from products where CONTAINS(keywords,'"235*"')
select * from products where CONTAINS(keywords,'"87112311437_ldzr_2*"')

两者都返回预期结果。这告诉我索引已设置且下划线字符不是问题。但是我得不到任何结果:

select * from products where CONTAINS(keywords,'"235_*"')
select * from products where CONTAINS(keywords,'"235_ldzr_2*"')

我已启用自动更改跟踪,并已禁用它,手动重建索引,重新启用它,但仍然没有运气。我甚至已经开始逐字逐句地评估字符串以获取ascii代码,以防特殊字符通过导入进入。该术语未出现在停止列表中。我现在不知道为什么这个项目没有显示。

我在单独的数据库中创建了一个副本并且无法重现该问题,因此无法在此处发布代码 - 因为我无法显示错误。

是否有人可以进行任何进一步检查或了解影响全文搜索功能的任何其他要点?

@HoneyBadger 我把它缩小了。数字后面跟一个带下划线的数字似乎有问题。在表格结构上尝试以下内容。

DELETE FROM TestFullTextSearch
insert into TestFullTextSearch values (1, '235_ldzr_2 testing ')
insert into TestFullTextSearch values (2, 'test 235_ldzr_2 testing ')
insert into TestFullTextSearch values (3, 'A 235_ldzr_2 testing ')
insert into TestFullTextSearch values (4, '1 235_ldzr_2 testing ')
insert into TestFullTextSearch values (5, '12 235_ldzr_2 testing ')
insert into TestFullTextSearch values (6, '123 235_ldzr_2 testing ')

SELECT * 
from   TestFullTextSearch 
where  contains(AllText, '"235*"')

SELECT * 
from   TestFullTextSearch 
where  contains(AllText, '"235_*"')

第1,2,3行全部按预期返回。 4,5,6不包括下划线。

1 个答案:

答案 0 :(得分:2)

SQL Server有一个被视为噪声的单词和符号列表,这些单词和符号被排除在索引之外,您无法专门搜索它。您可以编辑此列表,也可以创建一个新列表。有关操作方法,请参阅here

显然,您甚至可以在文件级别进行编辑,请参阅here

修改

我已经能够重现这个问题:

create table TestFullTextSearch (
Id int not null,
AllText nvarchar(400)
)

create unique index test_tfts on TestFullTextSearch(Id);
create fulltext catalog ftcat_tfts;
create fulltext index on TestFullTextSearch(AllText)
key index test_tfts on ftcat_tfts
with change_tracking auto, stoplist off
go

insert into TestFullTextSearch values (1, 'legacyreport Report Legacy 23049823490  20150713 Cardiac US ')
insert into TestFullTextSearch values (2, '123-45-678 foo bar  19450712 20020723 Exercise Stress US ')
insert into TestFullTextSearch values (3, '2048 jj goodguy xy2000 19490328 20150721 Cardiac US ')
insert into TestFullTextSearch values (4, '12345678 4.0 ALLCALCS  19650409 20031103 Cardiac Difficult US ')
insert into TestFullTextSearch values (5, 'Veterinary Products Beaphar Fiprotec Spot On Small Dog 67mg x 1 235_ldzr_2 Beaphar 87112311437_ldzr_2 ')

在此表中,如果我执行

select * 
from   TestFullTextSearch 
where  contains(AllText, '"235_ldzr_2*"')

我没有结果。但是,如果我添加一个反斜杠:

select  * 
FROM    TestFullTextSearch 
WHERE   CONTAINS(AllText, '"235\_ldzr_2*"')

我确实得到了结果!

我不明白。如果我添加另一行:

insert into TestFullTextSearch values (6, 'Veterinary Products Beaphar Fiprotec Spot On Small Dog 67_mg x 1 235_ldzr_2 Beaphar 87112311437_ldzr_2 ')

我搜索WHERE CONTAINS(AllText, '"67_*"'),我按预期得到了结果......其他测试也没有显示与contains(AllText, '"235_ldzr_2*"')相同的行为。

顺便说一句,我的LCID = 1033。

又一个测试用例:

Insert into TestFullTextSearch values (15, 'Veterinary Products Beaphar Fiprotec Spot On Small Dog 100_ldzr_2 x 1 225_ldzr_2 Beaphar 87112311437_ldzr_2 ')

我可以用

找到这条记录
CONTAINS(AllText, '"100_*"')

但是,这条记录,我在x 1前面添加了100_ldzr

Insert into TestFullTextSearch values (16, 'Veterinary Products Beaphar Fiprotec Spot On Small Dog x 1 100_ldzr_2 x 1 225_ldzr_2 Beaphar 87112311437_ldzr_2 ')

我找不到相同的CONTAINS,但如果我添加反斜杠,我就能找到它。

结论(暂时)

当数字后跟一个空格,然后是以下划线结尾的数字时,似乎会出现问题。请考虑以下事项:

select * from sys.dm_fts_parser('"x 235_*"', 1033, 0, 0)

这导致2个搜索词:“x”和“235 _”

然而:

select * from sys.dm_fts_parser('"1 235_*"', 1033, 0, 0)

七个搜索词的结果:“1 235”,“1235”,“1”,“235”和“_”。 (1和235也出现为nn1 / nn235)。

缺少“235_”解释了为什么找不到它。当我添加反斜杠时,它被解释为单词分隔符,将235\_235(以及_)匹配。

我非常有信心这就是原因。解决方案可能更难。