Το Elasticsearch είναι μια μηχανή αναζήτησης με json rest api, που χρησιμοποιεί Lucene και γράφεται σε Java. Μια περιγραφή όλων των πλεονεκτημάτων αυτού του κινητήρα είναι διαθέσιμη στη διεύθυνση επίσημη ιστοσελίδα. Στη συνέχεια θα αναφερθούμε στο Elasticsearch ως ES.
Παρόμοιες μηχανές χρησιμοποιούνται για σύνθετες αναζητήσεις σε μια βάση δεδομένων εγγράφων. Για παράδειγμα, αναζήτηση λαμβάνοντας υπόψη τη μορφολογία της γλώσσας ή αναζήτηση με γεωγραφικές συντεταγμένες.
Σε αυτό το άρθρο θα μιλήσω για τα βασικά του ES χρησιμοποιώντας το παράδειγμα της ευρετηρίασης αναρτήσεων ιστολογίου. Θα σας δείξω πώς να φιλτράρετε, να ταξινομείτε και να αναζητάτε έγγραφα.
Για να μην εξαρτώμαι από το λειτουργικό σύστημα, θα κάνω όλα τα αιτήματα στην ES χρησιμοποιώντας το CURL. Υπάρχει επίσης ένα πρόσθετο για το google chrome που ονομάζεται αίσθηση.
Σε όλο το κείμενο υπάρχουν σύνδεσμοι προς τεκμηρίωση και άλλες πηγές. Στο τέλος υπάρχουν σύνδεσμοι για γρήγορη πρόσβαση στην τεκμηρίωση. Ορισμοί άγνωστων όρων μπορούν να βρεθούν στο γλωσσάρια.
Εγκατάσταση ES
Για να γίνει αυτό, χρειαζόμαστε πρώτα Java. προγραμματιστές συνιστώ εγκαταστήστε εκδόσεις Java νεότερες από την ενημερωμένη έκδοση 8 της Java 20 ή την ενημερωμένη έκδοση 7 της Java 55.
# Добавим документ c id 1 типа post в индекс blog.
# ?pretty указывает, что вывод должен быть человеко-читаемым.
curl -XPUT "$ES_URL/blog/post/1?pretty" -d'
{
"title": "Веселые котята",
"content": "<p>Смешная история про котят<p>",
"tags": [
"котята",
"смешная история"
],
"published_at": "2014-09-12T20:44:42+00:00"
}'
Το ES δημιουργήθηκε αυτόματα δείκτη blog και τύπου Θέση. Μπορούμε να σχεδιάσουμε μια αναλογία υπό όρους: ένα ευρετήριο είναι μια βάση δεδομένων και ένας τύπος είναι ένας πίνακας σε αυτήν τη βάση δεδομένων. Κάθε τύπος έχει το δικό του σχήμα − χαρτης, ακριβώς όπως ένας σχεσιακός πίνακας. Η αντιστοίχιση δημιουργείται αυτόματα όταν το έγγραφο έχει ευρετηριαστεί:
# Получим mapping всех типов индекса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"
Στην απόκριση διακομιστή, πρόσθεσα τις τιμές των πεδίων του εγγράφου με ευρετήριο στα σχόλια:
Αξίζει να σημειωθεί ότι το ES δεν κάνει διαφοροποίηση μεταξύ μιας μεμονωμένης τιμής και ενός πίνακα τιμών. Για παράδειγμα, το πεδίο τίτλου περιέχει απλώς έναν τίτλο και το πεδίο ετικετών περιέχει μια σειρά από συμβολοσειρές, αν και αναπαρίστανται με τον ίδιο τρόπο στην αντιστοίχιση.
Θα μιλήσουμε περισσότερα για τη χαρτογράφηση αργότερα.
αιτήσεις
Ανάκτηση ενός εγγράφου με το αναγνωριστικό του:
# извлечем документ с id 1 типа post из индекса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
Νέα κλειδιά εμφανίστηκαν στην απάντηση: _version и _source. Σε γενικές γραμμές, όλα τα κλειδιά ξεκινούν από _ χαρακτηρίζονται ως επίσημοι.
Κλειδί _version δείχνει την έκδοση του εγγράφου. Χρειάζεται για να λειτουργήσει ο αισιόδοξος μηχανισμός κλειδώματος. Για παράδειγμα, θέλουμε να αλλάξουμε ένα έγγραφο που έχει την έκδοση 1. Υποβάλλουμε το τροποποιημένο έγγραφο και υποδεικνύουμε ότι πρόκειται για επεξεργασία ενός εγγράφου με την έκδοση 1. Εάν κάποιος άλλος επεξεργάστηκε επίσης ένα έγγραφο με την έκδοση 1 και υπέβαλε αλλαγές ενώπιόν μας, τότε Η ES δεν θα δεχτεί τις αλλαγές μας, γιατί αποθηκεύει το έγγραφο με την έκδοση 2.
Κλειδί _source περιέχει το έγγραφο που ευρετηριάσαμε. Η ES δεν χρησιμοποιεί αυτήν την τιμή για λειτουργίες αναζήτησης επειδή Τα ευρετήρια χρησιμοποιούνται για αναζήτηση. Για εξοικονόμηση χώρου, το ES αποθηκεύει ένα έγγραφο συμπιεσμένης πηγής. Εάν χρειαζόμαστε μόνο το αναγνωριστικό και όχι ολόκληρο το έγγραφο προέλευσης, τότε μπορούμε να απενεργοποιήσουμε την αποθήκευση προέλευσης.
Εάν δεν χρειαζόμαστε πρόσθετες πληροφορίες, μπορούμε να λάβουμε μόνο τα περιεχόμενα του _source:
curl -XPUT "$ES_URL/blog/post/3" -d'
{
"title": "Как у меня появился котенок",
"content": "<p>Душераздирающая история про бедного котенка с улицы<p>",
"tags": [
"котята"
],
"published_at": "2014-07-21T20:44:42+00:00"
}'
Ταξινόμηση
# найдем последний пост по дате публикации и извлечем поля title и published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"size": 1,
"_source": ["title", "published_at"],
"sort": [{"published_at": "desc"}]
}'
Επιλέξαμε την τελευταία ανάρτηση. size περιορίζει τον αριθμό των εγγράφων που πρέπει να εκδοθούν. total δείχνει τον συνολικό αριθμό των εγγράφων που αντιστοιχούν στο αίτημα. sort στην έξοδο περιέχει έναν πίνακα ακεραίων με τους οποίους εκτελείται η ταξινόμηση. Εκείνοι. η ημερομηνία μετατράπηκε σε ακέραιο. Περισσότερες πληροφορίες σχετικά με την ταξινόμηση μπορείτε να βρείτε στο τεκμηρίωση.
Φίλτρα και ερωτήματα
Το ES αφού η έκδοση 2 δεν κάνει διάκριση μεταξύ φίλτρων και ερωτημάτων εισάγεται η έννοια των πλαισίων.
Ένα περιβάλλον ερωτήματος διαφέρει από ένα περιβάλλον φίλτρου στο ότι το ερώτημα δημιουργεί ένα _score και δεν αποθηκεύεται στην κρυφή μνήμη. Θα σας δείξω τι είναι το _score αργότερα.
Φιλτράρισμα κατά ημερομηνία
Χρησιμοποιούμε το αίτημα σειρά στο πλαίσιο του φίλτρου:
# получим посты, опубликованные 1ого сентября или позже
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"filter": {
"range": {
"published_at": { "gte": "2014-09-01" }
}
}
}'
Φιλτράρισμα κατά ετικέτες
Χρησιμοποιούμε ερώτημα όρου για να αναζητήσετε αναγνωριστικά εγγράφων που περιέχουν μια δεδομένη λέξη:
# найдем все документы, в поле tags которых есть элемент 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
"_source": [
"title",
"tags"
],
"filter": {
"term": {
"tags": "котята"
}
}
}'
Ωστόσο, αν ψάξουμε για «ιστορίες» στο πεδίο περιεχομένου, δεν θα βρούμε τίποτα, γιατί Το ευρετήριο περιέχει μόνο τις αρχικές λέξεις, όχι τους μίσχους τους. Για να κάνετε αναζήτηση υψηλής ποιότητας, πρέπει να διαμορφώσετε τον αναλυτή.
Πεδίο _score παραστάσεις συνάφεια. Εάν το αίτημα εκτελείται σε περιβάλλον φίλτρου, τότε η τιμή _score θα είναι πάντα ίση με 1, που σημαίνει πλήρη αντιστοίχιση με το φίλτρο.
Αναλυτές
Αναλυτές απαιτούνται για τη μετατροπή του αρχικού κειμένου σε ένα σύνολο διακριτικών.
Οι αναλυτές αποτελούνται από έναν Tokenizer και πολλά προαιρετικά TokenFilters. Το Tokenizer μπορεί να προηγηθεί από πολλά CharFilters. Τα Tokenizers σπάζουν τη συμβολοσειρά πηγής σε διακριτικά, όπως κενά και χαρακτήρες στίξης. Το TokenFilter μπορεί να αλλάξει διακριτικά, να διαγράψει ή να προσθέσει νέα, για παράδειγμα, να αφήσει μόνο το στέλεχος της λέξης, να αφαιρέσει προθέσεις, να προσθέσει συνώνυμα. CharFilter - αλλάζει ολόκληρη τη συμβολοσειρά πηγής, για παράδειγμα, κόβει τις ετικέτες html.
Ας εκμεταλλευτούμε api και ας δούμε πώς οι τυπικοί και οι Ρώσοι αναλυτές μεταμορφώνουν τη σειρά "Funny stories about kittens":
# используем анализатор standard
# обязательно нужно перекодировать не ASCII символы
curl -XGET "$ES_URL/_analyze?pretty&analyzer=standard&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
Ο τυπικός αναλυτής χώρισε τη συμβολοσειρά κατά κενά και μετέτρεψε τα πάντα σε πεζά, ο ρωσικός αναλυτής αφαίρεσε ασήμαντες λέξεις, τη μετέτρεψε σε πεζά και άφησε το στέλεχος των λέξεων.
Ας δούμε ποια Tokenizer, TokenFilters, CharFilters χρησιμοποιεί ο ρωσικός αναλυτής:
Ας περιγράψουμε τον αναλυτή μας με βάση τα ρωσικά, ο οποίος θα κόψει ετικέτες html. Ας το ονομάσουμε προεπιλογή, γιατί ένας αναλυτής με αυτό το όνομα θα χρησιμοποιηθεί από προεπιλογή.
Αρχικά, όλες οι ετικέτες HTML θα αφαιρεθούν από τη συμβολοσειρά πηγής, στη συνέχεια το πρότυπο του tokenizer θα το χωρίσει σε διακριτικά, τα διακριτικά που προκύπτουν θα μετακινηθούν σε πεζά γράμματα, οι ασήμαντες λέξεις θα αφαιρεθούν και τα υπόλοιπα διακριτικά θα παραμείνουν το στέλεχος της λέξης.
Δημιουργία ευρετηρίου
Παραπάνω περιγράψαμε τον προεπιλεγμένο αναλυτή. Θα ισχύει για όλα τα πεδία συμβολοσειράς. Η ανάρτησή μας περιέχει μια σειρά από ετικέτες, επομένως οι ετικέτες θα υποβληθούν επίσης σε επεξεργασία από τον αναλυτή. Επειδή Αναζητούμε αναρτήσεις κατά ακριβή αντιστοίχιση με μια ετικέτα, τότε πρέπει να απενεργοποιήσουμε την ανάλυση για το πεδίο ετικετών.
Ας δημιουργήσουμε ένα ιστολόγιο ευρετηρίου2 με αναλυτή και αντιστοίχιση, στο οποίο η ανάλυση του πεδίου ετικετών είναι απενεργοποιημένη:
Ας προσθέσουμε τις ίδιες 3 αναρτήσεις σε αυτό το ευρετήριο (blog2). Θα παραλείψω αυτή τη διαδικασία γιατί... είναι παρόμοιο με την προσθήκη εγγράφων στο ευρετήριο του ιστολογίου.
Αναζήτηση πλήρους κειμένου με υποστήριξη έκφρασης
Ας ρίξουμε μια ματιά σε έναν άλλο τύπο αιτήματος:
# найдем документы, в которых встречается слово 'истории'
# query -> simple_query_string -> query содержит поисковый запрос
# поле title имеет приоритет 3
# поле tags имеет приоритет 2
# поле content имеет приоритет 1
# приоритет используется при ранжировании результатов
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "истории",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
Επειδή Χρησιμοποιούμε έναν αναλυτή με ρωσική προέλευση, τότε αυτό το αίτημα θα επιστρέψει όλα τα έγγραφα, αν και περιέχουν μόνο τη λέξη "ιστορικό".
Το αίτημα μπορεί να περιέχει ειδικούς χαρακτήρες, για παράδειγμα:
""fried eggs" +(eggplant | potato) -frittata"
Αίτημα σύνταξης:
+ signifies AND operation
| signifies OR operation
- negates a single token
" wraps a number of tokens to signify a phrase for searching
* at the end of a term signifies a prefix query
( and ) signify precedence
~N after a word signifies edit distance (fuzziness)
~N after a phrase signifies slop amount
# найдем документы без слова 'щенки'
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
"query": {
"simple_query_string": {
"query": "-щенки",
"fields": [
"title^3",
"tags^2",
"content"
]
}
}
}'
# получим 2 поста про котиков
Αν ενδιαφέρεστε για παρόμοια άρθρα-μαθήματα, έχετε ιδέες για νέα άρθρα ή έχετε προτάσεις για συνεργασία, τότε θα χαρώ να λάβω ένα μήνυμα με προσωπικό μήνυμα ή με email [προστασία μέσω email].