2011-08-19 33 views
6

Tôi khá mới để tìm kiếm toàn văn MySQL và tôi chạy vào vấn đề này hôm nay:mysql chế độ boolean tìm kiếm toàn văn với các kí hiệu và chữ

bảng Công ty của tôi có một kỷ lục với "e-tạp chí AG" trong tên cột. Tôi có chỉ mục toàn văn trên cột tên.

Khi tôi thực hiện truy vấn này kỷ lục không tìm thấy:

SELECT id, name FROM company WHERE MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

tôi cần phải làm việc với dấu ngoặc kép vì dấu gạch ngang và sử dụng các ký tự đại diện bởi vì tôi thực hiện một "tìm kiếm khi bạn gõ" chức năng.

Khi tôi tìm kiếm toàn bộ cụm từ "e-magazine AG", bản ghi được tìm thấy.

Bất kỳ ý tưởng nào tôi đang làm sai ở đây? Tôi đọc về việc thêm dấu gạch ngang vào danh sách các ký tự từ (cập nhật cấu hình cần thiết) nhưng tôi đang tìm kiếm một cách để làm điều này theo lập trình.

+0

Câu hỏi thú vị. Tôi có thể sao chép nó ở đây trong một bảng với một trường uuid như. 'SELECT id, bootid FROM socket WHERE MATCH (bootid) AGAINST ('+" 18bda775 "' IN BOOLEAN MODE);' sẽ hoạt động và nếu tôi tìm kiếm "18bda775-711c", nhưng tìm kiếm "18bda" hoặc "18bda775 -711 "sẽ không hoạt động. trường 'bootid' trong câu hỏi chứa: 18bda775-711c-4329-9de2-a3d81dc13d06 –

+0

Chúng tôi cũng đã thử thay đổi các ký tự điều khiển boolean để sử dụng # thay vì - nhưng nó không có hiệu lực (có, tôi đã sửa chỉ mục bảng sau khi thay đổi) : 'ft_boolean_syntax = + #><() ~ *:" "& |' – hajo

Trả lời

2

khoản này

MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

sẽ tìm kiếm một AND "e" AND NOT "magazi"; tức là - bên trong "e-magazi" sẽ được hiểu là not ngay cả khi nó nằm trong dấu ngoặc kép.
Vì lý do này, nó sẽ không hoạt động như mong đợi.
Giải pháp là áp dụng mệnh đề thêm having với LIKE.

Tôi biết điều này having là chậm, nhưng nó sẽ chỉ được áp dụng cho kết quả của trận đấu, do đó không có quá nhiều hàng nên tham gia.

Tôi đề nghị một cái gì đó như:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('magazine' IN BOOLEAN MODE) 
HAVING name LIKE '%e-magazi%'; 
+0

cảm ơn thông tin nhưng nó không giúp tôi vì chuỗi tìm kiếm được nhập bởi người dùng muốn tìm kiếm công ty.nói cách khác, backend thực thi truy vấn không thể biết rằng "e-magazi" là một phần của chuỗi "e-magazine". trường tìm kiếm phải chấp nhận cả phần từ và từ đầy đủ. – hajo

+0

Phương pháp rất độc đáo với phương pháp lọc! Cảm ơn bạn! – ProfileTwist

+0

Bạn thấy các khoảng trắng ở phía trước hoặc sau cụm từ tìm kiếm ở đâu? '+' Là toán tử toàn văn thông thường và không phải là khoảng trắng! – mgutt

0

MySQL toàn văn đối xử từ e-magazine trong một văn bản như một cụm từ không như một từ. Do đó, kết quả là hai từ emagazine. Và trong khi nó xây dựng chỉ mục tìm kiếm, nó không thêm e vào chỉ mục vì ft_min_word_len (mặc định là 4 ký tự).

Giới hạn độ dài tương tự được sử dụng cho truy vấn tìm kiếm. Đó là lý do tại sao tìm kiếm e-magazine trả lại kết quả giống hệt như a-magazinea- bị bỏ qua hoàn toàn.

Nhưng bây giờ bạn muốn tìm cụm từ chính xác e-magazine.Bằng cách đó bạn sử dụng dấu ngoặc kép và đó là cách hoàn chỉnh đúng để tìm các cụm từ, nhưng MySQL không hỗ trợ các nhà khai thác cho các cụm từ, chỉ cho chữ:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html

Với sửa đổi lần này, nhân vật nào đó có ý nghĩa đặc biệt tại bắt đầu hoặc kết thúc của lời trong chuỗi tìm kiếm

Một số người sẽ đề nghị sử dụng các truy vấn sau đây:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE) 
HAVING name LIKE 'e-magazi%'; 

Như tôi đã nói, MySQL bỏ qua số e- và tìm kiếm từ ký tự đại diện magazi*. Sau khi các kết quả đó được giải thích, nó sử dụng HAVING để lọc kết quả theo cách thủ công cho e-magazi* bao gồm e-. Bằng cách đó bạn sẽ tìm thấy cụm từ e-magazine AG. Tất nhiên HAVING chỉ cần thiết nếu cụm từ tìm kiếm chứa toán tử ký tự đại diện và bạn không bao giờ nên sử dụng dấu ngoặc kép. Toán tử này được sử dụng bởi người dùng của bạn chứ không phải bạn!

Lưu ý: Khi bạn không bao quanh cụm từ tìm kiếm với %, nó sẽ chỉ tìm các trường bắt đầu bằng từ đó. Và bạn không muốn bao quanh nó, bởi vì nó cũng sẽ tìm thấy bee-magazine. Vì vậy, có thể bạn cần thêm OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%' để làm cho nó có thể sử dụng được bên trong văn bản.

Lừa

Nhưng cuối cùng tôi thích một thủ thuật để HAVING là không cần thiết ở tất cả:

  1. Nếu bạn thêm văn bản với bảng cơ sở dữ liệu của bạn, thêm họ thêm vào một cột toàn văn riêng biệt được lập chỉ mục và thay thế các từ như up-to-date bằng up-to-date uptodate.
  2. Nếu người dùng tìm kiếm up-to-date thay thế nó trong truy vấn bằng uptodate.

Bằng cách đó bạn vẫn có thể tìm thấy specific trong user-specific nhưng up-to-date cũng (và không chỉ date).

Bonus

Nếu người dùng tìm kiếm -well-known huge ports MySQL coi đó như là not include *well*, could include *known* and *huge*. Tất nhiên bạn cũng có thể giải quyết điều đó bằng một biến thể truy vấn khác, nhưng với mẹo ở trên, bạn xóa dấu gạch ngang để truy vấn tìm kiếm trông giống như vậy:

SELECT id 
FROM texts 
WHERE MATCH(text) AGAINST('-wellknown huge ports' IN BOOLEAN MODE) 
Các vấn đề liên quan