SQL Server полнотекстовый поиск по номерам и символам подчеркивания

использование SQL Server 2012 (в целом с использованием SQL Server 2008 R2 до SQL Server 2016)

этот вопрос является более конкретной формулировкой SQL-Server полнотекстовый индекс неожиданные результаты. Пожалуйста, посмотрите здесь, как мы дошли до этого момента и что уже пробовали.

Я повторно публикую теперь, когда мы нашли конкретную ошибку. Большое спасибо @HoneyBadger.

его помощь была неоценимой, чтобы добраться до этого точка.

структура таблицы:

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

данные:

INSERT INTO TestFullTextSearch 
VALUES (1, ' 123_456 789 '), (2, ' 789 123_456 '),
       (3, ' 123_456 ABC '), (4, ' ABC 123_456 ')

обратите внимание, что эти данные предназначены исключительно для демонстрации проблемы и не указывают на живой набор данных. Наши живые наборы данных могут быть более 500 000 строк, с абзацами данных в одном поле поиска-следовательно, с использованием полнотекстового поиска.

выберите 1: результаты

SELECT *
FROM TestFullTextSearch
WHERE CONTAINS (AllText, '"123*"')

Id          AllText
----------- ------------
1            123_456 789
2            789 123_456
3            123_456 ABC
4            ABC 123_456

выберите 2: пропускает строку 2 в результирующий набор

SELECT *
FROM TestFullTextSearch
WHERE CONTAINS (AllText, '"123_*"')

Id          AllText
----------- ------------
1            123_456 789
3            123_456 ABC
4            ABC 123_456

выберите 3: возвращает только строку 2

SELECT *
FROM TestFullTextSearch
WHERE CONTAINS (AllText, '"123_*"')

Id          AllText
----------- ------------
2            789 123_456

вывод: Поиск числовой строки с суффиксом подчеркивания не выполняется, если предыдущее слово является числовой строкой.

: наши клиенты используют полнотекстовый поиск и ожидают, что результат будет приходить вокруг номеров деталей и ссылок каталога, которые могут или не могут быть в разделе текста, включая другие числовые строки. Полнотекстовый поиск не поддерживает это последовательно.

любая помощь с благодарностью получил.

NB: эта проблема не возникает на SQL SERVER 2008, но на 2012+

Я также попытался переключиться на более старую версию парсера FTS. Тестирование с помощью

SELECT * FROM sys.dm_fts_parser (' "789 123_456" ',1033,0,0)
SELECT * FROM sys.dm_fts_parser (' "789 123_456" ',2057,0,0)

у меня был с текущим парсером: enter image description here

и после возврата к устаревшему синтаксическому анализатору: enter image description here

так это оказывает влияние, однако я все еще получаю те же результаты.

существуют ли какие-либо другие различия в полнотекстовом поиске между 2008 и 2012 годами, которые могут иметь этот эффект?

4 ответов


Они изменили полнотекстовые синтаксические анализаторы / стеммеры между SQL 2008 и SQL 2012.

С изменением реестра, вы можете использовать устаревший парсер, который должен работать лучше в вашей ситуации.

см.https://technet.microsoft.com/en-us/library/gg509108 (v=sql.110).aspx для деталей.

Если вам нужно поддерживать как старый, так и новый стиль, то вы можете вернуть нам английский на старый и сохранить английский английский новый (или наоборот)

использование SQL 2016, я вернулся Великобритания английский и держал нас английский же:

exec sp_help_fulltext_system_components 'wordbreaker', 1033

exec sp_help_fulltext_system_components 'wordbreaker', 2057

возвращает: Screenshot showing fts components

Я создал другую таблицу, используя UK English и заполнил ее.

CREATE TABLE TestFullTextSearch2 (Id INT NOT NULL, AllText NVARCHAR(400))

CREATE UNIQUE INDEX test_tfts2 ON TestFullTextSearch2(Id)


CREATE FULLTEXT INDEX ON TestFullTextSearch2(AllText language 2057)
    KEY INDEX test_tfts2 ON ftcat_tfts 
    WITH CHANGE_TRACKING AUTO, STOPLIST OFF

    INSERT INTO TestFullTextSearch2
VALUES (1, ' 123_456 789 '), (2, ' 789 123_456 '),
       (3, ' 123_456 ABC '), (4, ' ABC 123_456 ')

Я получаю ожидаемые результаты 4 для всех 3-х запросов.

Results of FTS queries

убедитесь, что изменения вступили в силу.

exec sp_help_fulltext_system_components 'wordbreaker', 1033

exec sp_help_fulltext_system_components 'wordbreaker', 2057

select t.name, c.* from sys.tables t inner join sys.fulltext_index_columns c on t.object_id = c.object_id

проблема здесь в основном заключается в том, как MSSQL 2012 хранит индекс и как сам запрос обрабатывает подчеркивание _.

это становится ясно при осмотре индекс ключевых слов & парсер fts. Для строки 2 ключевое слово 123_456 не сохраняется как таковое из-за числового значения, находящегося перед ним. Однако парсер fts будет искать точное совпадение на "123_" и не удаляет подчеркивание.

select * from sys.dm_fts_index_keywords_by_document
( 
    DB_ID('TestDatabase'),     
    OBJECT_ID('TestFullTextSearch') 
) order by document_id

select * from sys.dm_fts_parser('"123_*"', 0, 0, 0)

один решением было бы изменить слово breaker для конкретного языка. Вы можете легко заменить его на dll Word breaker из MSSQL 2008 или 2016, где эта проблема не возникает. (например, возьмите один для нейтрального языка: NaturalLanguage6.файл DLL.) Обязательно создайте полнотекстовый индекс для того же языка.

чтобы найти зарегистрированные средства разбиения слов и где расположены dll, используйте этот запрос:

EXEC sp_help_fulltext_system_components 'wordbreaker';

почему бы вам не использовать LIKE оператор? Попробуй!--2-->, он вернет все четыре строки.

другое решение будет использовать CHARINDEX, например:

where charindex('123_', AllText) > 0

0 означало бы, что строка не найдена внутри другой.


если у вас есть проблема с полнотекстовым поиском с вышеуказанным запросом упоминания @Michal, то есть другое альтернативное решение, которое вы можете применить, как показано ниже:

  1. при вставке AllText в базе данных поддерживайте другой столбец, который содержит флаг (boolean), указывающий include 123, Так что во время SELECT оператор просто проверьте этот флаг.
  2. поддерживать вычисляемый столбец с формулой шаблона, которые возвращают true или false.