Полнотекстовый поиск - содержит подстановочный знак и одинарную кавычку
У меня есть таблица с полем имени с этим
Test O'neill 123
Если я использую
SELECT *
FROM table F
WHERE CONTAINS ( F.*, '"Test O''neill 123"' )
это работает нормально, но если я использую подстановочный знак *
Я не получаю результатов.
SELECT *
FROM table f
WHERE CONTAINS ( F.*, '"Test O''neill 123*"' )
почему это? Я использую синтаксический анализатор для моих условий поиска, и это добавляет подстановочный знак *
Я проверил несколько сайтов, чтобы избежать '
но я не нашел ничего, относящегося к этому..
Заранее спасибо
1 ответ
Проблема связана с комбинацией 1) использования нейтрального языка 2) плюс стоп-лист для вашего полнотекстового индекса 3) плюс неожиданное поведение при использовании подстановочного знака в поиске, включающем стоп-слова.
Нейтральный язык не охватывает все нюансы английского языка, поэтому в индексное время он учитывает O'neill
быть 2 отдельными словами O
а также neill
, Тогда ваш стоп-лист считает O
быть ключевым словом, так что это "слово" не добавляется в индекс, только neill
является.
Во время поиска поисковая система обычно игнорирует стоп-слова в словосочетаниях. Например, поиск Contains(*, '"we x people"')
будет соответствовать тексту ...we the people...
, x
а также the
оба являются стоп-словами и, таким образом, автоматически "совпадают" друг с другом. (Я использую термин "сопоставление" свободно, потому что поисковая система не сопоставляет стоп-слова, а скорее знает, что people
1 слово от we
.)
Таким образом, вы можете ожидать подстановочный поиск Contains(*, '"we the people*"')
также найти его соответствие, за исключением того, что он не находит при использовании стоп-листа. Если бы не стоп-слово the
в поисковой фразе, или если the
не считаться стоп-словом, поиск будет работать нормально. Я действительно не могу объяснить это поведение, но я подозреваю, что это как-то связано с тем, как вычисляются положения слов. Я также подозреваю, что это не предполагаемое поведение.
Итак, вернемся к вашему делу, Contains(*, '"Test O''neill 123"')
найдет совпадение, но поиск по шаблону Contains(*, '"Test O''neill 123*"')
не. (Вы можете даже упростить поиск Contains(*, '"O''neill*"')
и вы увидите, что он по-прежнему не находит соответствия.) Комбинация стоп-слов O
с подстановочным знаком сталкивается с проблемой, которую я объяснил в предыдущем абзаце. В этом суть проблемы, изложенной в вашем вопросе.
Решения от самых эффективных до наименее эффективных, но, возможно, более практичных для вашего случая:
1) Измените язык вашего полнотекстового индекса на английский и переиндексируйте. Это приведет к O'neill
будет рассматриваться как одно слово, и, таким образом, вы избежите странного подстановочного поведения, которое я объяснил. Вы можете изменить язык в свойствах полнотекстового индекса через SQL Server Management Studio или путем удаления и повторного создания индекса следующим образом:
ALTER FULLTEXT INDEX ON MyTable DROP (Column1)
GO
ALTER FULLTEXT INDEX ON MyTable ADD (Column1 LANGUAGE [English])
-- repeat for each column in the index
2) Если вам нужно продолжать использовать нейтральный язык, рассмотрите возможность удаления O
из вашего стоп-листа и переиндексации.
ALTER FULLTEXT STOPLIST MyStoplist DROP 'o' LANGUAGE 'Neutral';
3) Или не используйте стоп-лист, если он вам не нужен.
ALTER FULLTEXT INDEX ON MyTable SET STOPLIST = OFF
4) Если ни одно из приведенных выше решений не является практичным, рассмотрите возможность удаления стоп-слов из поисковой фразы или, по крайней мере, O'
префикс в фамилиях.