2010-11-19 35 views
15

Tôi đang cố gắng thực hiện tìm kiếm toàn văn trong ba bảng riêng biệt và sắp xếp kết quả theo mức độ liên quan. Trong quá trình tìm kiếm câu trả lời, tôi phát hiện ra rằng tôi không thể sử dụng tìm kiếm toàn văn bản trong nhiều bảng. Vì vậy, tôi đã thêm một chỉ mục toàn văn riêng biệt cho mỗi cột tôi muốn tìm kiếm. Bây giờ vấn đề là tôi có thể thực hiện tìm kiếm nhưng tôi không thể phân loại như tôi muốn.mysql fulltext trên nhiều bảng

Dưới đây là bảng tôi

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) 
); 

Và truy vấn sql của tôi. Đây là nơi tôi bị kẹt.

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 

Bây giờ với truy vấn này tôi có thể phân loại theo tiêu đề, tác giả hoặc nội dung. Những gì tôi muốn làm là, có được sự liên quan cho tất cả ba cột với nhau và ra lệnh cho kết quả đó.

Và, có, tôi biết các công cụ tìm kiếm khác như lucene hoặc sphinx, nhưng tôi không định sử dụng chúng ngay bây giờ.

Xin cảm ơn trước.

Trả lời

30

Bạn sẽ có thể thêm các giá trị tscore, ascore và cscore trong mệnh đề ORDER BY.

Hãy thử điều này:

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 
+1

chính xác. cảm ơn. – keune

+0

Giúp tôi tải. Cảm ơn! – youngcouple10

+1

Rất đẹp, những gì tôi cần cho dự án của mình! – NaturalBornCamper

-1

Tùy thuộc vào nội dung bạn muốn sắp xếp theo. Bạn có thể sắp xếp theo tác giả, sau đó tiêu đề, sau đó chương nội dung với điều này

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

ý tưởng được rằng khi bạn tìm thấy tên tác giả, đó là thích hợp hơn khi nó được tìm thấy trong các tiêu đề, do đó là thích hợp hơn tìm nó trong văn bản chương. Bạn cũng có thể sắp xếp theo tổng mức độ liên quan với

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

nhưng điều đó có thể cho kết quả lạ, như nội dung tìm kiếm chỉ hiển thị trong nội dung chương có thể hiển thị trước tiêu đề.

+0

không hoạt động tôi đã thử nó .... bạn có thể làm ORDER BY MATCH (..) AGAINST() thực hiện tương tự như truy vấn thứ hai – ITECH

0

giải pháp @Ike Walker là rất tốt, tuy nhiên trong trường hợp của tôi, tôi muốn để cuộn lên kết quả một-nhiều vào một hàng duy nhất cho mỗi kết quả tìm kiếm. Riffing trên giải pháp @Ike Walker dưới đây là cách tôi đã hoàn thành công việc:

Schema:

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

Indexes:

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 

Lưu ý: Nếu bạn muốn để thêm trọng số cho mỗi trường, bạn có thể làm một cái gì đó như thế nào.

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

Trong trường hợp này tiêu đề sẽ có 3x, body 2x giá trị của đối sánh trong nhận xét.

Các vấn đề liên quan