Преобразование введенного пользователем поискового запроса в предложение where для использования в полнотекстовом поиске SQL Server
-
21-08-2019 - |
Вопрос
Каков наилучший способ преобразовать поисковые запросы, введенные пользователем, в запрос, который можно использовать в предложении where для полнотекстового поиска, чтобы запросить таблицу и получить обратно соответствующие результаты?Например, следующий запрос, введенный пользователем:
+"e-mail" +attachment -"word document" -"e-learning"
Должно переводиться во что-то вроде:
SELECT * FROM MyTable WHERE (CONTAINS(*, '"e-mail"')) AND (CONTAINS(*, '"attachment"')) AND (NOT CONTAINS(*, '"word document"')) AND (NOT CONTAINS(*, '"e-learning"'))
Я использую класс анализатора запросов на данный момент, который анализирует запрос, введенный пользователями, в токены, используя регулярное выражение, а затем создает предложение where из токенов.
Однако, учитывая, что это, вероятно, общее требование многих систем, использующих полнотекстовый поиск, мне любопытно, как другие разработчики подошли к этой проблеме и есть ли лучший способ сделать что-то.
Решение
Возможно, это не совсем то, что вы ищете, но это может предложить вам некоторые дополнительные идеи.
http://www.sqlservercentral.com/articles/Full-Text+Search +(2008)/64248/
Другие советы
Как реализовать принятый ответ, используя .Net / C # / Entity Framework...
Установите Irony с помощью nuget.
Добавьте образец класса из:http://irony.codeplex.com/SourceControl/latest#Irony .Образцы/FullTextSearchQueryConverter/SearchGrammar.cs
Напишите подобный код, чтобы преобразовать введенную пользователем строку в запрос.
var grammar = new Irony.Samples.FullTextSearch.SearchGrammar(); var parser = new Irony.Parsing.Parser(grammar); var parseTree = parser.Parse(userEnteredSearchString); string query = Irony.Samples.FullTextSearch.SearchGrammar.ConvertQuery(parseTree.Root);
Возможно, напишите хранимую процедуру, подобную этой:
create procedure [dbo].[SearchLivingFish] @Query nvarchar(2000) as select * from Fish inner join containstable(Fish, *, @Query, 100) as ft on ft.[Key] = FishId where IsLiving = 1 order by rank desc
Запустите запрос.
var fishes = db.SearchLivingFish(query);
В дополнение к приведенному выше ответу @franzo вы, вероятно, также захотите изменить поведение стоп-слова по умолчанию в SQL.В противном случае запросы, содержащие однозначные числа (или другие стоп-слова), не вернут никаких результатов.
Либо отключите стоп-слова, создайте свой собственный список стоп-слов и / или задайте преобразование шумовых слов, как описано в SQL 2008:Отключите стоп-слова для полнотекстового поискового запроса
Чтобы просмотреть системный список (английских) стоп-слов sql, выполните:
select * from sys.fulltext_system_stopwords where language_id = 1033
Я понимаю, что это немного отступление от вашего первоначального вопроса, но рассматривали ли вы возможность отказа от полнотекстовых индексов SQL и использования чего-то вроде Lucene/Солр вместо этого?
Самый простой способ сделать это - использовать динамический SQL (я знаю, вставьте здесь вопросы безопасности) и разбить фразу на правильно отформатированную строку.
Вы можете использовать функцию для преобразования фразы в табличную переменную, которую можно использовать для создания новой строки.
Комбинация GoldParser и Calitha должна помочь вам разобраться здесь.
Эта статья: http://www.15seconds.com/issue/070719.htm также имеет класс googleToSql, который выполняет часть перевода за вас.