Преобразование введенного пользователем запроса поискового запроса в предложение where для полнотекстового поиска SQL Server

Какой лучший способ конвертировать поисковые запросы, введенные пользователем, в запрос, который может использоваться в предложении 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 из токенов.

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

Ответ 2

Как реализовать принятый ответ с использованием .Net/С#/Entity Framework...

  • Установите Ирония, используя nuget.

  • Добавить класс образца из: http://irony.codeplex.com/SourceControl/latest#Irony.Samples/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);
    

Ответ 3

В дополнение к ответу @franzo выше вы, вероятно, также захотите изменить поведение стоп-слова по умолчанию в SQL. В противном случае запросы, содержащие однозначные числа (или другие слова остановки), не возвратят никаких результатов.

Либо отключите стоп-слова, создайте свой собственный список стоп-слов и/или установите шумовые слова, которые будут преобразованы, как объяснено в SQL 2008: Отключить стоп-слова для запроса полного текста

Чтобы просмотреть системный список (английских) слов sql stop, запустите:

select * from sys.fulltext_system_stopwords where language_id = 1033

Ответ 4

Я понимаю это немного побочный шаг от вашего первоначального вопроса, но вы подумали о том, чтобы отойти от полнотекстовых индексов SQL и использовать что-то вроде Lucene/Solr вместо этого?

Ответ 5

Самый простой способ сделать это - использовать динамический SQL (я знаю, вставьте проблемы безопасности здесь) и сломал фразу в правильно отформатированную строку.

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

Ответ 6

Комбинация GoldParser и Calitha должна отсортировать вас здесь.

В этой статье: http://www.15seconds.com/issue/070719.htm имеет класс googleToSql, который выполняет некоторые переводы для вас.