Όταν πληκτρολογείς τρεις λέξεις στο Google και η απάντηση έρχεται σε κλάσμα δευτερολέπτου, με διορθωμένα τα ορθογραφικά σου λάθη, δεν είναι μια βάση SQL που διατρέχει δισεκατομμύρια σελίδες: είναι ένα ανεστραμμένο ευρετήριο (inverted index), ένα λεξικό «λέξη → σελίδες που την περιέχουν». Τα 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 (Panama Papers) | Neo4j | 11,5 εκατομμύρια έγγραφα και οι σύνδεσμοι μεταξύ εικονικών εταιρειών, στελεχών και τραπεζών, διερευνώμενοι σε γράφο από 370 δημοσιογράφους |
| eBay, Walmart | Neo4j | συστάσεις σε πραγματικό χρόνο: «όσοι αγόρασαν αυτό…», υπολογιζόμενες ακολουθώντας σχέσεις αγοράς |
Αυτό που έχουν κοινό αυτές οι εταιρείες: έχουν επίσης βάσεις SQL, για τις πληρωμές, τις παραγγελίες, τα τιμολόγια. Προσθέτουν έναν κινητήρα αναζήτησης δίπλα για να αναζητούν, και μια βάση γράφων δίπλα για να συνδέουν. Ακριβώς αυτό θα στήσεις σε αυτό το εργαστήριο, σε μικρή κλίμακα.
Φαντάσου ένα μεγάλο διαδικτυακό σχολείο. Στην υποδοχή, μια βιβλιοθηκονόμος βρίσκει σε ένα δευτερόλεπτο όλα τα μαθήματα που μιλούν για «ανάπτυξη κοντέινερ», ακόμη κι αν έγραψες «αναπτυξη» χωρίς τόνο: αυτό είναι το Elasticsearch. Στον τοίχο, οθόνες δείχνουν την κίνηση του ιστότοπου σε πραγματικό χρόνο, τις σελίδες με σφάλμα, τις χώρες προέλευσης των επισκεπτών: αυτό είναι το Kibana, που δεν αποθηκεύει τίποτα αλλά σχεδιάζει ό,τι περιέχει το Elasticsearch. Στο γραφείο προσανατολισμού, μια σύμβουλος γνωρίζει τις σχέσεις μεταξύ των ανθρώπων: ποιος παρακολούθησε τι, ποιο μάθημα είναι προαπαιτούμενο ποιου άλλου, ποιοι μαθητές μοιάζουν μεταξύ τους: αυτό είναι το Neo4j. Και το OpenSearch; Είναι η δίδυμη βιβλιοθηκονόμος, εκπαιδευμένη στο ίδιο σχολείο με το Elasticsearch, προσληφθείσα από όσους θέλουν ένα 100% ανοιχτού κώδικα συμβόλαιο. Τέσσερα εργαλεία, δύο τρόποι ταξινόμησης της πληροφορίας: με λέξεις (μηχανή αναζήτησης) ή με συνδέσμους (γράφος).
| Εργαλείο | Έκδοση εργαστηρίου | Ρόλος | Του μιλάς με |
|---|---|---|---|
| Elasticsearch | 9.5.3 | αποθηκεύει έγγραφα JSON και τα ανακτά μέσω κειμένου, φίλτρων, συγκεντρώσεων | Query DSL (JSON), ES|QL |
| Kibana | 9.5.3 | διεπαφή ιστού του Elasticsearch: Dev Tools, Discover, Lens, ταμπλό | κλικ, KQL, και Dev Tools για JSON |
| OpenSearch (+ Dashboards) | 3.8.0 | fork ανοιχτού κώδικα του Elasticsearch και του Kibana, ίδιο API σε ποσοστό 95% | το ίδιο Query DSL, καθώς και SQL και PPL |
| Neo4j Community | 5.26 | βάση γράφων: κόμβοι, σχέσεις, ιδιότητες | Cypher |
Τα Elasticsearch και OpenSearch μοιράζονται τον ίδιο εσωτερικό κινητήρα, το Apache Lucene, και την ίδια αρχή: το ανεστραμμένο ευρετήριο (inverted index). Αντί να διαβάζει κάθε έγγραφο σε κάθε αναζήτηση, ο κινητήρας κατασκευάζει μία φορά για πάντα ένα λεξικό «λέξη → λίστα εγγράφων που την περιέχουν». Η αναζήτηση «docker kubernetes» ανάγεται τότε στη διασταύρωση δύο λιστών αναγνωριστικών, κάτι που παίρνει λίγα χιλιοστά του δευτερολέπτου σε εκατομμύρια έγγραφα. Το Neo4j κάνει το αντίθετο στοίχημα: αποθηκεύει τις σχέσεις ως φυσικούς δείκτες μεταξύ κόμβων, ώστε «οι φίλοι των φίλων μου» να υπολογίζονται ακολουθώντας βέλη, χωρίς join.
Κάθε κινητήρας εφευρίσκει τις δικές του λέξεις, αλλά συχνά αναφέρονται στην ίδια ιδέα όπως σε μια σχεσιακή βάση. Ο παρακάτω πίνακας μεταφράζει τους βασικούς όρους μεταξύ της κλασικής SQL, των μηχανών αναζήτησης και του γράφου.
| Κλασική SQL | Elasticsearch / OpenSearch | Neo4j (γράφος) | Με απλά λόγια |
|---|---|---|---|
| βάση δεδομένων | cluster (σύνολο index) | βάση γράφου | όλο το περιεχόμενο που διαχειρίζεται ο διακομιστής |
| πίνακας | index | ετικέτα κόμβου (label) | μια συλλογή στοιχείων του ίδιου τύπου |
| γραμμή / εγγραφή | έγγραφο (JSON) | κόμβος | ένα στοιχείο |
| στήλη | πεδίο (field) | ιδιότητα | ένα χαρακτηριστικό του στοιχείου |
| σχήμα / DDL | mapping | ελαστικό σχήμα (προαιρετικό) | ο ορισμός των τύπων πεδίων |
| πρωτεύον κλειδί | _id του εγγράφου | ταυτότητα του κόμβου | το μοναδικό αναγνωριστικό |
| ξένο κλειδί + join | χωρίς join: cours_id αποκανονικοποιημένο | σχέση (-[:PREREQUIS_DE]->) | ο σύνδεσμος μεταξύ δύο στοιχείων |
| index (B-tree) επιτάχυνσης | ανεστραμμένο ευρετήριο | index σε μια ιδιότητα | η δομή που επιταχύνει την αναζήτηση |
SELECT … WHERE | Query DSL (JSON), ES|QL | MATCH … WHERE … RETURN | ερώτημα στα δεδομένα |
GROUP BY / συνάθροιση | συγκεντρώσεις (aggs) | count(), collect() | ομαδοποίηση και μέτρηση |
| SQL (γλώσσα) | Query DSL / ES|QL / KQL | Cypher | η γλώσσα ερωτημάτων |
Πρόσεξε τη λέξη «index». Στην SQL, ένα index είναι μια δομή επιτάχυνσης (B-tree) τοποθετημένη πάνω σε έναν πίνακα. Στο Elasticsearch, ένα index είναι το ισοδύναμο του ίδιου του πίνακα. Και το ανεστραμμένο ευρετήριο είναι κάτι ακόμη διαφορετικό: ο εσωτερικός μηχανισμός «λέξη → έγγραφα» που κάνει την αναζήτηση ακαριαία. Τρεις έννοιες για μία μόνο λέξη.
Ας πάρουμε τρεις έννοιες από το σχολείο μας: μαθήματα, μαθητές, κριτικές που αφήνουν οι μαθητές στα μαθήματα.
1. Σε SQL (πίνακες και joins) — τρεις κανονικοποιημένοι πίνακες, η πληροφορία δεν διπλασιάζεται ποτέ, οι σύνδεσμοι περνούν μέσα από ξένα κλειδιά:
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 που ενσωματώνει ό,τι χρειάζεται η αναζήτηση, συμπεριλαμβανομένου του ονόματος του καθηγητή και της ήδη υπολογισμένης μέσης βαθμολογίας. Δες, ακριβώς όπως είναι, το πρώτο έγγραφο του index 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"]
}Το όνομα του καθηγητή είναι αποκανονικοποιημένο (αντιγραμμένο σε κάθε μάθημα). Αν αλλάξει όνομα, θα χρειαστεί να επανευρετηριαστούν τα μαθήματά του: αυτό είναι το τίμημα της ακαριαίας αναζήτησης. Οι κριτικές ζουν σε ένα δεύτερο index, το avis, με το cours_id ως απλό πεδίο, χωρίς δυνατότητα join τη στιγμή του ερωτήματος.
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 θα αλυσόδενε τρία joins και όπου το 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. Τα παρακάτω αποσπάσματα καταγράφηκαν από το εργαστήριο του μαθήματος, ώστε να ξέρεις τι θα βρεις μέσα.
Το σύνολο δεδομένων: μια πλατφόρμα διαδικτυακών μαθημάτων. Ένας μόνο κόσμος τροφοδοτεί τους τρεις κινητήρες, για να συγκρίνεις τι κάνει καλύτερα ο καθένας.
| Σύνολο | Ακριβής όγκος | Περιεχόμενο |
|---|---|---|
index cours | 504 έγγραφα | τίτλος, περιγραφή (γαλλικός αναλυτής), κατηγορία, θέμα, επίπεδο, τιμή, ετικέτες, μέση βαθμολογία, καθηγητής |
index avis | 609 έγγραφα | βαθμολογία από 1 έως 5, κείμενο, όνομα, πόλη, χώρα, ημερομηνία, ψήφοι «χρήσιμο» |
index acces | 12.000 γραμμές | αρχεία καταγραφής ιστού από 2026-08-10 έως 2026-09-08: διαδρομή, κατάσταση HTTP, IP, χώρα, συσκευή, παραπομπή |
| γράφος Neo4j | 872 κόμβοι · 3.712 σχέσεις | Cours 504, Etudiant 300, Professeur 30, Competence 22, Ville 16 |
Αυτό που πρέπει να δεις: τα 504 μαθήματα του γράφου είναι τα ίδια με εκείνα του index cours (ίδια αναγνωριστικά C0001…C0504). Θα μπορέσεις να αναζητήσεις ένα μάθημα στο Elasticsearch και μετά να εξερευνήσεις τα προαπαιτούμενά του στο Neo4j.
Οι κατηγορίες είναι τέλεια ισορροπημένες. Μια συγκέντρωση terms στο categorie επιστρέφει:
Cloud 84 · DevOps 84 · Données 84 · Développement web 84 · IA 84 · Sécurité 84Και στα άλλα πεδία: niveau → debutant 252, avance 158, intermediaire 94· langue → fr 375, en 129· gratuit → 75 δωρεάν μαθήματα· 72 διακριτά θέματα (Docker, Kubernetes, Elasticsearch, Neo4j, React, AWS…)· 30 καθηγητές. Αυτό που πρέπει να δεις: στρογγυλοί και γνωστοί εκ των προτέρων αριθμοί, χρήσιμοι για να επαληθεύεις τα ερωτήματά σου στις ενότητες 2 και 3.
Μια κριτική, όπως αποθηκεύεται. Πρώτο έγγραφο του index 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 είναι μια απλή συμβολοσειρά. Κανένα join δεν συνδέει αυτή την κριτική με το μάθημά της στο Elasticsearch· η εφαρμογή σου θα κάνει τη σύνδεση.
Μια γραμμή αρχείου καταγραφής. Η πιο πρόσφατη του index 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" }Στις 12.000 γραμμές: 10.829 σε 200, 403 σε 404, 355 σε 301, 235 σε 304, 122 σε 500, 56 σε 503. Αυτό που πρέπει να δεις: το πεδίο @timestamp, απαραίτητο για το Kibana Discover για τον άξονα του χρόνου (ενότητα 4).
Ο γράφος, μετρημένος ανά ετικέτα και τύπο σχέσης. Πραγματικό αποτέλεσμα δύο ερωτημάτων Cypher:
Cours 504 · Etudiant 300 · Professeur 30 · Competence 22 · Ville 16
INSCRIT_A 1654 · COUVRE 994 · ENSEIGNE 504 · HABITE 330 · PREREQUIS_DE 230Αυτό που πρέπει να δεις: 1.654 εγγραφές για 300 μαθητές, δηλαδή περίπου 5,5 μαθήματα ανά μαθητή. Αυτό το πλέγμα είναι που θα κάνει ενδιαφέρουσες τις συστάσεις της ενότητας 7.
«Ξέρω SQL, γιατί να μην τα κάνω όλα με PostgreSQL;» → Μπορείς, μέχρι ένα σημείο. Η PostgreSQL ξέρει να κάνει αναζήτηση πλήρους κειμένου και αναδρομικά ερωτήματα. Αλλά μόλις θελήσεις ανοχή σε ορθογραφικά λάθη, ταξινόμηση κατά συνάφεια, συγκεντρώσεις σε εκατομμύρια γραμμές σε πραγματικό χρόνο ή διατρέξεις γράφου μεταβλητού βάθους, κάθε εξειδικευμένος κινητήρας κάνει τη δουλειά σε λίγα χιλιοστά του δευτερολέπτου εκεί όπου η SQL απαιτεί εξωτικά index και δυσανάγνωστα ερωτήματα. Η σωστή αντανακλαστική κίνηση: SQL για την πηγή αλήθειας των συναλλαγών, Elasticsearch δίπλα για αναζήτηση, Neo4j δίπλα για σύνδεση.
«Elasticsearch ή OpenSearch, πρέπει να διαλέξω τώρα;» → Όχι. Το μάθημα σε βάζει να δουλέψεις στο Elasticsearch· η ενότητα 5 ξαναπαίζει τα ίδια ερωτήματα στο OpenSearch και απαριθμεί τις διαφορές (μια χούφτα). Ό,τι μαθαίνεις ισχύει και για τα δύο.
«Το Kibana είναι βάση δεδομένων;» → Όχι, και είναι συχνή σύγχυση. Το Kibana αποθηκεύει μόνο τη διαμόρφωσή σου (ταμπλό, προβολές) σε ένα κρυφό index του Elasticsearch. Όλα τα δεδομένα που βλέπεις προέρχονται από το Elasticsearch· αν το Elasticsearch είναι σταματημένο, το Kibana εμφανίζει «Kibana server is not ready yet» (μάθημα 04).
Η λέξη «index» δηλώνει δύο διαφορετικά πράγματα: στην SQL, μια δομή επιτάχυνσης (B-tree) προσαρτημένη σε έναν πίνακα· στο Elasticsearch, το ισοδύναμο του ίδιου του πίνακα, χωρισμένο σε shards (αυτόνομα index Lucene). Η ενότητα 2, μάθημα 01, ξαναπιάνει αυτό το λεξιλόγιο στην πράξη πάνω στο εργαστήριο.