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

Примечание: Я имею в использовании функции поиска полнотекстовой SQL для , СОДЕРЖИТ положение и все - * является подстановочным в полном тексте,% только для статей LIKE.

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

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

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

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

Ответов (13)

Note: this was the answer I submitted for the original version #1 of the question before the CONTAINS keyword was introduced in revision #2. It's still factually accurate.

The wildcard character in SQL Server is the % sign and it works just fine, leading, trailing or otherwise.

That said, if you're going to be doing any kind of serious full text searching then I'd consider utilising the Full Text Index capabilities. Using % and _ wild cards will cause your database to take a serious performance hit.

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

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

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

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

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

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

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)

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

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

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

    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

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

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

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

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

From SQL Server Books Online:

To write full-text queries in Microsoft SQL Server 2005, you must learn how to use the CONTAINS and FREETEXT Transact-SQL predicates, and the CONTAINSTABLE and FREETEXTTABLE rowset-valued functions.

That means all of the queries written above with the % and _ are not valid full text queries.

Here is a sample of what a query looks like when calling the CONTAINSTABLE function.

SELECT RANK , * FROM TableName , CONTAINSTABLE (TableName, *, ' "*WildCard" ') searchTable WHERE [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 записей.

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

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

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

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

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

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

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

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

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

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

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

Чтобы, возможно, внести ясность в эту ветку, из моего тестирования на 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