SQL 服务器上的全文搜索具有区分大小写的行为
Full-text search on SQL Server has case-sensitive behavior
我有一个包含空非索引字表的全文索引。
table 包含一个值为 'A. Beta' 的行。如果我搜索 'A. Beta' 或 'A. beta'(使用全文搜索),该行会正确显示。但是,如果我搜索 'a. Beta' 或 'a. beta',该行不会显示。
这是怎么回事?有没有好的解决方法?在将搜索字符串发送到数据库之前,我可以从搜索字符串中删除句点,但是还有什么我应该删除的吗?
示例:
CREATE TABLE mytable (
id BIGINT IDENTITY NOT NULL,
name VARCHAR(256) NOT NULL,
CONSTRAINT mytable_pk PRIMARY KEY (id)
);
CREATE FULLTEXT STOPLIST empty_stoplist;
CREATE FULLTEXT CATALOG mytable_catalog;
CREATE FULLTEXT INDEX ON mytable (
name Language 1033
)
KEY INDEX mytable_pk
ON mytable_catalog;
ALTER FULLTEXT INDEX ON mytable SET STOPLIST empty_stoplist;
ALTER FULLTEXT INDEX ON mytable START UPDATE POPULATION;
INSERT INTO mytable (name) VALUES ('A. Beta');
-- Wait until indexing is complete
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"A. Beta"');
-- 1 result
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"A. beta"');
-- 1 result
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"a. Beta"');
-- 0 results
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"a. beta"');
-- 0 results
运行 'A. Beta' 和 'a. Beta' 上的 fts 解析器给出了不同的结果。这可能是相关的:
-- Replace 7 with the id of 'empty_stoplist' or use NULL instead (same result).
select * from sys.dm_fts_parser('"A. Beta"', 1033, 7, 0)
-- keyword group_id phrase_id occurrence special_term display_term expansion_type source_term
-- 0x0061 1 0 1 Exact Match a 0 A. Beta
-- 0x0062006500740061 1 0 2 Exact Match beta 0 A. Beta
对比
-- Replace 7 with the id of 'empty_stoplist' or use NULL instead (same result).
select * from sys.dm_fts_parser('"a. Beta"', 1033, 7, 0)
-- keyword group_id phrase_id occurrence special_term display_term expansion_type source_term
-- 0x0061 1 0 1 Exact Match a 0 a. Beta
-- 0xFF 1 0 9 End Of Sentence END OF FILE 0 a. Beta
-- 0x0062006500740061 1 0 10 Exact Match beta 0 a. Beta
问题实际上不是区分大小写,而是 a. Beta
中的句点,全文解析器将其解释为 "end of sentence"。换句话说,解析器正确地将 A.
(大写)解释为缩写并忽略句点,但它认为 a.
(小写)是句子的结尾而不是缩写,因为缩写通常大写英语。全文引擎在计算单词出现次数时使用句末标记和段末标记,以避免在匹配引用短语时出现误报。 (除了来自 How Search Query Results Are Ranked 的模糊声明外,我对出现次数计数的工作原理知之甚少:为了避免短语和邻近查询中的误报,句尾和结尾- of-paragraph 引入更大的出现间隙。)
解决此问题的最简单方法是从搜索字符串中删除句点。您会发现这两个搜索都会 return 您要查找的 1 个结果。
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"A Beta"');
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"a Beta"');
根据微软 documentation :
Full-text queries are not case-sensitive. For example, searching for "Aluminum" or "aluminum" returns the same results.
问题与搜索条件以及查询的解析方式有关,如@Keith 所回答。
我有一个包含空非索引字表的全文索引。
table 包含一个值为 'A. Beta' 的行。如果我搜索 'A. Beta' 或 'A. beta'(使用全文搜索),该行会正确显示。但是,如果我搜索 'a. Beta' 或 'a. beta',该行不会显示。
这是怎么回事?有没有好的解决方法?在将搜索字符串发送到数据库之前,我可以从搜索字符串中删除句点,但是还有什么我应该删除的吗?
示例:
CREATE TABLE mytable (
id BIGINT IDENTITY NOT NULL,
name VARCHAR(256) NOT NULL,
CONSTRAINT mytable_pk PRIMARY KEY (id)
);
CREATE FULLTEXT STOPLIST empty_stoplist;
CREATE FULLTEXT CATALOG mytable_catalog;
CREATE FULLTEXT INDEX ON mytable (
name Language 1033
)
KEY INDEX mytable_pk
ON mytable_catalog;
ALTER FULLTEXT INDEX ON mytable SET STOPLIST empty_stoplist;
ALTER FULLTEXT INDEX ON mytable START UPDATE POPULATION;
INSERT INTO mytable (name) VALUES ('A. Beta');
-- Wait until indexing is complete
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"A. Beta"');
-- 1 result
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"A. beta"');
-- 1 result
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"a. Beta"');
-- 0 results
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"a. beta"');
-- 0 results
运行 'A. Beta' 和 'a. Beta' 上的 fts 解析器给出了不同的结果。这可能是相关的:
-- Replace 7 with the id of 'empty_stoplist' or use NULL instead (same result).
select * from sys.dm_fts_parser('"A. Beta"', 1033, 7, 0)
-- keyword group_id phrase_id occurrence special_term display_term expansion_type source_term
-- 0x0061 1 0 1 Exact Match a 0 A. Beta
-- 0x0062006500740061 1 0 2 Exact Match beta 0 A. Beta
对比
-- Replace 7 with the id of 'empty_stoplist' or use NULL instead (same result).
select * from sys.dm_fts_parser('"a. Beta"', 1033, 7, 0)
-- keyword group_id phrase_id occurrence special_term display_term expansion_type source_term
-- 0x0061 1 0 1 Exact Match a 0 a. Beta
-- 0xFF 1 0 9 End Of Sentence END OF FILE 0 a. Beta
-- 0x0062006500740061 1 0 10 Exact Match beta 0 a. Beta
问题实际上不是区分大小写,而是 a. Beta
中的句点,全文解析器将其解释为 "end of sentence"。换句话说,解析器正确地将 A.
(大写)解释为缩写并忽略句点,但它认为 a.
(小写)是句子的结尾而不是缩写,因为缩写通常大写英语。全文引擎在计算单词出现次数时使用句末标记和段末标记,以避免在匹配引用短语时出现误报。 (除了来自 How Search Query Results Are Ranked 的模糊声明外,我对出现次数计数的工作原理知之甚少:为了避免短语和邻近查询中的误报,句尾和结尾- of-paragraph 引入更大的出现间隙。)
解决此问题的最简单方法是从搜索字符串中删除句点。您会发现这两个搜索都会 return 您要查找的 1 个结果。
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"A Beta"');
SELECT * FROM mytable mt WHERE CONTAINS(mt.*, '"a Beta"');
根据微软 documentation :
Full-text queries are not case-sensitive. For example, searching for "Aluminum" or "aluminum" returns the same results.
问题与搜索条件以及查询的解析方式有关,如@Keith 所回答。