Полнотекстовый поиск SQL Server

В настоящее время я работаю над приложением, в котором у нас есть база данных SQL-Server, и мне нужно заставить работать полнотекстовый поиск, который позволяет нам искать имена людей.

В настоящее время пользователь может ввести в поле имени, которое ищет 3 разных столбца varchar. Имя, Фамилия, Отчество

Скажем, у меня есть 3 строки со следующей информацией.

1 - Филипп - Дж - Фрай

2 - Эми - NULL - Вонг

3 - Лео - NULL - Вонг

Если пользователь вводит имя, такое как «Фрай», он вернет строку 1. Однако, если они введут Филиппа Фрая, или Фра, или Фила, они ничего не получат ... и я не понимаю, почему он это делает. Если они ищут Вонга, они получают строки 2 и 3, если они ищут Эми Вонг, они снова ничего не получают.

В настоящее время запрос использует CONTAINSTABLE, но я переключил его на FREETEXTTABLE, CONTAINS и FREETEXT без каких-либо заметных различий в результатах. Табличные методы предпочтительнее, потому что они возвращают те же результаты, но с ранжированием.

Вот запрос.

....
@Name nvarchar(100),
....
--""s added to prevent crash if searching on more then one word.
DECLARE @SearchString varchar(100)
SET @SearchString = '"'+@Name+'"'
SELECT Per.Lastname, Per.Firstname, Per.MiddleName
FROM Person as Per
INNER JOIN CONTAINSTABLE(Person, (LastName, Firstname, MiddleName), @SearchString) 
AS KEYTBL
ON Per.Person_ID = KEYTBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEYTBL.RANK DESC;  
....

Есть идеи...? Почему этот полнотекстовый поиск работает некорректно?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
3 744
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

FreeTextTable должен работать.

INNER JOIN FREETEXTTABLE(Person, (LastName, Firstname, MiddleName), @SearchString) 

@SearchString должна содержать такие значения, как «Phillip Fry» (одна длинная строка, содержащая все строки поиска, разделенные пробелами).

Если вы хотите найти Fr или Phil, вы должны использовать звездочку: Phil * и Fr *

«Фил» ищет именно слово «Фил». "Фил *" ищет все слова, начинающиеся с "Фил".

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

Вы можете просто задать следующий запрос. Разделите строку поиска на пробелы и создайте список условий поиска.

Select FirstName,MiddleName,LastName 
From person 
WHERE 
Firstname like @searchterm1 + '%'
or MiddleName like @searchterm1 + '%'
or LastName like @searchterm1 + '%'
or Firstname like @searchterm2 + '%'
etc....

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

Другими словами, создайте представление о ваших данных, которое превращает все разделенные поля, такие как firstname lastname, в составные поля, то есть full_name

Затем выполните поиск по представлению. Это, вероятно, упростит поисковый запрос.

Ответ принят как подходящий

Спасибо за ответы, ребята, я наконец смог заставить его работать. С частью ответов как Бири, так и Кибби. Мне нужно было добавить * к строке и разбить ее на пробелы, чтобы работать. Итак, в конце концов я получил

....
@Name nvarchar(100),
....
--""s added to prevent crash if searching on more then one word.
DECLARE @SearchString varchar(100)

--Added this line
SET @SearchString = REPLACE(@Name, ' ', '*" OR "*')
SET @SearchString = '"*'+@SearchString+'*"'

SELECT Per.Lastname, Per.Firstname, Per.MiddleName
FROM Person as Per
INNER JOIN CONTAINSTABLE(Person, (LastName, Firstname, MiddleName), @SearchString) 
AS KEYTBL
ON Per.Person_ID = KEYTBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEYTBL.RANK DESC;  
....

Есть и другие поля, в которых ведется поиск. Я просто упростил его для вопроса, извините за это, я не думал, что это повлияет на ответ. На самом деле он выполняет поиск в столбце, в котором есть псевдонимы в формате CSV, а также столбец примечаний.

Спасибо за помощь.

Обратите внимание, что звездочки в качестве подстановочных знаков работают только при использовании в конец условия поиска. Звездочки в начале поискового запроса просто игнорируются системой полнотекстового поиска.

RSW 26.01.2013 20:05

Спасибо за ответ. Вы забыли Лилу и Бендера. Могу ли я использовать для этого Lucene?

Rony Tesler 25.09.2014 20:59

Возможно, вы захотите проверить Lucene.net в качестве альтернативы полному тексту.

Другие вопросы по теме