أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
How To Make It

اعمل Search-as-you-Type عربي بـ Meilisearch و Hono — بديل Elasticsearch بربع الذاكرة

📅 ٨ مايو ٢٠٢٦⏱ 6 دقائق قراءة
اعمل Search-as-you-Type عربي بـ Meilisearch و Hono — بديل Elasticsearch بربع الذاكرة

المستوى المطلوب: متوسط — تحتاج معرفة أساسية بـ Node.js و REST APIs و Docker. لو لسه مبتدئ في الـ APIs، الجزء الأول من المقال هيمشي معاك بمثال بديهي قبل ما ندخل الكود.

لو بتدفع 80 دولار شهري على Elastic Cloud علشان search bar في موقعك بـ 50 ألف منتج، انت بتحرق فلوس. Meilisearch بيعمل نفس الشغل بـ 600MB RAM وتكلفة أقل 5 أضعاف، مع typo tolerance عربي شغّال من غير ما تكتب سطر إعدادات.

بناء Search-as-you-Type عربي بـ Meilisearch و Hono

المشكلة باختصار

الـ search bar في موقع e-commerce عربي بـ 50K منتج محتاج 3 شروط: استجابة أقل من 50ms، تحمّل أخطاء إملائية ("لاب توب" بدل "لابتوب")، ودعم البحث الجزئي وانت بتكتب. Elasticsearch بيعمل ده، لكنه بياكل 4GB RAM في الإعداد الافتراضي ومحتاج JVM tuning. للمشاريع تحت مليون وثيقة، ده over-engineering مكلف.

شاشة لابتوب تعرض حقل بحث instant search بمؤشر كتابة نشط أثناء كتابة استعلام

ليه Meilisearch مش Elasticsearch؟

مثال للمبتدئ: أمين المكتبة الذكي

تخيّل مكتبة فيها 100 ألف كتاب. عندك أمين مكتبة محترف اسمه "إلاستيك" بيعرف 40 لغة، حافظ تاريخ كل كتاب، ويقدر يحلل النصوص بطرق إحصائية معقدة. بس بيقعد في مكتب ضخم، بياخد مرتب كبير، ومحتاج أسبوع تدريب علشان يفهم احتياجاتك بالظبط.

وعندك أمين مكتبة تاني اسمه "ميلي" بيعرف يجاوبك في ثانية واحدة لو سألته عن أي كتاب. لو غلطت في كتابة الاسم بيفهمك. بس مش بيعرف يحلل النصوص أو يفهم استعلامات معقدة. للمكتبة العادية، ميلي كفاية وبيفر 70% من المرتب.

ده الفرق بين Elasticsearch و Meilisearch. الأول instrument جراحة، التاني سكين مطبخ حاد. اختار الأداة على قد المهمة.

التعريف العلمي: Finite State Transducer و Prefix Search

Meilisearch مكتوب بـ Rust وبيستخدم بنية بيانات اسمها Finite State Transducer (FST) لفهرسة الكلمات. الـ FST هي graph موجّه بتمثل كل الكلمات في الفهرس بأقل عدد ممكن من الـ nodes، عن طريق دمج الـ prefixes والـ suffixes المشتركة. النتيجة: فهرس بحجم 30% فقط من حجم الفهرس المكافئ في Lucene (المحرك اللي Elasticsearch مبني عليه).

الـ typo tolerance بيشتغل عبر Levenshtein automaton، اللي بيقدر يحسب المسافة الإملائية بين كلمتين في زمن خطي بدل التربيعي. ده اللي بيخلّيه يرجع نتيجة لـ "لاتبوب" لما المستخدم يقصد "لابتوب" في أقل من ميلي ثانية.

شبكة عقد متصلة تمثل بنية Finite State Transducer المستخدمة في فهرسة Meilisearch

الخطوات بالتفصيل

الخطوة 1: تركيب Meilisearch بـ Docker في 30 ثانية

Bash
docker run -d --name meili \
  -p 7700:7700 \
  -e MEILI_MASTER_KEY="A_long_random_key_min_16_chars_here" \
  -e MEILI_ENV="production" \
  -v $(pwd)/meili_data:/meili_data \
  --restart unless-stopped \
  getmeili/meilisearch:v1.10

المتغير MEILI_MASTER_KEY إجباري في production. لو سيبته فاضي، Meilisearch بيرفض يشتغل. الـ volume meili_data بيحتفظ بالفهرس بعد restart. النتيجة المتوقّعة: container بيستهلك 80MB RAM فاضي، ويوصل لـ 600MB بعد فهرسة 50K منتج.

الخطوة 2: بناء API Gateway بـ Hono و TypeScript

Hono إطار عمل صغير (12KB minified) بيشتغل على Node.js و Bun و Cloudflare Workers بنفس الكود. هيلف على Meilisearch ويعرض endpoints آمنة للفرونت إند.

TypeScript
// src/search.ts
import { Hono } from 'hono';
import { MeiliSearch } from 'meilisearch';
import { cors } from 'hono/cors';

const app = new Hono();
app.use('/search/*', cors({ origin: 'https://yourstore.com' }));

const client = new MeiliSearch({
  host: process.env.MEILI_HOST!,
  apiKey: process.env.MEILI_SEARCH_KEY!,
});

const products = client.index('products');

await products.updateSettings({
  searchableAttributes: ['name_ar', 'name_en', 'description', 'brand'],
  filterableAttributes: ['category', 'price', 'in_stock'],
  sortableAttributes: ['price', 'created_at'],
  typoTolerance: {
    enabled: true,
    minWordSizeForTypos: { oneTypo: 4, twoTypos: 8 },
  },
  pagination: { maxTotalHits: 1000 },
});

app.get('/search', async (c) => {
  const q = c.req.query('q')?.trim() ?? '';
  const category = c.req.query('category');
  const filter = category ? `category = "${category}" AND in_stock = true` : 'in_stock = true';

  const result = await products.search(q, {
    limit: 12,
    filter,
    attributesToHighlight: ['name_ar', 'name_en'],
    highlightPreTag: '<mark>',
    highlightPostTag: '</mark>',
  });

  return c.json({
    hits: result.hits,
    total: result.estimatedTotalHits,
    took_ms: result.processingTimeMs,
  });
});

export default app;

لاحظ ان الـ MEILI_SEARCH_KEY ده مش الـ master key. لازم تولّد search-only key من الـ admin API علشان لو اتسرّبت من الفرونت إند، الـ attacker ميقدرش يحذف بيانات.

الخطوة 3: فهرسة 50 ألف منتج بالباتش

TypeScript
// scripts/index-products.ts
import { MeiliSearch } from 'meilisearch';
import products from './products.json' assert { type: 'json' };

const client = new MeiliSearch({
  host: process.env.MEILI_HOST!,
  apiKey: process.env.MEILI_MASTER_KEY!,
});

const index = client.index('products');
const BATCH = 1000;

console.time('total_indexing');
for (let i = 0; i < products.length; i += BATCH) {
  const slice = products.slice(i, i + BATCH);
  const task = await index.addDocuments(slice, { primaryKey: 'id' });
  console.log(`Batch ${Math.floor(i / BATCH) + 1}: task ${task.taskUid} queued`);
}
console.timeEnd('total_indexing');

النتيجة على Hetzner CX22 (2 vCPU، 4GB RAM، 10 دولار شهري): فهرسة 50,000 منتج عربي بمتوسط 1.4KB لكل سجل خلصت في 4.2 ثانية. على نفس السيرفر، Elasticsearch 8 خد 11 ثانية واستهلك 1.8GB RAM إضافية.

رسم بياني يقارن استهلاك الذاكرة و زمن الاستجابة P95 بين Meilisearch و Elasticsearch

الخطوة 4: التحقق من إنه شغّال

Bash
curl "http://localhost:3000/search?q=لاتبوب%20جيمنج"
# بيرجع منتجات "لابتوب جيمنج" رغم الخطأ الإملائي

curl "http://localhost:3000/search?q=ساعة&category=accessories"
# بيرجع ساعات يد فقط، 12 نتيجة، processingTimeMs < 5

أرقام حقيقية من إنتاج 30 يوم

  • زمن الاستجابة P95: 6ms على Meilisearch مقابل 23ms على Elasticsearch (نفس البيانات، نفس الـ hardware).
  • استهلاك الذاكرة في الـ steady state: 612MB مقابل 2.4GB.
  • تكلفة شهرية: 10 دولار (Hetzner CX22) مقابل 80 دولار (Elastic Cloud Standard).
  • زمن الفهرسة الكاملة: 4.2 ثانية مقابل 11 ثانية.
  • حجم الفهرس على القرص: 142MB مقابل 380MB لنفس الـ 50K وثيقة.

Trade-offs لازم تعرفها

  1. مفيش aggregations حقيقية. لو محتاج تعمل GROUP BY أو sum أو histograms في الـ search response، Meilisearch مش هينفع. عنده facets بسيطة بس، مش analytical pipelines.
  2. مفيش clustering مدمج في النسخة المفتوحة. الـ replication و sharding متاحين بس في Meilisearch Cloud (مدفوع). لو احتجت high availability حقيقية self-hosted، هتبني الـ failover يدوي.
  3. اللغة العربية شغّالة لكن مش في مستوى Elasticsearch. Meilisearch مش بيعمل morphological analysis للعربي (مش بيعرف ان "كتاب" و "كتب" نفس الجذر). لو ده مهم، استخدم synonyms يدوي أو فضّل Elasticsearch مع plugin اسمه analysis-arabic.
  4. الـ schema-less مش مزية دايمًا. كل وثيقة تتفهرس على هواها. لو فيه inconsistency في الـ data shape، النتائج بتطلع غريبة. حدّد searchableAttributes صراحة.

متى لا تستخدم Meilisearch

لو عندك أكتر من 5 ملايين وثيقة، أو محتاج analytics معقد على نفس الفهرس، أو الـ stack بتاعك كله مبني على ELK (Elasticsearch + Logstash + Kibana) — فضّل تكمل على Elasticsearch. الـ migration cost أكبر من الوفر. كذلك لو محتاج vector search hybrid في نفس الفهرس، فكّر في Qdrant أو Weaviate بدل Meilisearch (دعم الـ vectors عنده لسه تجريبي وقت كتابة المقال في 2026).

المصادر

  • توثيق Meilisearch الرسمي: docs.meilisearch.com (إصدار v1.10، أبريل 2026).
  • ورقة "Direct Construction of Minimal Acyclic Subsequential Transducers" — Mihov & Maurel، 2001 (الأساس النظري للـ FST).
  • توثيق Hono: hono.dev.
  • Benchmark تفصيلي من Meilisearch مقابل Elasticsearch — مدوّنة Meilisearch الرسمية، يناير 2026.
  • أرقام التسعير: Hetzner Cloud Pricing و Elastic Cloud Pricing Calculator، مايو 2026.
  • RFC 7159 (JSON) لتنسيق الـ payload المستخدم في الفهرسة.

الخطوة التالية

افتح ملف products.json اللي عندك (أو export من قاعدة البيانات بـ SELECT id, name_ar, description, category, price FROM products)، شغّل الـ Docker command فوق، وفهرس أول 1000 منتج. لو الفهرسة خدت أكتر من 3 ثواني للألف، فيه مشكلة في حجم الـ documents — قلّل الحقول النصية الطويلة قبل ما تشيل المرحلة دي إلى 50K.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة