Как заставить лидирующий полнотекстовый поиск с подстановочными знаками работать в SQL Server?

Примечание. Я я использую возможности полнотекстового поиска SQL, предложения CONTAINS и все остальное - * - это подстановочный знак в полнотекстовом тексте,% - только для предложений LIKE.

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

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

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

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


person Greg Hurlman    schedule 06.08.2008    source источник


Ответы (13)


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

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

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

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

Не говоря уже о СОДЕРЖИМОСТИ ...

person xnagyg    schedule 23.09.2008

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

person Michael Stum    schedule 06.08.2008

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

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

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

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

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

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')
person Community    schedule 26.11.2008
comment
Я выполнил довольно много поисков именно этого, и, к сожалению, большинство людей ошибаются и думают, что они могут выполнить поиск по шаблонам с опережением. Поиск по подстановочным знакам впереди не работает. Franjo прав, подстановочный знак должен стоять в конце поисковой фразы. Я использую SQL 2008 R2. Он его вообще не находит (он не выполняет сканирование таблицы или индекса и не находит его - он вообще не находит) - person astrosteve; 02.03.2016

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

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

Однако моя дополнительная проблема заключается в том, что тот же запрос с завершающим *, который использует полный текст с подстановочными знаками, работал относительно быстро в 2005 году (20 секунд) и замедлился до 12 минут после миграции db на 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

person Forrest    schedule 06.10.2011

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

person Dave Ward    schedule 06.08.2008

Примечание: это был ответ, который я отправил на исходную версию №1 вопроса до того, как ключевое слово CONTAINS было введено в редакцию №2. Это по-прежнему достоверно.

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

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

person Kev    schedule 06.08.2008
comment
Учитывая, что он использовал ключевое слово CONTAINS, похоже, он уже использует полнотекстовое индексирование. - person PRMan; 21.07.2020
comment
@PRMan - Я ответил на ревизию №1 вопроса до того, как было упомянуто ключевое слово CONTAINS. Это было очень давно. - person Kev; 21.07.2020

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

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

person user9569    schedule 16.09.2008

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

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)
person ASP Force    schedule 04.01.2016

Что касается полнотекстового поиска, за мои деньги нет ничего лучше Lucene. Имеется .Net-порт, совместимый с индексами, созданными с помощью Java. версия.

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

Например, эта функция поиска поддерживается Lucene.Net.

person Sean Carpenter    schedule 08.08.2008

Возможно, следующая ссылка даст окончательный ответ на такое использование подстановочных знаков: Выполнение поиска по подстановочным знакам FTS.

Обратите внимание на отрывок, который гласит: «Однако, если вы укажете« Chain »или« Ch ain », вы не получите ожидаемого результата. Звездочка будет считаться обычным знаком препинания, а не подстановочным знаком. . "

person LogicalMan    schedule 18.10.2016

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

    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
person Hans    schedule 02.07.2018

% Соответствует любому количеству символов _ Соответствует одиночному символу

Я никогда не использовал полнотекстовую индексацию, но вы можете выполнять довольно сложные и быстрые поисковые запросы, просто используя встроенные строковые функции T-SQL.

person GateKiller    schedule 06.08.2008

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

Чтобы писать полнотекстовые запросы в Microsoft SQL Server 2005, вы должны научиться использовать предикаты Transact-SQL CONTAINS и FREETEXT, а также функции CONTAINSTABLE и FREETEXTTABLE, возвращающие значения наборов строк.

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

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

ВЫБРАТЬ РАНГ, * ​​FROM TableName, CONTAINSTABLE (TableName, *, '"* WildCard"') searchTable ГДЕ [KEY] = TableName.pk ORDER BY searchTable.RANK DESC

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

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

[Обновлять]

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

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

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 записей.

person Otto    schedule 06.08.2008
comment
Я не могу воспроизвести это в SQL 2005. Использование * в начале строки поиска, как показано, не приводит к возвращенным строкам. - person gregmac; 15.09.2009
comment
Не уверен, почему это помечено как ответ, потому что это не совсем точно. Подстановочный знак в начале не работает при полнотекстовом поиске. Проверено в SQL Server 2008 для полнотекстового индекса с помощью функции containstable. См. Ответ / сообщение Майкла Стума, чтобы понять, почему. - person Jagd; 04.04.2011
comment
@Jagd - Тогда дайте лучший ответ. - person Greg Hurlman; 06.10.2011
comment
Согласовано с @Jagd, это должно быть отклонено и не помечено как ответ. OP явно говорит об индексах FT (отсюда * как подстановочный знак), и совершенно неправильно утверждать, что * работает как префикс в операции с индексом FT. Я счастлив, что ошибся, но не думаю, что это так. - person John B; 23.12.2011
comment
Когда я задал этот вопрос, он основывался на том, как SQL 2005 работает с полнотекстовыми индексами, поэтому я сослался на электронную документацию 2005 года. - person Otto; 13.05.2012
comment
ведущий подстановочный знак не работает в sqlserver, поэтому этот ответ неверен с точки зрения исходного вопроса. - person Evert; 19.04.2013
comment
Здесь следует отметить двойные кавычки внутри одинарных кавычек. В моей исходной функции был термин «термин *», это НЕ сработало. Однако термин * имеет значение. Спасибо - person Yablargo; 09.05.2014