Как заставить ведущие полнотекстовые поисковые запросы работать в SQL Server? - PullRequest
39 голосов
/ 06 августа 2008

Примечание: I am с использованием возможностей полнотекстового поиска SQL, предложений CONTAINS и всего - * является подстановочным знаком в полнотекстовом формате,% - только для предложений LIKE.

В некоторых местах я читал, что поиск с «подстановочными символами» (например, использование «* overflow» для сопоставления со «stackoverflow») не поддерживается в MS SQL. Я рассматриваю возможность использования функции CLR для добавления соответствия регулярному выражению , но мне любопытно посмотреть, какие другие решения могут быть у людей.

Подробнее : Вы можете добавить звездочку только в конце слова или фразы. - вместе с моим эмпирическим опытом: при сопоставлении «myvalue», «my *» работает, но «(звездочка) значение» не возвращает совпадения, если выполнять запрос так же просто, как:

SELECT * FROM TABLENAME WHERE CONTAINS(TextColumn, '"*searchterm"');

Таким образом, моя потребность в обходном пути. Я использую поиск на своем сайте только на реальной поисковой странице - поэтому он должен работать в основном так же, как работает Google (в глазах пользователя типа Джо Сикспака). Не так сложно, но такое совпадение не должно провалиться.

Ответы [ 13 ]

22 голосов
/ 24 сентября 2008

Обходной путь только для ведущего символа подстановки:

  • сохранить перевернутый текст в другом поле (или в материализованном виде)
  • создать полнотекстовый индекс для этого столбца
  • найти перевернутый текст с *

    SELECT * 
    FROM TABLENAME 
    WHERE CONTAINS(TextColumnREV, '"mrethcraes*"');
    

Конечно, есть много недостатков, только для быстрого обхода ...

Не говоря уже о CONTAINSTABLE ...

14 голосов
/ 06 августа 2008

Проблема с ведущими символами подстановки: они не могут быть проиндексированы, поэтому вы выполняете полное сканирование таблицы.

6 голосов
/ 26 ноября 2008

Можно использовать подстановочный знак "*" в конце слова или фразы (поиск префикса).

Например, этот запрос найдет все «данные», «база данных», «базы данных» ...

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"datab*"')

Но, к сожалению, невозможно выполнить поиск с использованием символа подстановки.

Например, этот запрос не найдет «базу данных»

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')
4 голосов
/ 06 октября 2011

Чтобы, возможно, внести ясность в эту ветку, после моего тестирования на 2008 R2 Франьо правильно сказал выше. При работе с полнотекстовым поиском, по крайней мере, при использовании фразы CONTAINS, вы не можете использовать ведущий , только трейлинг функционально. * подстановочный знак, а не% в полном тексте.

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

Моя дополнительная проблема, однако, заключается в том, что тот же запрос с завершающим символом *, который использует полный текст с подстановочными знаками, работал относительно быстро в 2005 году (20 секунд) и замедлился до 12 минут после переноса базы данных в 2008 R2. Похоже, что по крайней мере еще у одного пользователя были похожие результаты, и он создал пост на форуме, который я добавил ... FREETEXT все еще работает быстро, но что-то "кажется" изменилось в связи с тем, что процессы 2008 тянулись * в CONTAINS. Они дают всевозможные предупреждения в помощнике по обновлению о том, что они «улучшили» полный текст, чтобы ваш код мог сломаться, но, к сожалению, они не дают вам никаких конкретных предупреждений об определенном устаревшем коде и т. Д. ... просто отказ от ответственности, что они изменили его Используйте на свой риск.

http://social.msdn.microsoft.com/Forums/ar-SA/sqlsearch/thread/7e45b7e4-2061-4c89-af68-febd668f346c

Может быть, это ближайший MS-ответ, связанный с этими проблемами ... http://msdn.microsoft.com/en-us/library/ms143709.aspx

3 голосов
/ 06 августа 2008

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

2 голосов
/ 06 августа 2008

Подстановочный знак в SQL Server - это знак %, и он работает просто отлично, в начале, в конце или в противном случае.

Тем не менее, если вы собираетесь заниматься каким-либо серьезным полнотекстовым поиском, я бы подумал об использовании возможностей полнотекстового индекса. Использование подстановочных знаков % и _ приведет к серьезному снижению производительности вашей базы данных.

1 голос
/ 05 января 2016

В качестве параметра хранимой процедуры вы можете использовать его как:

ALTER procedure [dbo].[uspLkp_DrugProductSelectAllByName]
(
    @PROPRIETARY_NAME varchar(10)
)
as
    set nocount on
    declare @PROPRIETARY_NAME2 varchar(10) = '"' + @PROPRIETARY_NAME + '*"'

    select ldp.*, lkp.DRUG_PKG_ID
    from Lkp_DrugProduct ldp
    left outer join Lkp_DrugPackage lkp on ldp.DRUG_PROD_ID = lkp.DRUG_PROD_ID
    where contains(ldp.PROPRIETARY_NAME, @PROPRIETARY_NAME2)
1 голос
/ 16 сентября 2008

Только к вашему сведению, Google не выполняет поиск или усечение подстрок, ни вправо, ни влево. У них есть подстановочный знак * для поиска неизвестных слов во фразе, но не слова.

Google, наряду с большинством полнотекстовых поисковых систем, устанавливает инвертированный индекс на основе алфавитного порядка слов со ссылками на их исходные документы. Бинарный поиск быстро работает даже для огромных индексов. Но в этом случае действительно трудно выполнить усечение влево, потому что оно теряет преимущество индекса.

1 голос
/ 06 августа 2008

Из электронной документации по SQL Server:

Для написания полнотекстовых запросов в Microsoft SQL Server 2005, вы должны узнать, как использовать СОДЕРЖАНИЕ и Предикаты FREETEXT Transact-SQL и СОДЕРЖАЩАЯ и СВОБОДНАЯ ТЕКСТА функции со значением набора строк.

Это означает, что все запросы, написанные выше с% и _, не являются допустимыми полнотекстовыми запросами.

Вот пример того, как выглядит запрос при вызове функции CONTAINSTABLE.

SELECT RANK, * FROM TableName, CONTAINSTABLE (TableName, *, ' "* WildCard" ') searchTable ГДЕ [KEY] = TableName.pk ORDER BY searchTable.RANK DESC

Чтобы функция CONTAINSTABLE знала, что я использую поиск по шаблону, мне нужно заключить его в двойные кавычки. Я могу использовать подстановочный знак * в начале или конце. Есть много других вещей, которые вы можете сделать, когда строите строку поиска для функции CONTAINSTABLE. Вы можете искать слово рядом с другим словом, искать слова со словами (диск = диски, водил, водил и водил) и искать синоним другого слова (у металла могут быть синонимы, такие как алюминий и сталь).

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

[Update]

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

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

Example:  "*ildcar" will look for a single word as long as it ends with "ildcar".

Example:  "*ildcar*" will look for a single word with "ildcar" in the middle, which means it will match "wildcard".  [Just noticed that Markdown removed the wildcard characters from the beginning and ending of my quoted string here.]

[Обновление № 2]

Дейв Уорд - Использование подстановочного знака с одной из функций не должно быть огромным хитом. Если я создал строку поиска только с "*", он не вернет все строки, в моем тестовом случае он вернул 0 записей.

0 голосов
/ 02 июля 2018

Если у вас есть доступ к списку слов в полнотекстовой поисковой системе, вы можете выполнить поиск по этому списку и сравнить базу данных с найденными словами, например таблица слов со следующими словами:

    pie
    applepie
    spies
    cherrypie
    dog
    cat

Чтобы сопоставить все слова, содержащие «pie» в этой базе данных в таблице fts «full_text» с полем «text»:

    to-match <- SELECT word FROM words WHERE word LIKE '%pie%'
    matcher = ""
    a = ""
    foreach(m, to-match) {
      matcher += a
      matcher += m
      a = " OR "
    }
    SELECT text FROM full_text WHERE text MATCH matcher
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...