الكلمة اللي اليوزر كتبها مش هي اللي بتتخزن
Apple iPhone 15 Pro لو اتسجلت جملة واحدة، البحث عن iphone ممكن ميلقاش حاجة. التحليل بيكسر النص ويوحّده وقت الـ indexing ووقت السؤال، عشان الطرفين يتكلموا نفس اللغة.
الناتج توكنز زي apple و iphone و 15 و pro. من هنا تقدر تعمل lowercase، أو تشيل كلمات مالهاش معنى، أو توحّد المرادفات. القواعد دي قرار بزنس ولغة، مش زرار واحد اسمه “بحث عربي”.
كل مرحلة بتقرر إيه
بتشتغل على النص وهو لسه جملة. زي ما تحوّل ١٥ إلى 15، أو تشيل حركة، قبل التقسيم.
يقص الجملة كلمات. الـ standard tokenizer مناسب لأسماء المنتجات المختلطة. بيفصل على المسافات وعلامات الترقي.
بعد التقسيم تيجي token filters بالترتيب:
- lowercase:
iPhoneوiphoneيبقوا نفس التوكن. - stop words: كلمات زي
withوforو “من” و “في” بتتشال لو مش بتفرّق في البحث. متشلّهاش من غير ما تجرب، لأن “pro” مثلًا مش stop word ولو اتشالت هتبوّظ موديلات. - stemming: يرجع الكلمة لجذرها. مفيد في الوصف الطويل، وخطر على اسم المنتج. stemmer عربي قوي ممكن يقرّب كلمات مش عايزها تتقرب.
- synonyms:
آيفونوايفونوiphoneيبقوا حاجة واحدة. ولابتوبوlaptop. المرادف الغلط بيوسّع البحث ويزوّد نتائج مش مقصودة.
Analyzer للمتجر
import { es } from "./es.js";const index = "products";export const settings = { analysis: { char_filter: { indic_digits: { type: "mapping", mappings: ["٠ => 0", "١ => 1", "٢ => 2", "٣ => 3", "٤ => 4", "٥ => 5", "٦ => 6", "٧ => 7", "٨ => 8", "٩ => 9"], }, }, filter: { product_synonyms: { type: "synonym_graph", synonyms: [ "iphone, آيفون, ايفون", "laptop, لابتوب, لاب توب, notebook", "phone, موبايل, تليفون", ], }, }, analyzer: { product_text: { type: "custom", char_filter: ["indic_digits"], tokenizer: "standard", filter: ["lowercase", "arabic_normalization", "product_synonyms"], }, }, },};export const mappings = { properties: { sku: { type: "keyword" }, name: { type: "text", analyzer: "product_text" }, description: { type: "text", analyzer: "product_text" }, brand: { type: "keyword" }, category: { type: "keyword" }, price: { type: "float" }, rating: { type: "float" }, stock: { type: "integer" }, ram_gb: { type: "integer" }, storage_gb: { type: "integer" }, },};export async function ensureProductsIndex() { const exists = await es.indices.exists({ index }); if (exists) return; await es.indices.create({ index, settings, mappings });}brand من نوع keyword لأن الفلتر “Apple” تطابق كامل، مش كلمات. هتحتاجه في الـ facets. arabic_normalization بيلم أشكال حروف زي الألف، فمتكررش نفس الشغل بفلتر تاني من غير ما تقرا هو بيعمل إيه. المرادف لازم يتكتب بالشكل اللي طالع من الفلتر اللي قبله. لو التطبيع غيّر الألف، حط الشكل الجديد في القائمة، و_analyze هو الحكم.
تغيير الـ analyzer بعد ما الإندكس اتملّى مش بيرجع يحلّل المستندات القديمة. هتحتاج reindex. عشان كده جرّب المرادفات على عينة قبل ما تفتحها على عشر مليون منتج.
🧪 Lab
بعد ما الإندكس يتخلق، اسأل المحرك هو شايف الجملة إزاي:
curl -s localhost:9200/products/_analyze \ -H 'Content-Type: application/json' \ -d '{"analyzer":"product_text","text":"آيفون ١٥ برو"}'
المفروض تشوف توكنز قريبة من iphone و 15 و برو (أو pro لو ضفت المرادف). لو ١٥ فضلت زي ما هي، الـ char filter مش واصل للـ analyzer. لو آيفون مفترق عن iphone، مرادفات الـ synonym لسه مش في الخط.