Đối sánh MySQL () với () - thứ tự theo mức độ liên quan và cột?


80

Được rồi, tôi đang cố gắng thực hiện tìm kiếm toàn văn trong nhiều cột, đơn giản như sau:

SELECT * FROM pages WHERE MATCH(head, body) AGAINST('some words' IN BOOLEAN MODE)

Bây giờ tôi muốn sắp xếp theo mức độ liên quan, (có bao nhiêu từ được tìm thấy?) Mà tôi có thể thực hiện với một số thứ như sau:

SELECT * , MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE) AS relevance 
FROM pages
WHERE MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE)
ORDER BY relevance

Bây giờ đến phần tôi bị lạc, tôi muốn ưu tiên mức độ liên quan trong headcột.

Tôi đoán tôi có thể tạo hai cột liên quan, một cho headvà một cho body, nhưng tại thời điểm đó, tôi sẽ thực hiện cùng một tìm kiếm trong bảng ba lần và đối với những gì tôi đang tạo hàm này, hiệu suất là rất quan trọng, vì cả truy vấn sẽ được kết hợp và khớp với các bảng khác.

Vì vậy, câu hỏi chính của tôi là , có cách nào nhanh hơn để tìm kiếm mức độ liên quan và ưu tiên các cột nhất định không? (Và như một phần thưởng có thể thậm chí làm cho mức độ liên quan đếm số lần các từ xuất hiện trong các cột?)

Bất kỳ đề xuất hoặc lời khuyên sẽ là tuyệt vời.

Lưu ý: Tôi sẽ chạy nó trên máy chủ LAMP. (WAMP trong thử nghiệm cục bộ)


Bạn có thực sự phải đặt MATCH ... AGAINST trong cả mệnh đề SELECT mệnh đề WHERE không? Bạn có thể không đặt bí danh nó trong mệnh đề SELECT và tham chiếu đến bí danh trong mệnh đề WHERE không? Tôi đang cố gắng sử dụng các câu lệnh đã chuẩn bị và điều này có vẻ thừa / lạ đối với tôi.
S. Imp

2
Không, như đã nêu trong tài liệu MySQL kể từ 5.5, MATCH ... AGAINST sẽ được tính toán một lần khi cả trong SELECT và WHERE, vì vậy không có thêm chi phí.
Bob2u

Câu trả lời:


156

Điều này có thể làm tăng mức độ liên quan đến phần đầu mà bạn muốn. Nó sẽ không tăng gấp đôi, nhưng nó có thể đủ tốt cho lợi ích của bạn:

SELECT pages.*,
       MATCH (head, body) AGAINST ('some words') AS relevance,
       MATCH (head) AGAINST ('some words') AS title_relevance
FROM pages
WHERE MATCH (head, body) AGAINST ('some words')
ORDER BY title_relevance DESC, relevance DESC

-- alternatively:
ORDER BY title_relevance + relevance DESC

Một giải pháp thay thế mà bạn cũng muốn điều tra, nếu bạn có thể linh hoạt để chuyển đổi công cụ DB, là Postgres . Nó cho phép thiết lập trọng số của các toán tử và chơi xung quanh với xếp hạng.


14
Ngoài ra, MySQL 5.6 hỗ trợ tìm kiếm toàn văn trên các bảng InnoDB!
Jabari

1
Bạn có thể cung cấp một câu đố SQL cho việc này không?
Người dùng

Nhiều tìm kiếm có bao nhiêu tác động tiêu cực? Tôi sẽ cần 4 trận đấu ion SELECT của tôi vì tôi có 4 yếu tố trọng lượng khác nhau. Điều đó sẽ làm cho hiệu suất thấp hơn nhiều?
ToBe

@ToBe Tôi đã thấy trong các câu hỏi tương tự khác, nhiều người nói rằng không có thêm chi phí khi sử dụng nhiều MATCHcâu lệnh, do cách MySQL hoạt động nội bộ.
BadHorsie

Hãy chắc chắn rằng bạn chạy hai cái này. ALTER TABLE talk_webpages ADD FULLTEXT(head)ALTER TABLE talk_webpages ADD FULLTEXT(head, body)
Supun Kavinda

15

Chỉ thêm cho những người có thể cần .. Đừng quên thay đổi bảng!

ALTER TABLE table_name ADD FULLTEXT(column_name);

3
nếu bạn thực hiện lệnh trên nhiều hơn một lần, nó sẽ tạo nhiều chỉ mục cho (các) cột giống nhau. Vì vậy, chỉ chạy lệnh này một lần duy nhất.
hakiko 29/09/18

Tốt hơn, hãy sử dụng CREATE FULLTEXT INDEX indexname trên tablename (column_name (s)). Bạn cũng nên thực sự kiểm tra xem chỉ mục có tồn tại hay không trước khi bạn cố gắng tạo nó. Bạn có thể kiểm tra xem nó có tồn tại hay không bằng cách sử dụng: SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_CATALOG= 'def' AND TABLE_SCHEMA= DATABASE () AND TABLE_NAME= 'tablename' AND INDEX_NAME= 'indexname';
Dave Hilditch

9

Tôi chưa bao giờ làm như vậy, nhưng có vẻ như

MATCH (head, head, body) AGAINST ('some words' IN BOOLEAN MODE)

Nên cho một trọng lượng gấp đôi đối với các que diêm được tìm thấy trong đầu.


Chỉ cần đọc nhận xét này trên trang tài liệu , Tôi nghĩ rằng nó có thể có giá trị đối với bạn:

Được đăng bởi Patrick O'Lone vào ngày 9 tháng 12 năm 2002 6:51 sáng

Cần lưu ý trong tài liệu rằng IN BOOLEAN MODE hầu như sẽ luôn trả về mức độ liên quan là 1.0. Để nhận được mức độ liên quan có ý nghĩa, bạn sẽ cần:

SELECT MATCH('Content') AGAINST ('keyword1 keyword2') as Relevance 
FROM table 
WHERE MATCH ('Content') AGAINST('+keyword1+keyword2' IN BOOLEAN MODE) 
HAVING Relevance > 0.2 
ORDER BY Relevance DESC 

Lưu ý rằng bạn đang thực hiện truy vấn mức độ liên quan thường xuyên để có được các yếu tố liên quan kết hợp với mệnh đề WHERE sử dụng BOOLEAN MODE. CHẾ ĐỘ BOOLEAN cung cấp cho bạn tập hợp con đáp ứng các yêu cầu của tìm kiếm BOOLEAN, truy vấn mức độ liên quan đáp ứng yếu tố liên quan và mệnh đề HAVING (trong trường hợp này) đảm bảo rằng tài liệu có liên quan đến tìm kiếm (tức là tài liệu đạt điểm dưới 0,2 được coi là không liên quan). Điều này cũng cho phép bạn sắp xếp theo mức độ liên quan.

Điều này có thể có hoặc không phải là lỗi trong cách hoạt động của IN BOOLEAN MODE, mặc dù các nhận xét tôi đã đọc trên danh sách gửi thư cho thấy rằng xếp hạng mức độ liên quan của IN BOOLEAN MODE không phức tạp lắm, do đó, bản thân nó kém khi thực sự cung cấp các tài liệu liên quan. BTW - Tôi không nhận thấy sự mất hiệu suất khi thực hiện việc này, vì có vẻ như MySQL chỉ thực hiện tìm kiếm FULLTEXT một lần, mặc dù hai mệnh đề MATCH khác nhau. Sử dụng GIẢI THÍCH để chứng minh điều này.

Vì vậy, có vẻ như bạn có thể không cần phải lo lắng về việc gọi tìm kiếm toàn văn hai lần, mặc dù bạn vẫn nên "sử dụng EXPLAIN để chứng minh điều này"


1
Thật đáng tiếc, việc thêm đầu hai lần vào hàm match () không hoạt động. Có thể vì truy vấn không đếm số lần các từ đang xảy ra? Và tôi cũng đang sử dụng trang đó mà bạn tham khảo, nhưng vì một số lý do, tôi có thể không làm cho nó hoạt động ... Tôi chưa lập chỉ mục các cột của mình và do đó không thể tìm kiếm nếu không có thẻ "IN BOOLEAN MODE" .. .
Kristoffer la Cour

Tôi nghĩ rằng một tìm kiếm không phải booleen sẽ trả về # lần xuất hiện, nhưng booleen thì không?
jisaacstone

Tôi sẽ xem xét nó nhiều hơn vào ngày mai, nhưng tôi sẽ giữ cho bây giờ. Cảm ơn câu trả lời, chúng tôi sẽ xem nó có giúp được gì cho tôi không khi tôi nắm được điều này.
Kristoffer la Cour

Tôi đã gặp sự cố khi sử dụng IN BOOLEAN MODE và sau đó sắp xếp theo mức độ liên quan và điều này đã giải quyết được vấn đề của tôi với mức độ liên quan luôn được trả về là 1. Cảm ơn.
Jazzy

Tạo trường điểm đã giải quyết được vấn đề của tôi: Tôi đã nhận được kết quả, nhưng nhiều kết quả trong số đó hoàn toàn bị nhiễu. Cảm ơn, +1
Chris Baker

4

Tôi cũng chỉ đang chơi đùa với cái này. Một cách bạn có thể tăng thêm trọng lượng là trong vùng ORDER BY của mã.

Ví dụ: nếu bạn đang đối sánh 3 cột khác nhau và muốn tăng trọng số các cột nhất định:

SELECT search.*,
MATCH (name) AGAINST ('black' IN BOOLEAN MODE) AS name_match,
MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE) AS keyword_match,
MATCH (description) AGAINST ('black' IN BOOLEAN MODE) AS description_match
FROM search
WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE)
ORDER BY (name_match * 3  + keyword_match * 2  + description_match) DESC LIMIT 0,100;

Đây không phải là một truy vấn thực sự nặng nề?
Beanow

5
Chuyển phép toán vào câu lệnh select và nó làm giảm tải rất nhiều. SELECT search.*, (MATCH (name) AGAINST ('black' IN BOOLEAN MODE) * 3) + (MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE)*2 + MATCH (description) AGAINST ('black' IN BOOLEAN MODE)) AS totalScore , FROM search WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE) ORDER BY totalScore DESC LIMIT 0,100;
invertedSpear
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.