Tại sao cần tăng cường độ chính xác tìm kiếm cho WordPress?
Tính năng tìm kiếm mặc định của WordPress sử dụng cơ chế LIKE trong MySQL để khớp từ khóa. Nghĩa là khi người dùng gõ từ “tiêu đề”, hệ thống sẽ tìm mọi bài viết chứa chuỗi ký tự “tiêu đề” ở bất kỳ vị trí nào trong nội dung. Điều này dẫn đến một vấn đề khá phiền toái: kết quả tìm kiếm không chính xác, hiển thị nhiều bài viết không liên quan hoặc ít liên quan.
Ví dụ, khi bạn tìm từ “test”, WordPress có thể trả về các bài viết chứa từ “contest”, “protest”, hay “latest” vì tất cả đều có chứa chuỗi “test”. Điều này gây khó chịu cho người dùng khi họ chỉ muốn tìm bài viết có từ “test” độc lập.
Bài viết này sẽ hướng dẫn bạn cách sử dụng REGEXP (Regular Expression) thay cho LIKE để thực hiện tìm kiếm theo ranh giới từ (word boundary). Phương pháp này giúp kết quả tìm kiếm chính xác hơn rất nhiều mà không cần cài đặt thêm plugin nào.
Nguyên lý hoạt động của giải pháp
Giải pháp này sử dụng filter hook posts_search của WordPress để thay thế câu truy vấn tìm kiếm mặc định. Thay vì dùng LIKE '%keyword%', ta dùng REGEXP '[[::]]keyword[[::]]' để chỉ khớp từ khóa khi nó là một từ hoàn chỉnh, đứng độc lập.
Cụ thể, biểu thức [[::]] trong MySQL REGEXP đại diện cho ranh giới từ (word boundary). Khi bạn tìm “test”, hệ thống chỉ khớp với “test” chứ không khớp với “contest” hay “protest”. Đây là cách hoạt động tương tự tính năng tìm kiếm nâng cao của các search engine chuyên nghiệp.
Ngoài ra, đoạn code còn tự động loại bỏ các bài viết có password protection khỏi kết quả tìm kiếm đối với người dùng chưa đăng nhập, giúp bảo vệ nội dung private của bạn.
Đoạn code tăng cường tìm kiếm cho WordPress
Bạn cần thêm đoạn code sau vào tập tin functions.php của theme đang sử dụng. Nếu bạn đang dùng child theme, hãy thêm vào file functions.php của child theme để tránh mất code khi cập nhật theme gốc.
Đoạn code này áp dụng vừa tìm Tiêu đề và Nội dung:
add_filter('posts_search', 'pvs_search_is_exact', 20, 2);
function pvs_search_is_exact($search, $wp_query){
global $wpdb;
if(empty($search))
return $search;
$q = $wp_query->query_vars;
$n = !empty($q['exact']) ? '' : '%';
$search = $searchand = '';
foreach((array)$q['search_terms'] as $term) :
$term = esc_sql(like_escape($term));
$search.= "{$searchand}($wpdb->posts.post_title REGEXP '[[::]]{$term}[[::]]') OR ($wpdb->posts.post_content REGEXP '[[::]]{$term}[[::]]')";
$searchand = ' AND ';
endforeach;
if(!empty($search)) :
$search = " AND ({$search}) ";
if(!is_user_logged_in())
$search .= " AND ($wpdb->posts.post_password = '') ";
endif;
return $search;
}
Giải thích chi tiết từng phần của code
add_filter(‘posts_search’, ‘pvs_search_is_exact’, 20, 2): Hook này can thiệp vào câu truy vấn SQL mà WordPress tạo ra khi thực hiện tìm kiếm. Tham số thứ 3 là priority (20) giúp đảm bảo hook này chạy sau các hook mặc định, tham số thứ 4 là số arguments (2) vì filter này nhận 2 biến.
global $wpdb: Biến toàn cục $wpdb là class của WordPress dùng để tương tác với database. Ta cần nó để truy cập tên bảng posts.
if(empty($search)) return $search: Nếu không có từ khóa tìm kiếm nào, trả về giá trị gốc luôn, không cần xử lý thêm.
$q[‘search_terms’]: Mảng chứa các từ khóa mà người dùng nhập vào. Nếu người dùng tìm “hoc WordPress”, mảng sẽ có 2 phần tử: “hoc” và “WordPress”.
esc_sql(like_escape($term)): Hai hàm này dùng để làm sạch dữ liệu đầu vào, ngăn chặn SQL Injection. Hàm like_escape xử lý các ký tự đặc biệt của MySQL, còn esc_sql escape toàn bộ chuỗi.
REGEXP ‘[[::]]{$term}[[::]]’: Đây là phần quan trọng nhất. Biểu thức REGEXP với word boundary [[::]] chỉ khớp khi từ khóa là một từ độc lập, không nằm trong từ khác.
post_password check: Phần cuối code kiểm tra nếu người dùng chưa đăng nhập thì chỉ trả về các bài viết không có password, giúp bảo vệ nội dung bảo mật.
Cách thêm code vào website WordPress
Bạn có 3 cách phổ biến để thêm đoạn code này vào website:
Cách 1: Thêm vào functions.php của child theme. Đây là cách được khuyến nghị nhất. Bạn truy cập Appearance > Theme File Editor trong wp-admin, chọn child theme, rồi thêm code vào cuối file functions.php. Ưu điểm là code sẽ không bị mất khi cập nhật theme.
Cách 2: Sử dụng plugin Code Snippets. Cài plugin Code Snippets từ WordPress repository, tạo snippet mới và dán code vào. Cách này tiện lợi vì bạn có thể bật/tắt snippet bất cứ lúc nào mà không cần chỉnh sửa file theme.
Cách 3: Thêm vào file wp-config.php. Bạn có thể dùng plugin WP Code Editor hoặc truy cập file qua FTP/SSH để chỉnh sửa. Cách này ít được khuyến nghị vì dễ gây lỗi nếu viết sai cú pháp PHP.
Các giải pháp thay thế cho tìm kiếm WordPress
Ngoài phương pháp dùng code tự viết, bạn cũng có thể tham khảo các giải pháp sau:
Plugin Relevanssi: Đây là plugin tìm kiếm phổ biến nhất cho WordPress, thay thế hoàn toàn hệ thống tìm kiếm mặc định. Relevanssi hỗ trợ tìm kiếm theo từ hoàn chỉnh, đánh trọng số kết quả theo ngày, tiêu đề, nội dung, và còn hỗ trợ tìm kiếm tiếng Việt khá tốt.
Plugin SearchWP: Một plugin trả phí với khả năng tùy chỉnh rất mạnh. Bạn có thể cấu hình từng loại post type, taxonomy, field nào được index và mức độ ưu tiên của từng loại nội dung. SearchWP phù hợp cho các website lớn cần tìm kiếm chuyên nghiệp.
Plugin ElasticPress: Sử dụng Elasticsearch để xử lý tìm kiếm, cho hiệu năng rất cao với lượng dữ liệu lớn. Plugin này miễn phí và đặc biệt phù hợp cho các trang có hàng ngàn bài viết.
Nếu website của bạn nhỏ gọn và bạn không muốn cài thêm plugin, phương pháp dùng code REGEXP trong bài viết này là lựa chọn tối ưu nhất: nhẹ, nhanh, không phụ thuộc plugin bên thứ ba.
Một số lưu ý khi sử dụng
Với nội dung tiếng Việt: REGEXP word boundary ([[::]]) hoạt động tốt với các từ Latin nhưng có thể gặp khó khăn với tiếng Việt có dấu. Nếu bạn chủ yếu viết tiếng Việt có dấu, hãy kiểm tra kỹ kết quả tìm kiếm sau khi áp dụng code.
Hiệu năng: REGEXP nói chung chậm hơn LIKE trong MySQL. Tuy nhiên, với hầu hết các website WordPress có dưới vài chục ngàn bài viết, sự khác biệt về tốc độ là không đáng kể. Nếu website bạn rất lớn, hãy cân nhắc dùng plugin ElasticPress hoặc Swiftype.
Backup trước khi thay đổi: Luôn sao lưu file functions.php hoặc tạo backup toàn site trước khi thêm code mới. Điều này giúp bạn dễ dàng khôi phục nếu có lỗi xảy ra.
Kiểm tra syntax PHP: Nếu bạn gặp lỗi trắng trang (white screen) sau khi thêm code, hãy kiểm tra xem có thiếu dấu ngoặc, dấu chấm phẩy hay không. Bạn có thể bật WP_DEBUG trong file wp-config.php để xem thông báo lỗi chi tiết.
Tổng kết
Tăng cường độ chính xác tìm kiếm cho WordPress bằng REGEXP word boundary là một giải pháp đơn giản nhưng hiệu quả. Chỉ với một đoạn code nhỏ trong functions.php, bạn đã cải thiện đáng kể trải nghiệm tìm kiếm cho người dùng mà không cần cài thêm plugin nặng nề. Phương pháp này đặc biệt phù hợp cho các blog, website tin tức có lượng bài viết vừa phải và muốn giữ tính nhẹ nhàng cho hệ thống.
Nếu bạn cần tìm kiếm chuyên nghiệp hơn với các tính năng như fuzzy search, autocomplete, hay tìm kiếm theo taxonomy, hãy cân nhắc dùng plugin Relevanssi hoặc SearchWP. Còn với nhu cầu cơ bản, code trong bài viết này là đủ dùng và đáng tin cậy.
Blog này vốn là góc cá nhân ghi chép kinh nghiệm WordPress, không phải tài liệu từ dân chuyên làm web. Nên nếu bạn đang cần một website chuẩn chỉnh, bên hỗ trợ mình quen làm nhanh và ổn định hơn tự làm – đơn vị tên TaigaWeb.

