جوه المحرك · فصل ٢

Inverted Index: ليه البحث سريع

Inverted index · documents · Elasticsearch service
🎯 الهدف: تفهم Elasticsearch خدمة مش مكتبة، وإزاي الـ inverted index بيوصّلك من الكلمة للمستندات من غير ما تلف على كل المنتجات.

Elasticsearch خدمة لوحدها

Elasticsearch محرك بحث وتحليل موزّع. بتبعتله داتا، يعملها indexing، وبعدين تبحث فيها. معاه full-text search، ترتيب، فلاتر، aggregations، fuzzy، autocomplete، و highlighting. ومتصمم يتوزع على أكتر من آلة لما الداتا أو الترافيك يكبروا.

مش package تحطه جوه الـ API وخلاص. عملية لوحدها ليها RAM وديسك وبورت. في التطوير تشتغل بـ Docker جنب الـ API والداتابيز. في الإنتاج يا تدير الـ cluster بنفسك يا تاخد خدمة جاهزة. نفس أفكار البحث موجودة في OpenSearch، والتفاصيل بتختلف. الأمثلة هنا على Elasticsearch.

من المستند للكلمة، ولا من الكلمة للمستند؟

الطريقة الساذجة: مع كل بحث تلف على العشر مليون منتج وتشوف الكلمة موجودة ولا لأ. ده document → words.

وقت الـ indexing، Elasticsearch يبني هيكل عكسي: inverted index. كل كلمة، وجنبها المستندات اللي ظهرت فيها. البحث بقى word → documents.

الكلمةمستندات
iphoneموبايل iPhone 15 Pro، كفر compatible with iPhone
proموبايل iPhone 15 Pro
caseالكفر بس

لما اليوزر يكتب iphone، المحرك مش بيبتدي من المنتج الأول. بيروح لسطر الكلمة في الفهرس ويطلّع الليست.

المستند في Elasticsearch مش صف SQL. مستند البحث بتاع المنتج ممكن يبقى JSON فيه الاسم والوصف والبراند والسعر والتقييم والمخزون، حتى لو في SQL دول خمس جداول. شكل المستند ده هنبنيه في فصل المزامنة.

الفهرس مش ببلاش وقت الكتابة

كل ما تحفظ منتج أو تغيّر سعره، الفهرس لازم يتحدث. القراءة بتبقى سريعة عشان الكتابة دفعت التمن قبل كده. وعشان كده Elasticsearch near-real-time: بعد ما الـ index ينجح، البحث ممكن يفضل ثانية لحد ما يحصل refresh (الافتراضي حوالي ثانية). متستناش إن الطلب اللي بعده على طول يشوف التعديل.

🧪 Lab

شغّل Elasticsearch محليًا. الملف ده للتطوير بس: الأمان مقفول عشان متتعطلش في أول تجربة. في الإنتاج سيبه شغال وابعت API key.

compose.yaml
services:  elasticsearch:    image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0    environment:      - discovery.type=single-node      - xpack.security.enabled=false      - ES_JAVA_OPTS=-Xms512m -Xmx512m    ports:      - "9200:9200"

على لينكس لو الـ container وقع بدري، دور على vm.max_map_count. راجع رسالة Docker، متخمّنهاش.

src/es.js
import { Client } from "@elastic/elasticsearch";export const es = new Client({  node: process.env.ELASTIC_URL ?? "http://localhost:9200",});
src/seed.js
import { es } from "./es.js";const index = "products";const exists = await es.indices.exists({ index });if (!exists) await es.indices.create({ index });await es.index({  index,  id: "p-1001",  refresh: true,  document: {    name: "Apple iPhone 15 Pro",    description: "موبايل بكاميرا 48 ميجا.",  },});const found = await es.search({  index,  query: { match: { name: "iphone" } },});console.log(found.hits.hits.map((hit) => hit._source.name));

refresh: true هنا عشان التجربة تشوف المستند فورًا. في مسار الكتابة الحقيقي سيبه للـ refresh العادي، عشان متعملش refresh مع كل طلب.

✅ الخلاصة — Checklist

🧠 اختبر نفسك
١) inverted index بيرتّب الدنيا إزاي؟
من الكلمة لقائمة المستندات، مش من المستند لكلماته وقت السؤال.
٢) ليه منستناش نتيجة البحث تتغير في نفس اللحظة بعد index ناجح؟
Elasticsearch near-real-time. المستند يبقى قابل للبحث بعد refresh.
٣) مين المفروض يفتح اتصال على بورت 9200؟
الـ API والخدمات الداخلية. مش متصفح اليوزر.