MySQL полный текст на нескольких таблицах - PullRequest
19 голосов
/ 19 ноября 2010

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

Вот мои столы

CREATE TABLE books (
 bookID int(11) NOT NULL AUTO_INCREMENT,
 title varchar(300) NOT NULL,
 authorID int(11) NOT NULL,
 FULLTEXT KEY title (title)
)

CREATE TABLE IF NOT EXISTS authors (
 authorID int(11) NOT NULL AUTO_INCREMENT,
 authorNamevarchar(200) NOT NULL,
 FULLTEXT KEY authorName(authorName)
);

CREATE TABLE IF NOT EXISTS chapters (
 chapterID int(11) NOT NULL AUTO_INCREMENT,
 bookID int(11) NOT NULL,
 content longtext NOT NULL,
 FULLTEXT KEY content (content)
);

И мой sql запрос. Вот где я застрял.

SELECT *, 
 MATCH(books.title) AGAINST('$q') as tscore,
 MATCH(authors.authorName) AGAINST('$q') as ascore
 MATCH(chapters.content) AGAINST('$q') as cscore
FROM books 
LEFT JOIN authors ON books.authorID = authors.authorID 
LEFT JOIN chapters ON books.bookID = chapters.bookID 
WHERE 
 MATCH(books.title) AGAINST('$q')
 OR MATCH(authors.authorName) AGAINST('$q')
 OR MATCH(chapters.content) AGAINST('$q')
ORDER BY ???? DESC

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

И, да, я знаю о других поисковых системах, таких как lucene или sphinx, но я не планирую использовать их сейчас.

Заранее спасибо.

Ответы [ 3 ]

35 голосов
/ 19 ноября 2010

Вы должны иметь возможность добавить значения tscore, ascore и cscore в предложении ORDER BY.

Попробуйте это:

SELECT *, 
 MATCH(books.title) AGAINST('$q') as tscore,
 MATCH(authors.authorName) AGAINST('$q') as ascore,
 MATCH(chapters.content) AGAINST('$q') as cscore
FROM books 
LEFT JOIN authors ON books.authorID = authors.authorID 
LEFT JOIN chapters ON books.bookID = chapters.bookID 
WHERE 
 MATCH(books.title) AGAINST('$q')
 OR MATCH(authors.authorName) AGAINST('$q')
 OR MATCH(chapters.content) AGAINST('$q')
ORDER BY (tscore + ascore + cscore) DESC
0 голосов
/ 09 января 2018

@ Решение Айка Уокера великолепно, однако в моем случае я хотел свернуть результаты «один ко многим» в одну строку для каждого результата поиска. Следуя решению @Ike Walker, вот как я справился с работой:

Схема:

T1: Articles
T2: Comments (many comments to one article)

Индексы:

ALTER TABLE articles ADD FULLTEXT title_index (title)
ALTER TABLE articles ADD FULLTEXT body_index (body)
ALTER TABLE comments ADD FULLTEXT comment_index (comment)

SQL:

SELECT 
    articles.title, 
    SUM(MATCH(articles.title) AGAINST('$q') + 
    MATCH(articles.body) AGAINST('$q') + 
    MATCH(comments.comment) AGAINST('$q')) as relevance 
FROM 
    articles 
LEFT JOIN 
    comments ON articles.id = comments.article_id 
WHERE 
    MATCH(articles.title) AGAINST('$q') 
    OR MATCH(articles.body) AGAINST('$q') 
    OR MATCH(comments.comment) AGAINST('$q') 
GROUP BY 
    articles.id 
ORDER BY 
    relevance DESC

Примечание: если вы хотите добавить веса к каждому полю, вы можете сделать что-то вроде.

SUM((MATCH(articles.title) AGAINST('$q')*3) + 
        (MATCH(articles.body) AGAINST('$q')*2) + 
        MATCH(comments.comment) AGAINST('$q')) as relevance 

В этом случае заголовок будет иметь 3x, тело в 2 раза больше значения совпадения в комментариях.

0 голосов
/ 19 ноября 2010

Это зависит от того, что вы хотите отсортировать.Вы можете отсортировать по автору, затем по названию, а затем по содержанию главы с помощью этой

ORDER BY MATCH(authors.authorName) DESC ,MATCH(books.title) DESC ,MATCH(chapters.content) DESC

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

ORDER BY MATCH(authors.authorName) + MATCH(books.title) + MATCH(chapters.content) DESC

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...