2012-03-04 3 views
4

Я работаю над проектом с SQL Server 2008, где, я считаю, поиск в полнотекстовом режиме - лучший способ. Я читал на нем столько, сколько могу, и очень понимаю, что он хотел настроить его для одной таблицы. Однако я не совсем уверен, как это сделать с моим сценарием - представьте себе следующую структуру таблицы:Полностью текстовый поиск SQL Server - отношение «многие ко многим»

Книга

- Id 
- Title 
- Description 

BookAuthor

- BookId 
- AuthorId 

Автор

- Id 
- Name 

Как вы можете видеть, база данных содержит таблицу с книгами, и в каждой книге нет ни одного, ни одного автора. Каждый автор также может быть частью ни одного, одного или многих книг, то есть таблицы Book и Author имеют отношение «многие ко многим», обрабатываемые со ссылкой на таблицу BookAuthor.

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

Book.Title 
Book.Description 
Author.Name 

В сущности, я хочу результирующее множество книг, в том числе как книгу с названием Brown Bear и книги, написанные автором Dan Brown. Если есть какие-то предложения относительно того, как я должен это сделать, я бы очень признателен за ваш вклад!

(как примечание стороны, когда у меня есть эта фильтрующая работа, результат запроса также необходим будет сортировкой и выгружаемыми, обрабатывается с помощью @SortOrder, @PageIndex и @PageSize передавались в хранимую процедуру - но я думаю, что может быть отдельный вопрос после этого!)

+0

Почему вы используете полнотекстовый поиск, это достойное решение здесь? Это похоже на нормальный дизайн databae для меня. – TomTom

+0

Возможный дубликат [Использование полнотекстового поиска в SQL Server 2008 для нескольких таблиц, столбцов] (http://stackoverflow.com/questions/403630/using-full-text-search-in-sql-server-2008-across -multiple-tables-columns) –

+0

@TomTom Поиск «Брауна», как указано выше, является просто упрощенным примером того, что я хочу достичь. Мне нужно найти x количество слов, и использование LIKE не будет работать.В будущем мы также захотим найти строки, которые соответствуют _almost_, и для этого потребуется полнотекстовый поиск (насколько я знаю). – Iskariot

ответ

2

Предикат СОДЕРЖИТ может взять список столбцов для поиска в качестве своего первого аргумента; однако эти столбцы должны быть из одной таблицы. У вас есть несколько вариантов обойти это ограничение. Один из вариантов состоит в том, что вы можете выполнять два отдельных поиска, по одному на каждую таблицу, а затем вместе СОЕДИНЯТЬ результаты.

select Id, Title from Book where contains([Description], 'brown') 
union 
select b.Id, b.Title 
    from Book b inner join BookAuthor ba on b.Id = ba.BookId 
     inner join Author a on a.Id=ba.AuthorId 
    where contains([Name], 'brown') 

Другой вариант, чтобы воспользоваться тем, что FTS indexes can be created on indexed views. Для этого создайте индексированное представление, содержащее как поле Title из таблицы Book, так и поле Name в таблице Author, а затем создайте индекс FTS для обоих этих столбцов в представлении. Затем вы можете писать запросы в этом представлении следующим образом:

select BookId, Title from vw_BooksAndAuthors 
where contains(([Description], [Name]), 'brown') 
+0

Спасибо за предложения Джо! # 1 Я определенно вижу, что это даст правильные результаты - есть ли у вас какие-либо идеи о производительности, хотя с двумя запросами и объединением? Скажем, что в книге есть описание, соответствующее поиску, и 5 отдельных авторов, которые соответствуют - одна и та же книга будет найдена 6 раз, прежде чем они будут «объединены» с утверждением union. – Iskariot

+0

Правильно, производительность двух запросов и объединения определенно будет хуже, чем у одного запроса. Есть некоторые вещи, которые вы, возможно, захотите рассмотреть по соображениям производительности, но прежде чем инвестировать время в это, вы должны сначала установить, что производительность будет проблемой в вашем приложении, а не тратить время на преждевременную оптимизацию. Если вы хотите оптимизировать производительность, у вас может быть задание, которое периодически запускает и агрегирует содержимое таблиц книги и автора в единую таблицу ненормированной таблицы, а затем запрашивает единую таблицу с деноминацией. –

+0

Да, я тоже думал об этом варианте, чтобы в основном иметь таблицу BookIndex, в которой есть BookId, и один/много дополнительных столбцов, которые имеют всю необходимую информацию для поиска, например Title, Description, каждое имя автора, агрегированное в одной строке в этой таблице. Затем полнотекстовый индекс, который один, и присоедините его к Книжной таблице при поиске. Я думаю, что я попробую ваше первое предложение выше с профсоюзом, но если производительность станет проблемой, я пойду по этому пути. Большое спасибо за ваш вклад! – Iskariot

Смежные вопросы