【问题标题】:SQL-Server Full Text Index Unexpected resultsSQL-Server 全文索引 意外结果
【发布时间】:2018-02-15 00:43:47
【问题描述】:

MS SQL 服务器 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) 运行 select lcid from sys.syslanguages where langid=@@langid 以获取您的数据库语言的 LCID 2) 运行 select * from sys.dm_fts_parser('"235_*"', your-lcid-here, 0, 0); 这将向您展示如何解析字符串(包括目录停止列表)
  • 嗨,亚历克斯。好电话-但已经走上了这条路。下划线被正确解析。我什至在该单个字段中有多个下划线实例,其中一个可以搜索,其中一个不能。很高兴看到我们的想法相同。
  • 我得出了与数字有关的相同结论,请参阅我的上次编辑。

标签: sql-server full-text-search


【解决方案1】:

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_*"')

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

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(和 _)。

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

【讨论】:

  • 嗨 HoneyBadger。你的权利有很多字符会被替换 & - / \ 等,但下划线不是其中之一。我们实际上做了几个替换来访问我们的客户要求搜索的这些字符。例如我们将 '-' 替换为 'hyph' 或 '&' 替换为 'and'。这是我们经常做的事情,因为我们“误用”全文搜索匹配的零件号。答案加 1,因为它可能对其他人有帮助,但不幸的是,这里并非如此。
  • 好的,上面的评论中有下划线,但我只是得到粗体字 - 很抱歉有任何混淆
  • @MatthewBaker,一直在挖掘,请参阅编辑。我现在有点吃惊……
  • 我刚刚运行了相同的测试。 select * FROM TestFullTextSearch WHERE CONTAINS(AllText, '"235_ldzr_2*"') 返回 5&6,但是 select * FROM TestFullTextSearch WHERE CONTAINS(AllText, '"87112311437_ldzr_2*"') 根本不返回任何行。那不只是我在做傻事吗?
  • 是的,我的 lcid = 1033 也是。
猜你喜欢
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-02
  • 2010-09-12
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
相关资源
最近更新 更多