SQL Azure 包含未返回所有结果

SQL Azure CONTAINS not returning all results

我们添加了对以下 table 的自由文本搜索:

| 1 | kayer-meyar | 
| 2 | KA-ME |

但是,

select * 
from Names 
where CONTAINS(name, '"ME*"')

returns:

| 1 | kayer-meyar |

同时,

select * 
from Names 
where CONTAINS(name, '"KA*"')

returns 两者:

| 1 | kayer-meyar |
| 2 | KA-ME |

当我们 运行:

select * 
from sys.dm_fts_parser('"KA-ME"', 1033, NULL, 0)

returns:

ka-me
ka
me

尝试 运行 查询:select * 来自 sys.dm_fts_parser('"kayer-meyar"', 1033, NULL, 0)

ME 不是 Kayer-meyar 中的一个词,您可能得不到结果。

在搜索和调整你的问题后,我发现全文搜索有两个主要错误:

  1. 连字符可能会被视为分词。当我使用 '"ME*"' 时,它 return 只有 | 1 | kayer-meyar |。它没有 return | 2 | KA-ME |。问题是因为您的条件只允许单词以 (not end with or in a middle) ME + at least one character 开头。 你可以说"then how come it return | 1 | kayer-meyar | as string me is in the middle of this word ?"。好吧,这是因为全文搜索不将其视为一个单字,而是将其视为两个单独的词(类似于 kayer meyar ),因此它满足了要求(me*)。再次在 KA-ME 的情况下,它识别为 KA ME 而不是一个单词,它也没有满足条件(尽管它以 ME 为星标,但之后没有额外的字符)
  2. 您尝试过重建全文索引吗? .

现在 解决方案 是: 我已关闭全文搜索查询的停止列表 为此使用此查询(我的 table 名称是 MyTable):

ALTER FULLTEXT INDEX ON MyTable SET STOPLIST = OFF

然后 运行 您的查询。这次你会得到你想要的结果。

这是我的完整查询:

--CREATE TABLE MyTable
--(
--Id INT IDENTITY(1,1),
--Name varchar(max)  Not Null
--)

---- To see if FULLTEXT installed or not
--SELECT SERVERPROPERTY('IsFullTextInstalled')

---- 
---- https://technet.microsoft.com/en-us/library/ms187317.aspx
---- 
---- 

--CREATE UNIQUE INDEX ui_MyTable ON MyTable(Id); 
--select name from sysindexes where object_id('MyTable') = id;

--CREATE FULLTEXT CATALOG ft AS DEFAULT; 

--CREATE FULLTEXT INDEX ON MyTable(Name)   
--   KEY INDEX ui_MyTable  
--   WITH STOPLIST = SYSTEM;  
--GO  

--INSERT INTO MyTable(Name) VALUES('kayer-meyar'),('KA-ME');


ALTER FULLTEXT INDEX ON MyTable SET STOPLIST = OFF

select * 
from MyTable 
where CONTAINS(Name, '"ME*"')

select *
from MyTable 
where CONTAINS(Name, '"KA*"')

您描述的行为是正确使用系统停用词列表的结果。这是预期的行为。 "Me"是停用词,存在于系统停用词列表中。数据索引过程默认使用的系统停用词列表。

你可以用这个脚本检查自己:

select * from sys.dm_fts_parser('"KA-ME"', 1033, 0, 0)

这里的第三个参数是停用词列表标识符。当您传递 NULL 时,停用词不会在解析时被识别,您会看到 "ME" 类型 "Exact Match"。当您将 0 作为第三个参数传递时,将使用系统停用词列表,并且 "ME" 将属于 "Noise Word" 类型。这意味着SQL服务器不会将其保存到FTS索引中进行搜索。

正如 Raihan 所说,你可以关闭系统停用词列表,但对我来说,完全关闭停用词是一个太大的锤子,尤其是对于 Azure SQL 数据库,因为你应该支付额外的费用 space(FTS索引存储在同一个数据库的内部表中)。创建一个新的(更小的)停用词列表并将其用于 FTS 可能是更好的解决方案。