البحث باللغة العربية في ووردبريس: النتائج التي يفوتها دون علمك
Jaafar Abazid
نسخة عربية مختصرة. أما المقال الكامل بالإنجليزية، وما يتضمنه من قياسات، وجداول المقارنة قبل وبعد، وجميع التفاصيل، فيمكنك الاطلاع عليه هنا.
مئتان وخمسون ألف مقال، والشكوى الوحيدة التي كانت تصلنا عن البحث أنه بطيء. لم يتحدث أحد عن دقته، بل عن وقت الانتظار: تكتب اسماً في بحث لوحة التحكم، ثم تنشغل بشيء آخر ريثما تظهر النتيجة.
تلك هي الشكوى السهلة، لأنها تصل إليك؛ فهناك من يخبرك بها. أما الشكوى الأخرى فلا تصل أبداً، وقد استغرقني وقتاً أطول مما ينبغي لأدرك أنها غائبة: لم يخبرني أحد قط أن البحث لم يجد خبراً نعلم يقيناً أننا نشرناه. ولن يفعل أحد، لأن البحث الذي لا يعثر على شيء لا يبدو وكأنه خلل، بل يبدو دليلاً على أننا لم ننشر ذلك الخبر أساساً.
ما الذي يحدث فعلاً؟ يعتمد البحث الافتراضي في ووردبريس على مطابقة النص حرفياً، باستخدام LIKE '%word%' على العنوان، والنص الانتقائي، والمحتوى. وفي اللغة العربية، يعني ذلك أن أي اختلاف إملائي شائع يؤدي إلى عدم العثور على أي نتيجة. فالبحث عن محمد لا يجد مُحَمَّد (مع التشكيل)، والبحث عن أحمد لا يجد احمد (لاختلاف الهمزة على الألف)، كما أن الكلمة المنتهية بـ ه لا تجد نظيرتها المنتهية بـ ة. وينطبق الأمر نفسه على التطويل (ـ)، وكذلك على الألف المقصورة والياء (ى و ي). بالنسبة للقارئ، كلها تمثل الكلمة نفسها، أما بالنسبة لمحرك البحث، لا يطابق أيٌّ منها الآخر.
والمفاجأة: قاعدة البيانات تعرف الإجابة، لكن ووردبريس لا يسألها عنها. فترميز المحارف Collation الذي يفرضه ووردبريس على جداوله، utf8mb4_unicode_520_ci، ليس جاهلاً باللغة العربية. فإذا سألت MySQL باستخدام مقارنة مباشرة (=)، فسيعتبر مُحَمَّد ومحمد متساويين تماماً، إذ يتجاهل التشكيل ويعامل الكلمتين كسلسلة نصية واحدة. لكن ووردبريس يستخدم LIKE '%…%'، ومطابقة الأنماط باستخدام Wildcard تتجاوز هذا السلوك بالكامل، فتُهدر كل تلك المعرفة اللغوية الموجودة في قاعدة البيانات بمجرد إحاطة الكلمة بعلامتي %. فالإمكانية موجودة بالفعل، لكن بنية البحث في ووردبريس تتحجاوزها دون أن تستفيد منها.
لكن حتى توظيف ذلك لن تكون كافياً. فالـ Collation يتجاهل الحركات، مثل التشكيل، لأنها تُضاف فوق الحروف. أما الهمزة فليست علامة، بل إن أ و ا حرفان مختلفان، وكذلك ى و ي، و ة و ه. ولا يوجد Collation يعامل هذه الأحرف على أنها متطابقة، مهما كانت طريقة المقارنة، مع أنها ليست حالات نادرة، بل من أكثر الاختلافات الإملائية شيوعاً في الاستخدام اليومي. لذلك لا مفر من توحيد (تطبيع) صيغة النص Normalisation بأنفسنا، وبشكل مقصود، على جانبي المقارنة.
أما الثمن فهو الجانب الذي يشتكي منه المحررون بالفعل. فاستعلام LIKE الذي يبدأ بـ % لا يستطيع استخدام أي فهرس Index، لذلك تتحول كل عملية بحث إلى مسح كامل للجدول Full Table Scan. والمفارقة أن أبطأ عملية بحث هي تلك التي لا تعثر على أي نتيجة، لأنها تضطر إلى فحص جميع الصفوف لتتأكد من أن النتيجة غير موجودة فعلاً. وهذا يعني أن عمليات البحث التي تعود بصمت دون أي نتائج هي نفسها الأكثر كلفة من حيث التنفيذ. فالشكوى التي تصلك، والشكوى التي لا تصلك أبداً، هما في الحقيقة الاستعلام نفسه.
ما الذي بنيناه، وما الذي لم يحلّه. فعلنا ما بدا أنه الحل الصحيح: أنشأنا جدولاً خارج ووردبريس على AWS، يضم صفاً واحداً لكل مقال، ويُحدَّث مع كل عملية نشر أو تعديل أو حذف. توقفت عمليات البحث عن فحص ربع مليون صف، واختفت شكاوى البطء. لكننا لم نوحّد صيغة النص العربي Normalise أبداً. ظل الجدول الجديد يخزن النص ويطابقه حرفياً كما هو، لذلك استمرت جميع عمليات البحث التي تستخدم صيغاً إملائية مختلفة في العودة بلا نتائج، تماماً كما كان يحدث من قبل. وقد استغرقنا سنوات لندرك الدرس: البطء مشكلة بنية تحتية، أما المطابقة فليست كذلك، ولا يمكن لأي قدر من التوسع أن يحول الأولى إلى حل للثانية. توحيد الصيغة مشكلة نصّية، وإن لم تحلّها تبعتك إلى AWS.
الطبقة التي كانت تنقصنا. الحل بسيط، وهو نفسه مهما كان مكان وجود فهرس البحث: وحّد صيغة النص على جانبي المقارنة. احتفظ بنسخة موحّدة الصيغة من النص القابل للبحث، وأنشئ لها فهرساً Index، ثم مرّر كل استعلام بحث عبر عملية توحيد النص نفسها قبل المطابقة. أزل التشكيل، واحذف التطويل، ووحّد أشكال الألف (أ، إ، آ، ٱ تصبح جميعها ا)، ووحّد ة/ه و ى/ي. وأزل أداة التعريف الـ بحذر، مع وجود شرط يمنع حذفها من بداية الكلمات القصيرة، ثم توقف عند هذا الحد. قد يبدو حذف أحرف الجر والعطف المفردة مثل و، ف، ب، ك، ل فكرة مغرية، لكنه مدمّر، لأنها قد تكون أيضاً جزءاً أصيلاً من الكلمة، فيتحول بيت إلى يت، وتتحول فكرة إلى كرة، وهي كلمة مختلفة تماماً. واترك الأحرف اللاتينية كما هي (WordPress، AWS، S3)، ولا تعبث بها.
ولا يتطلب أي من ذلك وجود بنية سحابية. صحيح أن قصتنا مرت عبر جدول على AWS، لكن ذلك كان حلاً لمشكلة التوسع، لا لمشكلة المطابقة. وحتى في ووردبريس الذي يعمل على خادم واحد، فإن الاحتفاظ بنسخة موحدة من النص في قاعدة البيانات نفسها، مع توحيد استعلام البحث أيضاً، كفيل بحل كلٍ من النتائج المفقودة ومشكلة البطء، دون الحاجة إلى أي مكونات خارجية.
والاختبار الحقيقي. جرّبناه أخيراً على أرشيف حقيقي: ربع مليون مقال عربي، ونصف مليون ملف وسائط، على نسخة من أرشيف غرفة أخبار قيد الاستخدام. وكانت عملية بحث واحدة كافية لحسم الأمر كله.
| البحث عن «مُحَمَّد» في 250,000 مقال | النتائج | الزمن |
|---|---|---|
| ووردبريس | 1 | 4.8 ثانية |
| مع الإضافة | 28,238 | 0.55 ثانية |
نتيجة واحدة فقط. من بين 28,238 مقالاً ورد فيها هذا الاسم، لم يعثر ووردبريس إلا على مقال واحد، لأنه وحده كُتب بالتشكيل نفسه تماماً. أما المقالات الـ 28,237 الأخرى، فكانت موجودة في قاعدة البيانات طوال الوقت، ومع ذلك لم يكن بوسع أي شخص يبحث عن هذا الاسم أن يراها.
السرعة هي ما كنت ستكتبه في التقرير باعتباره شكوى. أما العمود الآخر، فهو ما لم يكن أحد ليشتكي منه أصلاً.
الإضافة. جمعنا كل ذلك في إضافة must-use مكوّنة من ملف واحد، مفتوحة المصدر بترخيص GPL، ومتوفرة على GitHub وPackagist بالإصدار 0.9.3 حتى وقت كتابة المقال. وبشكل افتراضي، تجمع الإضافة كل ما يمكن البحث عنه في المقال، أي العنوان، والنص الانتقائي، والمحتوى، في عمود واحد بعد توحيد صيغتها Normalisation، مع إنشاء فهرس FULLTEXT Index له، ثم تعيد توجيه البحث في ووردبريس لاستخدامه، لتحل مشكلة البحث في الموقع وفي لوحة التحكم معاً.
كما أن الإضافة تغطي ملفات الوسائط بحقولها الأربعة: العنوان، والتعليق Caption، والنص البديل Alt Text، واسم الملف، بحيث يمكنك العثور على صورة سواء بالعنوان العربي المصاحب لها أو باسم ملفها، مع العلم أن ووردبريس نفسه لا يبحث في النص البديل Alt Text إطلاقاً.
أما لمن يعتمد على فهرسة خارجية (مثل جدول على AWS أو OpenSearch)، فتوفّر الإضافة وضع normaliser الذي يتيح دالة لتوحيد الصيغة، ويطلق حدثاً عند كل عملية حفظ، بحيث يستخدم طرفا المطابقة الكود نفسه في عملية التوحيد.
composer require mantekio/wp-arabic-search
ونقطة أخيرة تستحق الذكر: لا يقوم FULLTEXT بفهرسة الكلمات التي يقل طولها عن ثلاثة أحرف، وهو ما يشمل في العربية كلمات مثل من، وفي، وما، وعن، وهي كلمات حقيقية تتكرر في عدد كبير من عمليات البحث. فالفهرس الذي لم يرَ كلمةً قط لا يمكنه العثور عليها، ولذلك فإن الاعتماد عليه وحده يعني إرجاع صفحة نتائج فارغة لاستعلام يستطيع بحث ووردبريس التقليدي الإجابة عنه دون أي مشكلة. وهذا بالضبط هو العطل الصامت الذي يدور حوله هذا المقال، وهو العطل الذي كدنا نقع فيه نحن أيضاً. لذلك تستبعد الإضافة هذه الكلمات من شرط المطابقة بدلاً من اشتراط وجودها، وإذا لم يتبقَّ في استعلام البحث أي كلمة غيرها، فإنها تعيد تمرير الاستعلام إلى بحث LIKE الأصلي كما هو دون أي تعديل.
القاعدة التي تلتزم بها الإضافة بسيطة: عندما لا تستطيع الإضافة أن تحسّن النتيجة، فإنها تتنحّى جانباً، بدلاً من أن تقدّم نتائج أسوأ من البحث الذي جاءت لتحلّ محله.
وكلمة صريحة عن عمر الإضافة: ما تزال الإضافة جديدة، وهي تحمل حالياً الإصدار 0.9.3. ومن الجدير بالذكر أنها وصلت بالفعل إلى إصدارها الرابع، لكن السبب بسيط: ست جولات من الاختبارات كشفت عن خطأ في كل مرة، ولم يُكتشف أي واحد منها بمجرد قراءة الكود. وكان أسوأها في الإصدار الأول. فعند البحث عن كلمة عربية من حرفين، مثل من أو في، كانت الإضافة تعيد صفحة نتائج فارغة تماماً، لأن الشرط الذي يفترض أن يستبعد الكلمات الأقصر من الحد الأدنى الذي يفهرسه FULLTEXT كان يحسب البايتات لا الأحرف. وبما أن الحرف العربي يشغل بايتين، فقد كانت هذه الكلمات تمر من الشرط، ثم تتحول إلى جزء من استعلام يبحث عن كلمات لا يحتويها الفهرس أصلاً. وهذا يعني أن إضافةً تقوم فكرتها من الأساس على أن البحث باللغة العربية قد يفشل في العثور على النتائج بصمت، خرج أول إصدار لها بطريقة تجعل البحث العربي يفشل بصمت في العثور على النتائج.
لقد أُصلحت جميع هذه الأخطاء، لكن المغزى أهم من الأخطاء نفسها: فقد كانت كلها مختبئة داخل الكود، لكنها أصبحت واضحة تماماً بمجرد تشغيله واختباره فعلياً.
الشرح الكامل، وجداول القياس قبل وبعد، وجميع التفاصيل الفنية موجودة في المقال باللغة الإنجليزية. وإذا كان أرشيفك باللغة العربية، ولم تجرب يوماً كيف يتعامل محرك البحث لديك مع الهمزة، فتواصل معنا.