Использование полнотекстового поиска в SQL Server 2008 по нескольким таблицам и столбцам

StackOverflow https://stackoverflow.com/questions/403630

Вопрос

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

Причина, по которой я выбираю полнотекстовый поиск:1.Чтобы иметь возможность легко искать слова акцентированных слов (Cafè) 2.Уметь ранжировать по близости слов и т. д.3."Вы имели в виду ххх?" функциональность

Вот дурачок структура таблицы, чтобы проиллюстрировать задачу:

Настольная книга
BookID
Name (Full-text indexed)
Notes (Full-text indexed)

Настольная полка
ShelfID
BookID

Стол ПолкаАвтор
AuthorID
ShelfID

Таблица Автор
AuthorID
Name (Full-text indexed)

Мне нужно выполнить поиск по названию книги, примечаниям к книге и имени автора.

Я знаю два способа добиться этого:

  1. Использование полнотекстового индексированного представления: Это был бы мой предпочтительный метод, но я не могу этого сделать, потому что для полнотекстовой индексации представления оно должно быть привязано к схеме, не иметь каких-либо внешних соединений и иметь уникальный индекс.Представление, которое мне понадобится для получения данных, не удовлетворяет этим ограничениям (оно содержит множество других объединенных таблиц, из которых мне нужно получить данные).

  2. Использование объединений в хранимой процедуре:Проблема этого подхода в том, что мне нужно отсортировать результаты по рангу.Если я делаю несколько объединений между таблицами, SQL Server по умолчанию не будет выполнять поиск по нескольким полям.Я могу объединить два отдельных запроса CONTAINS к двум связанным таблицам, но не знаю, как извлечь комбинированный ранжирование по двум поисковым запросам.Например, если я ищу «Артур», результаты запроса «Книга» и «Автор» должны быть приняты во внимание и соответствующим образом взвешены.

Это было полезно?

Решение

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

SELECT b.Name, a.Name, bkt.[Rank] + akt.[Rank]/2 AS [Rank]
FROM Book b
INNER JOIN Author a ON b.AuthorID = a.AuthorID
INNER JOIN FREETEXTTABLE(Book, Name, @criteria) bkt ON b.ContentID = bkt.[Key] 
LEFT JOIN FREETEXTTABLE(Author, Name, @criteria) akt ON a.AuthorID = akt.[Key]
ORDER BY [Rank] DESC

Обратите внимание, что я упростил вашу схему для этого примера.

Другие советы

У меня была та же проблема, что и у вас, но на самом деле в ней участвовало 10 таблиц (таблица «Пользователи» и несколько других для информации)

Я выполнил свой первый запрос, используя FREETEXT в предложении WHERE для каждой таблицы, но запрос занимал слишком много времени.

Затем я увидел несколько ответов об использовании вместо этого FREETEXTTABLE и проверке ненулевых значений в ключевом столбце для каждой таблицы, но выполнение этого также заняло много времени.

Я исправил это, используя комбинацию выбора FREETEXTTABLE и UNION:

SELECT Users.* FROM Users INNER JOIN
(SELECT Users.UserId FROM Users INNER JOIN FREETEXTTABLE(Users, (column1, column2), @variableWithSearchTerm) UsersFT ON Users.UserId = UsersFT.key
UNION
SELECT Table1.UserId FROM Table1 INNER JOIN FREETEXTTABLE(Table1, TextColumn, @variableWithSearchTerm) Table1FT ON Table1.UserId = Table1FT.key
UNION
SELECT Table2.UserId FROM Table2 INNER JOIN FREETEXTTABLE(Table2, TextColumn, @variableWithSearchTerm) Table2FT ON Table2.UserId = Table2FT.key
... --same for all tables
) fts ON Users.UserId = fts.UserId

Это оказалось невероятно быстрее.

Я надеюсь, что это помогает.

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

Единственный способ, которым я вижу эту проблему, — это реплицировать столбцы автора, по которым вы хотите выполнять поиск, в таблице книги и индексировать эти столбцы (или столбец, поскольку, вероятно, было бы разумно хранить соответствующую информацию об авторе в столбце XML в книге). стол).

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

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

Select SearchResults.key, SearchResults.rank From FREETEXTTABLE(myColumn, *, @searchString) as SearchResults Order By SearchResults.rank Desc

Этот ответ уже давно назрел, но один из способов сделать это, если вы не можете изменить основные таблицы, — это создать новую таблицу с добавленными в один столбец параметрами поиска.

Затем создайте полнотекстовый индекс для этого столбца и запросите этот столбец.

Пример

SELECT 
    FT_TBL.[EANHotelID]                 AS HotelID, 
    ISNULL(FT_TBL.[Name],'-')           AS HotelName,
    ISNULL(FT_TBL.[Address1],'-')       AS HotelAddress,
    ISNULL(FT_TBL.[City],'-')           AS HotelCity,
    ISNULL(FT_TBL.[StateProvince],'-')  AS HotelCountyState,
    ISNULL(FT_TBL.[PostalCode],'-')     AS HotelPostZipCode,
    ISNULL(FT_TBL.[Latitude],0.00)      AS HotelLatitude,
    ISNULL(FT_TBL.[Longitude],0.00)     AS HotelLongitude,
    ISNULL(FT_TBL.[CheckInTime],'-')    AS HotelCheckinTime,
    ISNULL(FT_TBL.[CheckOutTime],'-')   AS HotelCheckOutTime,
    ISNULL(b.[CountryName],'-')         AS HotelCountry,
    ISNULL(c.PropertyDescription,'-')   AS HotelDescription,
    KEY_TBL.RANK 

    FROM [EAN].[dbo].[tblactivepropertylist] AS FT_TBL INNER JOIN
     CONTAINSTABLE ([EAN].[dbo].[tblEanFullTextSearch], FullTextSearchColumn, @s)
      AS KEY_TBL
    ON FT_TBL.EANHotelID = KEY_TBL.[KEY]
    INNER JOIN [EAN].[dbo].[tblCountrylist] b
    ON FT_TBL.Country = b.CountryCode
    INNER JOIN [EAN].[dbo].[tblPropertyDescriptionList] c
    ON FT_TBL.[EANHotelID] = c.EANHotelID

В приведенном выше коде [EAN].[dbo].[tblEanFullTextSearch] FullTextSearchColumn — это новая таблица и столбец с добавленными полями. Теперь вы можете выполнить запрос к новой таблице с объединениями с таблицей, из которой вы хотите отобразить данные. .

Надеюсь это поможет

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top