Thư mục bài viết
Gần đây tôi đang làm một việc gì đó.WordPressTôi muốn thêm chức năng tìm kiếm toàn trang hiệu suất cao vào trang web của mình. Sau nhiều lần tìm kiếm, tôi đã chọn Meilisearch và kết hợp nó với một plugin có tên là Scry Search.
Ban đầu mọi việc diễn ra suôn sẻ. Tôi đã cài đặt plugin, cấu hình nó, và chỉ mục được tạo tự động. Tốc độ tìm kiếm nhanh như chớp, và trải nghiệm thực sự tuyệt vời.
Nhưng vấn đề ở đây là.
Trên trang web có một số bài viết bất thường. Một số bài dùng để thử nghiệm nội bộ, một số là trang đích dành riêng cho khách hàng cụ thể, và một số khác là nội dung chưa hoàn thiện mà chúng tôi không muốn xóa. Tôi cần các ID bài viết này biến mất hoàn toàn khỏi kết quả tìm kiếm.
Không chỉ là không thể tìm thấy nó, mà vấn đề là nó thậm chí không có trong chỉ mục của Meilisearch.

Tôi nghĩ việc này khá đơn giản; chỉ cần loại trừ một vài ID là xong. Tài liệu hướng dẫn của plugin chắc hẳn đã có các hook tương ứng; chỉ cần thêm bộ lọc là được.
Hóa ra, tôi đã nhầm.
Tại sao các phương pháp chặn bắt thông thường lại thất bại?
Đầu tiên, tôi đã thử sử dụng hook lọc được đề cập trong tài liệu chính thức. Tôi đã thêm một vài dòng mã vào functions.php, lưu lại, làm mới trang quản trị và lập chỉ mục lại.
Sau đó tôi đã kiểm tra hệ thống quản trị của Meilisearch.
Những bài viết đó vẫn còn đó.
Tôi sững sờ.
Tôi nghĩ mình đã viết sai mã, nên đã kiểm tra đi kiểm tra lại nhiều lần, nhưng không thấy có gì sai cả. Sau đó, tôi tìm kiếm trên diễn đàn GitHub Issues của plugin và thấy rằng một số người khác cũng gặp phải vấn đề tương tự.
Hóa ra plugin Scry Search sử dụng cơ chế hàng đợi tác vụ bất đồng bộ để tránh làm chậm quá trình lưu trữ nền. Điều này có nghĩa là khi bạn nhấp vào "Lưu bài viết" trong nền, dữ liệu có thể được đẩy ngay lập tức vào một bảng tác vụ tùy chỉnh, bỏ qua quá trình lọc bài viết đơn lẻ thông thường.
Điều nguy hiểm hơn nữa là khi bạn nhấp vào "Lập chỉ mục bài viết" ở chế độ nền để tạo lại chỉ mục toàn cầu, plugin sẽ trực tiếp thực hiện truy vấn cơ sở dữ liệu hàng loạt ở cấp độ cơ sở. Tại thời điểm này, hook bộ lọc mà bạn đã thêm trước đó sẽ không bao giờ có cơ hội được thực thi.
Nói cách khác, các phương pháp chặn thông thường chỉ có hiệu lực khi bạn tự tay lưu bài viết. Nhưng logic đồng bộ hóa của Scry Search phức tạp hơn nhiều so với bạn tưởng tượng.
Mã cốt lõi của bộ chặn bảo hiểm kép
Sau khi suy nghĩ kỹ, tôi nhận ra rằng chuyện này không thể cứ để như vậy được.
Vì cơ chế hook thông thường chỉ kiểm soát điểm truy cập "lưu một bài viết duy nhất", tôi cần tìm cách chặn nó từ những nơi khác nữa.
Tôi đã nghĩ ra hai phương án.
Vấn đề đầu tiên là khâu truyền tải dữ liệu qua mạng. Cho dù là đồng bộ hóa từng bài viết hay đồng bộ hóa hàng loạt, dữ liệu cuối cùng vẫn cần được gửi đến máy chủ Meilisearch thông qua các yêu cầu HTTP, đúng không? Vì vậy, trước khi gửi yêu cầu HTTP, tôi cần kiểm tra xem phần thân yêu cầu có chứa ID của các bài viết bị loại trừ hay không. Nếu có, tôi nên chặn yêu cầu đó ngay lập tức.
Điểm thứ hai liên quan đến truy vấn cơ sở dữ liệu. Vì plugin truy xuất danh sách bài viết trực tiếp từ cơ sở dữ liệu trong quá trình lập chỉ mục hàng loạt, tôi sẽ loại bỏ các ID cụ thể đó khỏi kết quả truy vấn trước khi thực hiện truy vấn cơ sở dữ liệu. Từ góc nhìn của plugin, các bài viết này không tồn tại, vì vậy chúng sẽ không được truy xuất.
Hai con đường, bảo hiểm gấp đôi. Nếu một con đường không thể bị chặn, thì con đường khác sẽ là phương án dự phòng.
Sau khi hiểu ra vấn đề, tôi bắt đầu viết mã.
Đối với bộ chặn đầu tiên, tôi đã sử dụng bộ chặn mặc định của WordPress.pre_http_requestBộ lọc. Hook này được kích hoạt trước khi WordPress thực hiện bất kỳ yêu cầu HTTP nào. Logic của tôi là nó sẽ phát hiện xem URL được yêu cầu có chứa...meilisearchNếu nội dung yêu cầu chứa ID của các bài viết bị loại trừ, yêu cầu sẽ bị chặn.
Để ngăn plugin báo lỗi, tôi cũng cần tạo ra một phản hồi giả thành công. Định dạng phản hồi tiêu chuẩn của Meilisearch là...{"taskUid":0,"status":"enqueued"}Tôi chỉ đơn giản là trả về giá trị này, khiến plugin cho rằng quá trình đồng bộ hóa đã thành công.
Máy bay đánh chặn thứ hai mà tôi đã sử dụngpre_get_postsHook này được kích hoạt trước khi WordPress thực hiện truy vấn cơ sở dữ liệu. Logic của tôi là bất cứ khi nào quản trị viên thực hiện thao tác nào đó ở phần quản trị hoặc khi một plugin thực hiện các thao tác bất đồng bộ/đồng bộ, các ID bị loại trừ sẽ được hợp nhất vào...post__not_inTrong các tham số.
Sau khi viết xong, tôi đã thử nghiệm nó.
Đầu tiên, tôi vào phần quản trị, mở một trong những bài viết bị loại trừ, thực hiện một vài thay đổi nhỏ và nhấn cập nhật. Quá trình lưu thành công mà không có lỗi nào. Sau đó, tôi kiểm tra phần quản trị của Meilisearch và chỉ mục của bài viết vẫn không thay đổi; không có gì mới xuất hiện.
Tôi lại nhấn vào "Lập chỉ mục bài viết" và xây dựng lại toàn bộ chỉ mục. Sau khi chờ một lúc, tôi kiểm tra lại trang quản trị của Meilisearch. Những bài viết bị loại trừ vẫn còn đó.
Xong rồi.
Phân tích chuyên sâu: Cơ chế bảo hiểm kép hoạt động như thế nào?
Thành thật mà nói, quá trình này khiến tôi nhớ đến một điều khá thú vị.
Bạn biết đấy, vào những năm 1880, khi điện năng mới bắt đầu phổ biến ở Hoa Kỳ, nhiều chủ nhà máy đã bỏ ra rất nhiều tiền để mua máy phát điện và động cơ điện rồi lắp đặt chúng trong nhà máy của mình. Tuy nhiên, sau khi lắp đặt, nhiều người nhận thấy hiệu quả sản xuất không được cải thiện đáng kể.
为什么?
Bởi vì họ chỉ đơn giản thay thế động cơ hơi nước bằng động cơ điện, nhưng bố cục tổng thể, quy trình và phương pháp quản lý của nhà máy vẫn không thay đổi. Điện năng là một công nghệ mới, nhưng tư duy sử dụng nó thì vẫn giữ nguyên như cũ.
Những người thực sự hưởng lợi từ sự bùng nổ điện năng chính là nhóm người đầu tiên hiểu được "điện năng thực sự có nghĩa là gì". Họ không chỉ thay đổi nguồn năng lượng mà còn thiết kế lại toàn bộ quy trình sản xuất của mình.
vừa rồiAIĐiều tương tự cũng áp dụng cho thời đại. Nhiều người sử dụng AI như một công cụ, nhưng ít người xem xét logic cơ bản mà nó thực sự thay đổi. Công cụ có thể mới, nhưng tư duy sử dụng nó có thể vẫn lỗi thời.
Ví dụ, khi tôi thiết lập tính năng chặn tìm kiếm cho WordPress, có lẽ tôi sẽ không thể làm cho nó hoạt động nếu chỉ làm theo các phương pháp tiêu chuẩn trong tài liệu hướng dẫn của plugin. Điều này là do logic đồng bộ hóa của Scry Search không còn là phương pháp truyền thống "lưu một bài viết, đồng bộ một bài viết" nữa; nó sử dụng hàng đợi không đồng bộ, xử lý theo lô và các cơ chế riêng của nó.
Bạn cần phải tìm hiểu cách thức hoạt động của cơ chế này trước khi có thể tìm ra bước đột phá thực sự.
Những hạn chế và biện pháp phòng ngừa của kế hoạch
Tuy nhiên, tôi phải thẳng thắn thừa nhận rằng kế hoạch này cũng không hoàn hảo.
Nó có một hạn chế đáng kể: nó chỉ có thể quản lý việc đồng bộ hóa trong tương lai và không thể tự động xóa các bản ghi lịch sử hiện có trong Meilisearch. Nói cách khác, nếu bạn đã đồng bộ hóa các bài viết đó, bạn vẫn cần phải xóa dữ liệu cũ theo cách thủ công trong bảng điều khiển Meilisearch hoặc sử dụng các lệnh API.
Đây là một công việc chỉ cần thực hiện một lần; sau khi hoàn thành, bạn không cần phải lo lắng về nó nữa. Nhưng tôi cần làm rõ điều này trước, để sau khi bạn triển khai mã, bạn sẽ không thấy những bài viết đó vẫn còn trong kết quả tìm kiếm và cho rằng mã chưa có hiệu lực.
Một điểm cần lưu ý nữa là phương pháp này dựa trên kiến trúc mạng và cơ sở dữ liệu nền tảng của WordPress. Chừng nào các phiên bản tương lai của plugin Scry Search vẫn tiếp tục hoạt động dựa trên kiến trúc này, thì bộ chặn này sẽ vẫn hiệu quả. Tuy nhiên, nếu nó chuyển sang một cơ chế đồng bộ hóa hoàn toàn khác, thì việc điều chỉnh lại có thể là cần thiết.
Thành thật mà nói, điều này khó xảy ra. Toàn bộ hệ sinh thái WordPress được xây dựng trên kiến trúc này, và hầu như không thể có plugin nào hoàn toàn bỏ qua nó.
Hướng dẫn triển khai ba bước
/**
* Scry Search 双保险拦截器:彻底排除指定文章 ID 同步到 Meilisearch
*/
// ==========================================
// 【配置】请在这里填写你想要排除的文章或页面 ID
// ==========================================
define('MEILI_EXCLUDED_IDS', array(1067, 1014, 1474, 34020));
/**
* 保险一:拦截单篇保存/更新时的网络推送 (方案 A 优化版)
* 原理:当 WordPress 发送网络请求时,如果发现是发往 meilisearch 且带有排除的 ID,直接掐断
*/
add_filter('pre_http_request', function($preempt, $parsed_args, $url) {
// 1. 检查是不是发往 Meilisearch 的请求
if (strpos($url, 'meilisearch') !== false && isset($parsed_args['body'])) {
$body_content = $parsed_args['body'];
// 2. 检查请求体里是否包含任何一个被排除的文章 ID
foreach (MEILI_EXCLUDED_IDS as $id) {
// 匹配格式如 "id":1067 或 字符串中的 ID
if (strpos($body_content, (string)$id) !== false) {
// 找到匹配,直接拦截网络请求,并向插件伪造一个标准的成功响应
return array(
'response' => array('code' => 200, 'message' => 'OK'),
'body' => '{"taskUid":0,"status":"enqueued"}'
);
}
}
}
return $preempt;
}, 10, 3);
/**
* 保险二:拦截后台全量索引时的数据库查询 (方案 B)
* 原理:在插件试图从数据库捞取文章列表时,直接将这几个 ID 从查询结果中剔除
*/
add_action('pre_get_posts', function($query) {
// 仅在后台管理员操作,或者插件执行异步同步时生效
if (is_admin() || (defined('DOING_ASYNC') && DOING_ASYNC)) {
// 获取当前查询已经存在的排除 ID(如果有的话)
$current_excluded = $query->get('post__not_in');
if (!is_array($current_excluded)) {
$current_excluded = array();
}
// 将我们的专属排除 ID 合并进去
$query->set('post__not_in', array_merge($current_excluded, MEILI_EXCLUDED_IDS));
}
});
Cuối cùng, chúng ta hãy tóm tắt các bước vận hành.
Đầu tiên, sao chép đoạn mã vào cuối tệp functions.php của bạn, hoặc thêm nó bằng plugin Code Snippets. Sau đó, ở đầu...defineTrong mảng, hãy nhập ID của bài viết hoặc trang bạn muốn loại trừ.
Bước thứ hai là dọn dẹp các chỉ mục lịch sử. Đăng nhập vào bảng điều khiển Meilisearch của bạn hoặc sử dụng các lệnh API để xóa thủ công dữ liệu chỉ mục cũ cho các bài viết bị loại trừ.
Bước thứ ba là kiểm tra. Truy cập vào phần quản trị và thực hiện bất kỳ thay đổi nhỏ nào đối với bài viết bị loại trừ, nhấp vào cập nhật, sau đó kiểm tra lại trên phần quản trị của Meilisearch. Nếu không có chỉ mục mới nào xuất hiện, việc chặn đã có hiệu lực.
Thành thật mà nói, tôi luôn cảm thấy hơi áy náy khi viết những bài viết chia sẻ kiến thức kỹ thuật kiểu này.
Những điều tôi chia sẻ có thể hữu ích với một số người, nhưng với những người khác, chúng chỉ là những thao tác cơ bản.
Nhưng quá trình triển khai tính năng chặn tìm kiếm WordPress lần này thực sự rất bổ ích. Thường thì, những vấn đề chúng ta gặp phải không phải do thiếu giải pháp, mà là do tư duy của chúng ta bị hạn chế bởi các khuôn khổ hiện có.
Plugin Scry Search cung cấp một hook lọc, khiến chúng ta tin rằng đây là lựa chọn duy nhất. Tuy nhiên, toàn bộ kiến trúc của WordPress cung cấp nhiều khả năng hơn thế. Việc chặn có thể được thực hiện ở lớp mạng, và cũng có thể được thực hiện ở lớp cơ sở dữ liệu. Chỉ cần bạn sẵn sàng suy nghĩ, luôn luôn có cách.
Đó là lý do tại sao tôi thích mày mò với những thiết bị công nghệ này. Không phải để khoe khoang hay cố tỏ ra ấn tượng. Đơn giản vì cảm giác hiểu rõ một vấn đề nào đó thật sự rất thỏa mãn.
Lần này cũng vậy, từ sự bối rối ban đầu, đến quá trình suy ngẫm ở giữa, rồi đến lời giải cuối cùng, toàn bộ quá trình giống như việc giải một câu đố.
Bí ẩn đã được giải đáp, câu trả lời đã được hé lộ, hóa ra nó đơn giản đến thế.
Nhưng nếu bạn chưa từng trải qua quá trình khó hiểu đó, bạn sẽ không bao giờ hiểu được niềm vui giản dị này.
Đến đây rồi, nếu thấy hữu ích, hãy like và chia sẻ nhé. Nếu muốn nhận thông tin cập nhật sớm nhất, bạn cũng có thể theo dõi tôi.
Cảm ơn bạn đã đọc bài viết của tôi. Hẹn gặp lại lần sau.
Hy vọng Chen Weiliang Blog ( https://www.chenweiliang.com/ Bài viết "Cách loại trừ hoàn toàn một ID bài viết cụ thể khỏi quá trình đồng bộ hóa với Meilisearch trong WordPress (Ứng dụng thực tế của plugin Scry Search)" được chia sẻ ở đây có thể hữu ích cho bạn.
Chào mừng bạn đến chia sẻ liên kết của bài viết này:https://www.chenweiliang.com/cwl-34343.html
