Полнотекстовый индекс в представлении MySQL или правильный способ поиска в объединенных таблицах - PullRequest
1 голос
/ 07 марта 2011

Хотя эта тема широко обсуждалась, она очень смутила меня, и я не смог найти правильный ответ.Не могли бы вы помочь мне в правильном направлении?Спасибо.

У меня есть эта настройка: таблица page связана с таблицей widget посредством справочной таблицы widget_to_page:

page (p) sid | title | content виджет (ш) sid | content widget_to_page (wtp) sid | page_sid | widget_sid

Я создал полнотекстовый индекс для p.title, p.content, w.content

Далее, я хотел бы использовать комбинацию page-widget:

SELECT *, MATCH(p.title, p.content, w.content) AGAINST("'.$keyword.'") AS score 
FROM page p, widget w, widget_to_page wtp
WHERE MATCH(p.title, p.content, w.content) AGAINST("'.$keyword.'")
AND p.sid = wtp.page_sid
AND w.sid = wtp.widget_sid
ORDER BY score DESC

Некоторые замечания:

  1. Это, очевидно, не работает ...: -)
  2. Я читал, что если я использую этот синтаксис для объединения таблиц (или используйте оператор JOIN), чтобы MySQL игнорировал полнотекстовый индекс.Какой правильный метод?

Альтернатива, которую я попробовал, состояла в том, чтобы создать представление MySQL из следующего утверждения:

SELECT * 
FROM page p, widget w, widget_to_page wtp
WHERE p.sid = wtp.page_sid
AND w.sid = wtp.widget_sid

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

Короче ... что такоелучшая практика в такой ситуации?Спасибо.

1 Ответ

3 голосов
/ 07 марта 2011

Индекс FULLTEXT может включать несколько столбцов, но эти столбцы должны находиться в одной таблице. Таким образом, вы не сможете охватить эти 3 столбца из 2 таблиц в одном индексе. Для этого вам понадобится как минимум 2 индекса.

Кроме того, индексы FULLTEXT работают только с механизмом хранения MyISAM, поэтому, если вы используете механизм транзакций, такой как InnoDB, это не будет работать. Вам следует прочитать руководство, чтобы узнать о других функциях и ограничениях полнотекстовых индексов (включая логический режим, стоп-слова и т. Д.):

http://dev.mysql.com/doc/refman/5.1/en/fulltext-search.html

Предполагая, что вы используете MyISAM, вы можете создать 1 полнотекстовый индекс для (p.title, p.content) и другой полнотекстовый индекс для (w.content), затем запросить два индекса по отдельности и использовать UNION ALL для объединения результатов .

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

select page_sid, page_title, sum(score) as total_score
from 
(
SELECT p.sid as page_sid,p.title as page_title,NULL as widget_sid, 
  MATCH(p.title, p.content) AGAINST("'.$keyword.'") AS score 
FROM page p
WHERE MATCH(p.title, p.content) AGAINST("'.$keyword.'")
UNION
SELECT p.sid as page_sid,p.title as page_title,w.sid as widget_sid, 
  MATCH(w.content) AGAINST("'.$keyword.'") AS score 
FROM page p
  inner join widget_to_page wtp on p.sid = wtp.page_sid
  inner join widget w on w.sid = wtp.widget_sid
WHERE MATCH(w.content) AGAINST("'.$keyword.'")
) as sub_query
group by page_sid
ORDER BY total_score DESC
...