عندما تكتب ثلاث كلمات في Google وتصل الإجابة في جزء من الثانية ، مع تصحيح أخطائك ، فهذا ليس قاعدة بيانات SQL تتصفح مليارات الصفحات : إنها فهرس معكوس ، قاموس « كلمة → الصفحات التي تحتويها ». يطبّق Elasticsearch و OpenSearch نفس هذا المبدأ على بياناتك الخاصّة. وعندما يقترح عليك Netflix « الأشخاص الذين أحبّوا هذا شاهدوا أيضًا… » أو يقترح عليك Facebook صديق صديق ، فهذه علاقات نتصفحها ، وليس صفوفًا نصفّيها : هذا عمل قاعدة بيانات الرسم البيانيّ مثل Neo4j.
| من | الأداة | لماذا |
|---|---|---|
| Wikipedia | Elasticsearch | شريط البحث لجميع المقالات بجميع اللغات متسامح مع الأخطاء |
| Netflix و Uber و Slack | Elasticsearch + Kibana | مليارات الأسطر من السجلّات يوميًّا ، يتم استكشافها مباشرة للعثور على عطل في ثوان قليلة |
| Stack Overflow و GitHub | Elasticsearch | البحث الكامل النص عن الأسئلة والإجابات والأكواد |
| Amazon | OpenSearch | المحرّك الذي أنشأته Amazon وتحتفظ به لمحافظة نسخة 100% مفتوحة المصدر مباعة كخدمة مُدارة على AWS |
| NASA | Neo4j | قاعدة بيانات « الدروس المستفادة » من 50 سنة من المهام المربوطة معًا للعثور على سابقة في قفزات قليلة |
| اتحاد ICIJ (أوراق بنما) | Neo4j | 11.5 مليون مستند والروابط بين الشركات الوهميّة والقادة والبنوك يستكشفها 370 صحافيًّا عبر الرسم البيانيّ |
| eBay و Walmart | Neo4j | التوصيات في الوقت الفعليّ : « أولئك الذين اشتروا هذا… » تُحسب بمتابعة علاقات الشراء |
ما تشترك فيه هذه الشركات : لديها أيضًا قواعس بيانات SQL لدفع المستخدمين والطلبات والفواتير. تضيف محرّك بحث إلى الجانب للبحث وقاعدة رسم بيانيّ إلى الجانب للربط. هذا بالضبط ما ستبنيه في هذا المختبر بأحجام صغيرة.
تخيّل مدرسة كبيرة على الإنترنت. في الاستقبال أمينة مكتبة تجد في ثانية واحدة جميع الدورات التي تتحدّث عن « نشر الحاويات » حتّى لو كتبت « deploiement » بدون لكنة : هذا Elasticsearch. على الحائط تعرض شاشات حركة المرور الحيّة على الموقع والصفحات الخاطئة وأصول الزوّار : هذا Kibana الذي لا يُخزّن شيئًا لكنّه يرسم ما يحتويه Elasticsearch. في مكتب التوجيه ، مستشار يعرف الروابط بين الناس : من درس ماذا وأيّ دورة متطلّب لأيّ دورة أخرى وأيّ طلاب يتشابهون : هذا Neo4j. و OpenSearch؟ إنّها أمينة المكتبة التوأم المدرّبة في نفس المدرسة مثل Elasticsearch التي وظّفتها أولئك الذين يريدون عقدًا 100% مفتوح المصدر. أربع أدوات وطريقتان لترتيب المعلومات : حسب الكلمات (محرّك بحث) أو حسب الروابط (رسم بيانيّ).
| الأداة | الإصدار في المختبر | الدور | تتحدّث معها عبر |
|---|---|---|---|
| Elasticsearch | 9.5.3 | تُخزّن مستندات JSON وتسترجعها عبر النص والمرشّحات والتجميعات | Query DSL (JSON) و ES|QL |
| Kibana | 9.5.3 | واجهة ويب لـ Elasticsearch : أدوات المطوّرين و Discover و Lens ولوحات المراقبة | النقرات و KQL وأدوات المطوّرين للـ JSON |
| OpenSearch (+ Dashboards) | 3.8.0 | نسخة مفتوحة المصدر من Elasticsearch و Kibana نفس الـ API بنسبة 95% | نفس Query DSL بالإضافة إلى SQL و PPL |
| Neo4j Community | 5.26 | قاعدة رسم بيانيّ : عقد وعلاقات وخصائص | Cypher |
يشارك Elasticsearch و OpenSearch نفس المحرّك الداخليّ و Apache Lucene والمبدأ نفسه : الفهرس المعكوس. بدلًا من قراءة كل مستند في كل بحث يُنشئ المحرّك قاموسًا مرّة واحدة « كلمة → قائمة المستندات التي تحتويها ». البحث عن « docker kubernetes » ينتهي به لعبور قائمتي معرّفات وهو يأخذ بضعة ملايين من الثواني على ملايين المستندات. يراهن Neo4j على الضدّ : يُخزّن العلاقات كمؤشّرات فعليّة بين العقد لذا « أصدقاء أصدقائي » تُحسب بمتابعة الأسهم بدون ربط.
كل محرّك يختلع كلماته الخاصّة لكنّها غالبًا تعني الفكرة نفسها من قاعدة بيانات العلاقة. يترجم هذا الجدول الشروط الأساسيّة بين SQL الكلاسيكيّ ومحرّكات البحث والرسم البيانيّ.
| SQL كلاسيكيّ | Elasticsearch / OpenSearch | Neo4j (رسم بيانيّ) | بوضوح |
|---|---|---|---|
| قاعدة بيانات | cluster (مجموعة من الفهارس) | قاعدة الرسم البيانيّ | كل المحتوى المُدار من قِبل الخادم |
| جدول | index (فهرس) | علامة العقدة (label) | مجموعة من العناصر من نفس النوع |
| صفّ / سجلّ | document (JSON) | node (عقدة) | عنصر واحد |
| عمود | field (حقل) | property (خاصيّة) | سمة من العنصر |
| schema / DDL | mapping (ربط) | schema مرن (اختيارىّ) | تعريف أنواع الحقول |
| المفتاح الأساسيّ | _id من المستند | هويّة العقدة | المعرّف الفريد |
| المفتاح الأجنبيّ + ربط | لا يوجد ربط : cours_id منزّع التطبيع | relation (-[:PREREQUIS_DE]->) | الرابط بين عنصرين |
| index (B-tree) للتسريع | فهرس معكوس | index على خاصيّة | البنية التي تسرّع البحث |
SELECT … WHERE | Query DSL (JSON) و ES|QL | MATCH … WHERE … RETURN | الاستعلام عن البيانات |
GROUP BY / aggregate | aggregations (aggs) | count() و collect() | التجميع والعدّ |
| SQL (لغة) | Query DSL / ES|QL / KQL | Cypher | لغة الاستعلام |
انتبه لكلمة « index ». في SQL index هي بنية تسريع (B-tree) موضوعة على جدول. في Elasticsearch index هي معادل الجدول نفسه. و الفهرس المعكوس شيء آخر تمامًا : آليّة داخليّة « كلمة → مستندات » تجعل البحث فوريًّا. ثلاثة معانٍ لكلمة واحدة.
خذ ثلاث فكرات من مدرستنا : دورات و طلاب و مراجعات تركها الطلاب على الدورات.
1. في SQL (الجداول والروابط) — ثلاثة جداول معياريّة والمعلومات لا تُكرّر أبدًا تمرّ الروابط من خلال المفاتيح الأجنبيّة :
SELECT c.titre, AVG(a.note)
FROM cours c
JOIN avis a ON a.cours_id = c.id
JOIN etudiant e ON e.id = a.etudiant_id
WHERE e.ville = 'Montréal'
GROUP BY c.titre;مثاليّ للاتّساق (تُغيّر ملاحظة واحدة في كل مكان) أقلّ جودة ل « جميع الدورات التي الوصف يحتوي على نشر » : LIKE '%déploy%' يقرأ الجدول كاملًا.
2. في المستندات (Elasticsearch / OpenSearch) — الدورة مستند JSON واحد يحمل ما تحتاجه البحث بما فيه اسم المعلّم والدرجة المتوسّطة المحسوبة بالفعل. هنا تمامًا الوثيقة الأولى للفهرس cours من المختبر :
{
"id": "C0001",
"titre": "Docker expliqué simplement",
"description": "Dans ce cours accessible sans prérequis, vous apprenez à automatiser vos applications avec Docker. …",
"categorie": "DevOps", "sujet": "Docker", "niveau": "debutant", "langue": "en",
"prix": 129, "gratuit": false, "duree_heures": 5,
"tags": ["docker", "linux", "helm", "devops"],
"date_publication": "2024-08-14",
"note_moyenne": 4.4, "nb_avis": 327,
"professeur": { "id": "P001", "nom": "Karim Caron", "ville": "Gatineau" },
"competences": ["Conteneurisation", "Intégration continue"]
}اسم المعلّم منزّع التطبيع (مُنسخ في كل دورة). إذا تغيّر اسمه يجب أن تُعيد فهرسة دوراته : هذا ثمن البحث الفوريّ. تعيش المراجعات في فهرس ثانٍ avis مع cours_id كحقل بسيط بلا ربط ممكن في وقت الاستعلام.
3. في الرسم البيانيّ (Neo4j) — نفس الأفكار تصبح عقد والروابط تصبح علاقات من الدرجة الأولى التي تحمل خصائصها الخاصّة. هنا ثلاث علاقات حقيقيّة من رسم المختبر البيانيّ حول الدورة C0001 :
(:Etudiant {prenom: "Hugo"})-[:INSCRIT_A {progression: 100, note: 4}]->(:Cours {id: "C0001", titre: "Docker expliqué simplement"})
(:Cours {id: "C0001"})-[:PREREQUIS_DE]->(:Cours {id: "C0003", titre: "Docker : le guide complet"})
(:Professeur {prenom: "Karim", nom: "Caron"})-[:ENSEIGNE]->(:Cours {id: "C0001"})السؤال « أيّ الدورات الطلاب الذين أحبّوا نفس الدورة التي أحببتها بعدها؟ » يُكتب في سطر واحد من Cypher وتُحسب بمتابعة ثلاث علاقات حيث كان SQL ستربط ثلاث مرّات وحيث Elasticsearch لن تستطيع الإجابة ببساطة.
| السؤال | أفضل أداة | لماذا |
|---|---|---|
| « دورات حول نشر الحاويات متسامحة مع الأخطاء » | Elasticsearch / OpenSearch | فهرس معكوس و محلّل عربيّ و fuzzy |
| « توزيع أخطاء 500 حسب الدولة على مدى 30 يومًا » | Elasticsearch + Kibana | تجميعات وتصوّر وقت فعليّ |
| « مسار المتطلّبات للوصول إلى الدورة C0230 » | Neo4j | جولة العلاقات والمسار الأقصر |
| « التوصية بدورة بناءً على التسجيلات المتشابهة » | Neo4j | التصفية التعاونيّة = نمط الرسم البيانيّ |
| « الدفع والفاتورة والاتّساق الصارم » | SQL (خارج المختبر) | معاملات ACID |
في الحياة الحقيقيّة السجلّات تصل بشكل مستمرّ (Filebeat أو Logstash أو التطبيق نفسه) وقاعدة الرسم البيانيّ تُغذّى من نظام الأعمال. في المختبر أمران يحلان محلّ كل ذلك : importer يُرسل ملفات NDJSON إلى API _bulk من Elasticsearch و charger-graphe ينفّذ نص Cypher يقرأ CSV. لا يتواصل العالمان بينهما : أنت أو تطبيقك من اختار من يسأل كل سؤال.
لا شيء تكتبه في هذا الدرس : يبدأ المختبر في الدرس 03. تمّ جمع المقتطفات أدناه على مختبر الدورة حتّى تعرف ما ستجده بداخله.
مجموعة البيانات : منصة دورات عبر الإنترنت. كون واحد يُغذّي المحرّكات الثلاثة لمقارنة ما يفعله كلّ واحد بشكل أفضل.
| اللعبة | الحجم الدقيق | المحتوى |
|---|---|---|
فهرس cours | 504 مستندات | العنوان و الوصف (محلّل عربيّ) والفئة والموضوع والمستوى والسعر والعلامات والدرجة المتوسّطة والمعلّم |
فهرس avis | 609 مستندات | درجة من 1 إلى 5 والنص والاسم الأول والمدينة والدولة والتاريخ وأصوات « مفيد» |
فهرس acces | 12000 سطرًا | سجلّات الويب من 2026-08-10 إلى 2026-09-08 : المسار وحالة HTTP والـ IP والدولة والجهاز والمرجع |
| رسم Neo4j البيانيّ | 872 عقدة · 3712 علاقة | الدورات 504 والطلاب 300 والمعلّمون 30 والمهارات 22 والمدن 16 |
ما يجب أن تراه : 504 دورات في الرسم البيانيّ هي نفسها في فهرس cours (نفس المعرّفات C0001…C0504). ستتمكّن من البحث عن دورة في Elasticsearch ثم استكشاف متطلّباتها في Neo4j.
الفئات متوازنة تمامًا. تجميع terms على categorie الرجوع إلى :
Cloud 84 · DevOps 84 · Données 84 · Développement web 84 · IA 84 · Sécurité 84وعلى الحقول الأخرى : niveau → مبتدئ 252 ومتقدّم 158 ومتوسّط 94 ; langue → فرنسيّ 375 وإنجليزيّ 129 ; gratuit → 75 دورة مجانيّة ; 72 موضوعًا مختلفًا (Docker و Kubernetes و Elasticsearch و Neo4j و React و AWS…) ; 30 معلّمًا. ما يجب أن تراه : أرقام دائريّة وأرقام معروفة مسبقًا عمليّة للتحقّق من استعلاماتك من الوحدات 2 و 3.
تقييم واحد كما تُخزّن. أول وثيقة في فهرس avis :
{ "id": "A00001", "cours_id": "C0028", "etudiant": "Nathan", "ville": "Sherbrooke", "pays": "Canada",
"note": 3, "texte": "Les vidéos sont bonnes, la partie théorique est dense.", "date": "2024-06-21", "utile": 33 }ما يجب أن تراه : cours_id سلسلة بسيطة. لا ربط يربط هذا التقييم بدورته في Elasticsearch ; تطبيقك هو من سيعمل الرابط.
سطر واحد من السجلّ. الأحدث في فهرس acces :
{ "id": "L012000", "@timestamp": "2026-09-08T23:39:29.000Z", "methode": "GET", "chemin": "/cours/C0430",
"cours_id": "C0430", "categorie": "Cloud", "statut": 200, "octets": 168403, "duree_ms": 351,
"ip": "169.199.97.7", "pays": "CA", "appareil": "desktop", "navigateur": "Chrome", "referent": "direct" }على 12000 سطرًا : 10829 في 200 و 403 في 404 و 355 في 301 و 235 في 304 و 122 في 500 و 56 في 503. ما يجب أن تراه : حقل @timestamp ضروريّ لـ Kibana Discover للمحور الزمنيّ (الوحدة 4).
الرسم البيانيّ المعدود حسب العلامة ونوع العلاقة. النتيجة الفعليّة لاستعلامي Cypher :
الدورات 504 · الطلاب 300 · المعلّمون 30 · المهارات 22 · المدن 16
INSCRIT_A 1654 · COUVRE 994 · ENSEIGNE 504 · HABITE 330 · PREREQUIS_DE 230ما يجب أن تراه : 1654 تسجيل لـ 300 طالب أي حوالي 5.5 دورات لكل طالب. هذا التشابك هو ما سيجعل التوصيات من الوحدة 7 مثيرة للاهتمام.
« أنا أعرف SQL لماذا لا أفعل كل شيء مع PostgreSQL؟ » → يمكنك حتّى نقطة معيّنة. تعرف PostgreSQL البحث النصيّ الكامل والاستعلامات التكراريّة. لكن بمجرّد أن تريد التسامح مع الأخطاء والتصنيف حسب الصلة والتجميعات على ملايين الأسطر في الوقت الفعليّ أو جولات الرسم البيانيّ بعمق متغيّر كلّ محرّك متخصّص يقوم بالعمل في بضع ملايين من الثواني حيث يطلب SQL فهارس غريبة واستعلامات غير مقروءة. الانعكاس الصحيح : SQL للمصدر المعاملة الحقيقيّ و Elasticsearch جانبًا للبحث و Neo4j جانبًا للربط.
« Elasticsearch أو OpenSearch يجب أن أختار الآن؟ » → لا. تأخذك الدورة للعمل على Elasticsearch ; الوحدة 5 تعيد نفس الاستعلامات على OpenSearch وتُدرج الفروقات (حفنة). ما تتعلّمه ينطبق على الاثنين.
« Kibana قاعدة بيانات؟ » → لا وهذا التباس متكرّر. تُخزّن Kibana فقط إعدادك (لوحات المراقبة والآراء) في فهرس مختبئ من Elasticsearch. تأتي كلّ البيانات التي ترها من Elasticsearch ; إذا تمّ إيقاف Elasticsearch تعرض Kibana « Kibana server is not ready yet » (الدرس 04).
كلمة « index » تعني شيئين مختلفين : في SQL بنية تسريع (B-tree) مرفقة بجدول ; في Elasticsearch معادل الجدول نفسه مقسّم إلى shards (فهارس Lucene مستقلّة). تُكرّر الوحدة 2 الدرس 01 هذا المصطلح عمليًّا على المختبر.