מדריך מאמרים
לאחרונה עבדתי על אתר וורדפרס ורציתי להוסיף מנוע חיפוש בעל ביצועים גבוהים לכל האתר. לאחר חיפושים רבים, בחרתי ב-Meilisearch ושילבתי אותו עם תוסף בשם Scry Search.
בהתחלה זה הלך חלק. התקנתי את התוסף, הגדרתי אותו, והאינדקס נוצר אוטומטית. מהירות החיפוש הייתה מהירה כברק, והחוויה הייתה אכן מצוינת.
אבל כאן מגיעה הבעיה.
יש באתר כמה מאמרים יוצאי דופן. חלקם מיועדים לבדיקות פנימיות, חלקם דפי נחיתה ייעודיים ללקוחות ספציפיים, ואחרים הם תוכן לא גמור שאנחנו לא רוצים למחוק. אני צריך שמזהי המאמרים האלה ייעלמו לחלוטין מתוצאות החיפוש.
לא מספיק שלא ניתן למצוא אותו; זה אפילו לא ניתן להופיע באינדקס של Meilisearch.

חשבתי שזה פשוט; זה רק עניין של אי הכללת כמה מזהים. בתיעוד התוסף חייבים להיות ה-hooks המתאימים; פשוט הוסיפו פילטר וזהו.
כפי שהתברר, טעיתי.
מדוע שיטות יירוט קונבנציונליות נכשלות?
ניסיתי לראשונה את ה-filter hook שהוזכר בתיעוד הרשמי. הוספתי כמה שורות קוד ל-functions.php, שמרתי אותו, רעננתי את ה-backend ואינדקסתי אותו מחדש.
לאחר מכן בדקתי את ה-backend של Meilisearch.
המאמרים האלה עדיין שם.
הייתי המום.
חשבתי שכתבתי את הקוד הלא נכון, אז בדקתי אותו כמה פעמים, אבל לא היה בו שום דבר לא בסדר. לאחר מכן חיפשתי ב-GitHub Issues של התוסף ומצאתי שכמה אנשים אחרים נתקלו בבעיות דומות.
מסתבר שתוסף החיפוש של Scry משתמש במנגנון אסינכרוני של תור משימות כדי למנוע האטה של תהליך שמירת הרקע. משמעות הדבר היא שכאשר לוחצים על "שמור מאמר" ברקע, הנתונים עשויים להישלח באופן מיידי לטבלת משימות מותאמת אישית, תוך עקיפת הסינון הרגיל של מאמר בודד.
מה שעוד יותר ערמומי הוא שכאשר לוחצים על "אינדקס פוסטים" ברקע כדי ליצור מחדש את האינדקס הגלובלי, התוסף מבצע ישירות שאילתת אצווה של מסד הנתונים ברמה הבסיסית. בשלב זה, הוו של הסינון שהוספת קודם לכן לא מקבל הזדמנות להתבצע.
במילים אחרות, שיטות חסימה קונבנציונליות נכנסות לתוקף רק ברגע שמירת המאמר ידנית. אבל לוגיקת הסנכרון של Scry Search מורכבת הרבה יותר ממה שאתם עשויים לדמיין.
קוד ליבה של יירוט ביטוח כפול
אחרי שחשבתי על זה, הבנתי שאי אפשר להשאיר את העניין הזה ככה.
מכיוון שה-hook הקונבנציונלי שולט רק בנקודת הכניסה של "שמירת מאמר יחיד", אני צריך למצוא דרך לחסום אותו גם ממקומות אחרים.
הגעתי לשני מסלולים.
הבעיה הראשונה היא קצה השידור ברשת. בין אם מדובר בסנכרון של מאמר בודד או בסנכרון אצווה, הנתונים הסופיים עדיין צריכים להישלח לשרת Meilisearch דרך בקשות HTTP, נכון? לכן, לפני שליחת בקשת ה-HTTP, עליי לבדוק אם גוף הבקשה מכיל את המזהים של המאמרים שלא נכללו. אם כן, עליי לחסום ישירות את שליחת הבקשה.
הנקודה השנייה נוגעת לשאילתת מסד הנתונים. מכיוון שהתוסף מאחזר את רשימת המאמרים ישירות ממסד הנתונים במהלך אינדוקס אצווה, אסיר את המזהים הספציפיים הללו מתוצאות השאילתה לפני ביצוע שאילתת מסד הנתונים. מנקודת מבטו של התוסף, מאמרים אלה אינם קיימים כלל, ולכן הם לא יאוחזרו.
שני נתיבים, ביטוח כפול. אם לא ניתן לחסום נתיב אחד, ישנו אחר כגיבוי.
אחרי שהבנתי את זה, התחלתי לכתוב קוד.
עבור המיירט הראשון, השתמשתי בגרסה המקורית של וורדפרס.pre_http_requestהמסנן. הוו הזה מופעל לפני שוורדפרס מבצע בקשות HTTP כלשהן. ההיגיון שלי הוא שהוא יזהה אם כתובת האתר המבוקשת מכילה...meilisearchאם גוף הבקשה מכיל את המזהים של המאמרים שלא נכללו, הבקשה תיחסם.
כדי למנוע מהתוסף לדווח על שגיאות, אני צריך גם לזייף תגובה מוצלחת. פורמט התגובה הסטנדרטי עבור Meilisearch הוא...{"taskUid":0,"status":"enqueued"}פשוט החזרתי את זה, מה שגרם לתוסף לחשוב שהסנכרון הצליח.
המיירט השני בו השתמשתיpre_get_postsהוו. הוו הזה מופעל לפני שוורדפרס מבצעת שאילתת מסד נתונים. ההיגיון שלי הוא שבכל פעם שמנהל מבצע פעולה ב-backend, או כאשר תוסף מבצע פעולות אסינכרוניות/סינכרוניות, יש למזג את המזהים שלא נכללו לתוך...post__not_inבפרמטרים.
אחרי שסיימתי לכתוב את זה, עשיתי בדיקה.
ראשית, נכנסתי לשרת האחורי, פתחתי אחד מהמאמרים שלא נכללו, ביצעתי כמה שינויים קלים ולחצתי על עדכון. החיפוש נשמר בהצלחה ללא שגיאות. לאחר מכן בדקתי את שרת החיפוש של Meilisearch, ואינדקס המאמר נותר ללא שינוי; לא הופיע שום דבר חדש.
לחצתי שוב על "אינדקס פוסטים" ובניתי מחדש את כל האינדקס. לאחר המתנה של זמן מה, בדקתי את ה-backend של Meilisearch. המאמרים שלא נכללו עדיין היו שם.
זה נגמר.
ניתוח מעמיק: כיצד פועל מנגנון הביטוח הכפול?
למען האמת, התהליך הזה הזכיר לי משהו די מעניין.
אתם יודעים, בשנות ה-80 של המאה ה-19, כאשר החשמל רק הפך נפוץ בארצות הברית, בעלי מפעלים רבים הוציאו כסף רב על קניית גנרטורים ומנועים חשמליים והתקנתם במפעלים שלהם. עם זאת, לאחר ההתקנה, אנשים רבים גילו כי יעילות הייצור לא השתפרה באופן משמעותי.
为什么?
מכיוון שהם פשוט החליפו את מנוע הקיטור במנוע חשמלי, אבל המבנה הכללי, התהליכים ושיטות הניהול של המפעל נותרו ללא שינוי. החשמל היה חדש, אבל הגישה לשימוש בו הייתה ישנה.
אלו שבאמת נהנו מפריחת החשמל היו למעשה הקבוצה הראשונה שהבינה "מה באמת משמעות החשמל". הם לא רק שינו את מקור הכוח שלהם; הם עיצבו מחדש את כל תהליך הייצור שלהם.
אותו הדבר נכון גם לגבי עידן הבינה המלאכותית . אנשים רבים משתמשים בבינה מלאכותית ככלי, אך מעטים שוקלים איזה היגיון הוא משנה. הכלי עצמו חדש, אך ייתכן שאופן החשיבה בו נעשה שימוש נותרה מיושנת.
לדוגמה, כשהגדרתי חסימת חיפוש בוורדפרס, כנראה שלא הייתי מצליח לגרום לזה לעבוד אם הייתי פשוט עוקב אחר השיטות הסטנדרטיות בתיעוד התוסף. הסיבה לכך היא שלוגיקת הסנכרון של Scry Search כבר אינה הגישה המסורתית של "שמור מאמר אחד, סנכרן מאמר אחד"; יש לה תורים אסינכרוניים, עיבוד אצווה ומערכת מנגנונים משלה.
אתה צריך להבין איך המנגנון הזה עובד לפני שתוכל למצוא פריצת דרך אמיתית.
מגבלות ואמצעי זהירות של התוכנית
עם זאת, אני חייב לומר בכנות שגם התוכנית הזו אינה מושלמת.
יש לו מגבלה משמעותית: הוא יכול לנהל רק סנכרונים עתידיים ואינו יכול למחוק אוטומטית רשומות היסטוריות קיימות ב-Meilisearch. במילים אחרות, אם כבר סנכרנתם את המאמרים הללו, עדיין תצטרכו למחוק ידנית את הנתונים הישנים בלוח המחוונים של Meilisearch או באמצעות פקודות API.
זוהי משימה חד פעמית; ברגע שתסיימו, לא תצטרכו לדאוג יותר לגביה. אבל אני צריך להבהיר זאת מראש, כדי שאחרי שתפרסו את הקוד, לא תמצאו את המאמרים האלה עדיין בתוצאות החיפוש ותניחו שהקוד לא נכנס לתוקף.
נקודה נוספת שיש לציין היא שגישה זו מסתמכת על ארכיטקטורת הרשת ומסד הנתונים הבסיסית של וורדפרס. כל עוד גרסאות עתידיות של תוסף Scry Search ימשיכו לפעול על סמך ארכיטקטורה זו, מיירט זה יישאר יעיל. עם זאת, אם אי פעם יעבור למנגנון סנכרון שונה לחלוטין, ייתכן שיהיה צורך בהתאמה מחדש.
למען האמת, זה לא סביר. כל המערכת האקולוגית של וורדפרס בנויה על ארכיטקטורה זו, וכמעט בלתי אפשרי שתוספים יעקפו אותה לחלוטין.
מדריך שלושה שלבים ליישום
/**
* 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));
}
});
לבסוף, בואו נסכם את שלבי הפעולה.
ראשית, העתיקו את הקוד לתחתית קובץ ה-functions.php שלכם, או הוסיפו אותו באמצעות התוסף Code Snippets. לאחר מכן, בחלק העליון...defineבמערך, הזן את המזהה של המאמר או הדף שברצונך לא לכלול.
השלב השני הוא ניקוי אינדקסים היסטוריים. התחבר ללוח המחוונים של Meilisearch, או השתמש בפקודות API כדי למחוק ידנית את נתוני האינדקס הישנים עבור המאמרים שלא נכללו.
השלב השלישי הוא בדיקה. עבור אל השרת האחורי ובצע שינויים קלים במאמר שלא נכלל, לחץ על עדכון, ולאחר מכן בדוק את השרת האחורי של Meilisearch. אם לא מופיע אינדקס חדש, החסימה נכנסה לתוקף.
למען האמת, תמיד הרגשתי קצת אשם לגבי כתיבת מאמרים טכניים כאלה.
הדברים שאני משתף עשויים להיות שימושיים לחלק מהאנשים, אך עבור אחרים אלו עשויים להיות רק פעולות בסיסיות.
אבל תהליך יישום חסימת החיפוש בוורדפרס הפעם היה באמת מעמיק. לעתים קרובות, הבעיות שאנו נתקלים בהן אינן נובעות מחוסר פתרונות, אלא משום שהחשיבה שלנו מוגבלת על ידי מסגרות קיימות.
תוסף החיפוש של Scry מספק וו סינון, מה שמוביל אותנו להאמין שזו האפשרות היחידה. עם זאת, הארכיטקטורה כולה של וורדפרס מציעה הרבה יותר אפשרויות. יירוט יכול להתבצע בשכבת הרשת, וניתן לעשות זאת גם בשכבת מסד הנתונים. כל עוד אתם מוכנים לחשוב, תמיד יש דרך.
זו הסיבה שאני נהנה להתעסק עם הגאדג'טים הטכניים האלה. זה לא עניין של להשוויץ או לנסות להיראות מרשים. זה פשוט בגלל שהתחושה של להבין לחלוטין בעיה היא מספקת בצורה יוצאת דופן.
בדיוק כמו הפעם, מהבלבול הראשוני, דרך ההשתקפות באמצע, ועד לפתרון הסופי, כל התהליך היה כמו פתרון חידה.
התעלומה נפתרה, התשובה נחשפה, מסתבר שזה היה כל כך פשוט.
אבל אם לא עברתם את התהליך המבלבל הזה, לעולם לא תבינו את השמחה הפשוטה הזו.
עכשיו, אחרי שקראתם עד כאן, אם זה היה מועיל לכם, אנא עשו לייק ושתפו. אם אתם רוצים לקבל עדכונים ראשונים, אתם יכולים גם לעקוב אחריי.
תודה שקראתם את המאמר שלי. נתראה בפעם הבאה.
אני מקווה שהמאמר "כיצד לשלול לחלוטין מזהה פוסט ספציפי מסנכרון עם Meilisearch בוורדפרס (תוסף חיפוש Scry בפועל)" ששותף בבלוג של צ'ן וייליאנג ( https://www.chenweiliang.com/ ) יהיה לעזר עבורכם.
אל תהססו לשתף את הקישור למאמר הזה: https://www.chenweiliang.com/cwl-34343.html
