Elasticsearch — це потужний розподілений пошуковий двигун, який дозволяє швидко та точно реалізувати функціонал пошуку для веб-додатків. Цей посібник допомагає розробникам зрозуміти та використовувати Elasticsearch Search APIs для впровадження надійних функцій пошуку.
Він охоплює основи налаштування Elasticsearch і пояснює важливі концепції, такі як базові пошукові запити, фільтрація та агрегації. Розробники дізнаються, як виконувати розширені пошуки, працювати з нечіткими запитами та оптимізувати свої запити для швидкості та релевантності.
Реальні приклади включають використання Elasticsearch для платформ електронної комерції, стрічок соціальних мереж та агрегації логів. Посібник також наголошує на кращих практиках, таких як ефективна пагінація та стратегії індексації, що забезпечують ефективну продуктивність навіть при масштабуванні.
В кінці розробники будуть оснащені інструментами та знаннями для того, щоб освоїти Elasticsearch і створювати швидкі, масштабовані рішення пошуку, які покращують користувацький досвід і продуктивність додатків.
Продукти електронної комерції в пошуку Elasticsearch
Приклад набору даних: Продукти електронної комерції
Цей набір даних буде проіндексовано в Elasticsearch для прикладів:
[
{
"product_id": 1,
"name": "Безпровідні навушники",
"category": "Електроніка",
"price": 59.99,
"rating": 4.5,
"in_stock": true,
"tags": ["аудіо", "bluetooth", "безпровідні"],
"release_date": "2023-01-15"
},
{
"product_id": 2,
"name": "Кросівки для бігу",
"category": "Спорт",
"price": 89.99,
"rating": 4.7,
"in_stock": false,
"tags": ["фітнес", "взуття", "біг"],
"release_date": "2022-11-05"
},
{
"product_id": 3,
"name": "Смартфон",
"category": "Електроніка",
"price": 699.99,
"rating": 4.6,
"in_stock": true,
"tags": ["мобільний", "сенсорний", "android"],
"release_date": "2022-09-20"
}
]
1. Індекс
Індекс — це колекція документів. У цьому прикладі ми створимо індекс з назвою products
.
Запит: Створити індекс
PUT /products
Виведення:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "products"
}
2. Документ
Документ — це об'єкт JSON, який зберігається в індексі.
Запит: Додати документ
Запит:
POST /products/_doc/1
{
"product_id": 1,
"name": "Безпровідні навушники",
"category": "Електроніка",
"price": 59.99,
"rating": 4.5,
"in_stock": true,
"tags": ["аудіо", "bluetooth", "безпровідні"],
"release_date": "2023-01-15"
}
Виведення:
{
"_index": "products",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
}
}
3. Поле
Поле — це пара ключ-значення в документі. Приклад полів: name
, product_id
, price
.
Запит:
GET /products/_search
{
"query": {
"term": {
"name": "Смартфон"
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 3,
"name": "Смартфон",
"price": 79.99
}
}
]
}
}
4. Шарди
Шарди розбивають індекс на менші частини для розподіленого зберігання.
У Elasticsearch шарди використовуються для поділу індексу на менші частини для розподіленого зберігання. Коли створюється індекс, він поділяється на кілька шардів, і кожен шард може зберігатися на різних вузлах в кластері. Це дозволяє Elasticsearch масштабуватися та розподіляти дані по кількох вузлах.
Щоб розбити індекс на менші частини (шарди), ви можете використовувати API для поділу індексу.
Ось приклад запиту, який розбиває існуючий індекс на новий індекс з більшою кількістю шардів.
Запит: Розбити індекс на менші шард
Припустимо, у вас вже є індекс з назвою products
, і ви хочете розбити його на новий індекс з назвою products_split
з 3 шардами.
Крок 1: Створіть новий індекс (ціль для розбиття) Спочатку створіть цільовий індекс з бажаною кількістю шардів. Ви не можете змінювати кількість шардів після створення індексу, тому це важливий крок.
PUT /products_split
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
Виведення:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "products_split"
}
Крок 2: Розбийте оригінальний індекс на новий індекс Далі використовуйте API split
, щоб скопіювати документи з оригінального індексу products
в products_split
, ефективно розподіливши їх на 3 шарди.
POST /products/_split/products_split
Виведення:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "products_split"
}
Це розбиває оригінальний індекс products
на індекс products_split
з 3 шардами.
Запит: Перевірити шард для нового індексу
Щоб перевірити шард, використовуйте наступний запит:
GET /products_split/_settings
Виведення:
{
"products_split": {
"settings": {
"index": {
"number_of_shards": "3",
"number_of_replicas": "1",
"creation_date": "1609459200000",
"analysis": {},
"uuid": "uX6Z2BkzQFmZ31Kv7yxNRg",
"version": {
"created": "7080199"
}
}
}
}
}
Пояснення:
- Крок 1 створює новий індекс
products_split
з 3 шардами. - Крок 2 розбиває оригінальний індекс
products
на новий індексproducts_split
. - Остаточний запит перевіряє, що індекс
products_split
тепер має 3 шарди, підтверджуючи, що операція розбиття була успішною.
Цей приклад демонструє, як розбити індекс на менші шарди для розподіленого зберігання та масштабування.
5. Репліки
Репліки — це копії шардів для забезпечення стійкості до збоїв.
Налаштування реплік для стійкості до збоїв
У Elasticsearch репліки є копіями основних шардів, які допомагають забезпечити стійкість до збоїв і покращують продуктивність запитів. За замовчуванням кожен індекс має одну репліку для кожного основного шару, але ви можете налаштувати кількість реплік при створенні або оновленні індексу.
A. Створення індексу з репліками
Цей запит створює індекс з 3 основними шардами та 2 репліками для кожного шару.
Запит:
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 2
}
}
Виведення:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "products"
}
У цьому випадку індекс products
створюється з 3 основними шарами та 2 репліками для кожного шару, що означає, що буде всього 6 шардів (3 основні + 3 репліки).
B. Оновлення кількості реплік для існуючого індексу
Ви можете змінити кількість реплік для існуючого індексу за допомогою наступного запиту.
Запит:
PUT /products/_settings
{
"number_of_replicas": 1
}
Виведення:
{
"acknowledged": true
}
Це змінює кількість реплік для індексу products
на 1 репліку для кожного основного шару, що призводить до 3 основних шардів і 3 реплік в цілому.
C. Перевірка кількості реплік для індексу
Щоб перевірити поточні налаштування індексу, включаючи кількість реплік, ви можете використовувати цей запит.
Запит:
GET /products/_settings
Виведення:
{
"products": {
"settings": {
"index": {
"number_of_shards": "3",
"number_of_replicas": "1",
"uuid": "Y_X9A9y-SIuTqkjbD-FLQ",
"version": {
"created": "7060199"
}
}
}
}
}
Це показує, що індекс products
має 3 основні шард і 1 репліку для кожного основного шару.
Репліки для стійкості до збоїв
Якщо один із вузлів у кластері вийде з ладу, Elasticsearch все одно зможе обробляти запити та забезпечувати стійкість до збоїв за допомогою реплікованих шардів. Якщо ви вимкнете вузол, дані все одно будуть доступні з реплікованих шардів.
Щоб змоделювати цю стійкість до збоїв:
- Вимкніть вузол у кластері (наприклад, зупиніть Elasticsearch на одному з вузлів).
- Elasticsearch продовжуватиме обробляти запити з реплікованих шардів до того моменту, поки вузол не повернеться в мережу.
Приклад запиту для отримання продуктів:
Запит:
GET /products/_search
{
"query": {
"match_all": {}
}
}
Виведення (з дією стійкості до збоїв):
{
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Смартфон",
"price": 79.99
}
},
{
"_source": {
"product_id": 2,
"name": "Смарт-годинник",
"price": 159.99
}
},
{
"_source": {
"product_id": 3,
"name": "Навушники",
"price": 49.99
}
}
]
}
}
Навіть якщо один з вузлів вийшов з ладу, Elasticsearch використовує репліковані шарди для повернення даних за запитом.
Це ілюструє стійкість до збоїв, яку забезпечують репліки в Elasticsearch.
6. Query DSL
Elasticsearch використовує Query DSL для визначення запитів.
7. Match Query
Знайти продукти з терміном "Навушники" в полі name
.
Запит:
GET /products/_search
{
"query": {
"match": {
"name": "Навушники"
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"category": "Електроніка",
"price": 59.99,
"rating": 4.5,
"in_stock": true,
"tags": ["аудіо", "bluetooth", "безпровідні"],
"release_date": "2023-01-15"
}
}
]
}
}
8. Term Query
Знайти продукти з точною категорією Electronics
.
Запит:
GET /products/_search
{
"query": {
"term": {
"category": {
"value": "Електроніка"
}
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"category": "Електроніка",
"price": 59.99,
"rating": 4.5,
"in_stock": true,
"tags": ["аудіо", "bluetooth", "безпровідні"],
"release_date": "2023-01-15"
}
},
{
"_source": {
"product_id": 3,
"name": "Смартфон",
"category": "Електроніка",
"price": 699.99,
"rating": 4.6,
"in_stock": true,
"tags": ["мобільний", "сенсорний", "android"],
"release_date": "2022-09-20"
}
}
]
}
}
9. Bool Query
Об'єднати кілька умов:
- Має бути співпадіння
in_stock: true
іprice < 100
.
Запит:
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "term": { "in_stock": true } },
{ "range": { "price": { "lt": 100 } } }
]
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"category": "Електроніка",
"price": 59.99,
"rating": 4.5,
"in_stock": true,
"tags": ["аудіо", "bluetooth", "безпровідні"],
"release_date": "2023-01-15"
}
}
]
}
}
10. Filter
Фільтри виключають документи, не впливаючи на релевантність.
11. Aggregation
Знайти середню ціну всіх продуктів.
Запит:
GET /products/_search
{
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
Виведення:
{
"aggregations": {
"average_price": {
"value": 283.3233333333333
}
}
}
12. Highlighting
Підсвічування відповідних термінів у результатах.
Сортування
Сортуйте результати за ціною в порядку зростання.
Запит:
GET /products/_search
{
"sort": [
{ "price": "asc" }
]
}
Виведення:
{
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"price": 59.99
}
},
{
"_source": {
"product_id": 2,
"name": "Кросівки для бігу",
"price": 89.99
}
},
{
"_source": {
"product_id": 3,
"name": "Смартфон",
"price": 699.99
}
}
]
}
}
14. Запит діапазону
Знайти продукти з ціною між $50 і $100.
Запит:
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 50,
"lte": 100
}
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"price": 59.99
}
},
{
"_source": {
"product_id": 2,
"name": "Кросівки для бігу",
"price": 89.99
}
}
]
}
}
15. Запит за префіксом
Знайти продукти, де назва починається з “Wire”.
Запит:
GET /products/_search
{
"query": {
"prefix": {
"name": "Wire"
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники"
}
}
]
}
}
16. Запит за шаблоном
Знайти продукти з назвами, що містять "Sho*" (наприклад, Shoes).
Запит:
GET /products/_search
{
"query": {
"wildcard": {
"name": {
"value": "Sho*"
}
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 2,
"name": "Кросівки для бігу"
}
}
]
}
}
17. Точковий запит
Знайти продукти з назвами, подібними до “Smartfone” (припускаючи помилки в написанні).
Запит:
GET /products/_search
{
"query": {
"fuzzy": {
"name": {
"value": "Smartfone",
"fuzziness": 2
}
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 3,
"name": "Смартфон"
}
}
]
}
}
18. Запит на наявність
Знайти всі продукти, у яких є поле rating
.
Запит:
GET /products/_search
{
"query": {
"exists": {
"field": "rating"
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"hits": [
{ "_source": { "product_id": 1, "rating": 4.5 } },
{ "_source": { "product_id": 2, "rating": 4.7 } },
{ "_source": { "product_id": 3, "rating": 4.6 } }
]
}
}
19. Запит за термінами
Знайти продукти в кількох категоріях: Електроніка
та Спорт
.
Запит:
GET /products/_search
{
"query": {
"terms": {
"category": ["Electronics", "Sports"]
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"hits": [
{ "_source": { "product_id": 1, "category": "Електроніка" } },
{ "_source": { "product_id": 2, "category": "Спорт" } },
{ "_source": { "product_id": 3, "category": "Електроніка" } }
]
}
}
20. Запит за точною фразою
Знайти продукти з точною фразою “Running Shoes” у їхній назві.
Запит:
GET /products/_search
{
"query": {
"match_phrase": {
"name": "Running Shoes"
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 2,
"name": "Running Shoes"
}
}
]
}
}
## 21. Запит на підвищення
Підвищити документи, де категорія `Electronics`, але знижувати ті, у яких рейтинг менше 4.6.
Запит:
GET /products/search
{
"query": {
"boosting": {
"positive": {
"term": { "category": "Electronics" }
},
"negative": {
"range": { "rating": { "lt": 4.6 } }
},
"negativeboost": 0.5
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"source": {
"productid": 3,
"name": "Смартфон",
"rating": 4.6
}
},
{
"source": {
"productid": 1,
"name": "Безпровідні навушники",
"rating": 4.5
}
}
]
}
}
```
22. Запит Multi-Match
Шукати продукти за ключовими словами в полях name
і tags
.
Запит:
GET /products/_search
{
"query": {
"multi_match": {
"query": "bluetooth",
"fields": ["name", "tags"]
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"tags": ["audio", "bluetooth", "wireless"]
}
}
]
}
}
23. Запит за рядковим запитом
Знайти продукти, використовуючи рядковий запит, який відповідає “name:Smart AND price:[50 TO 100]”.
Запит:
GET /products/_search
{
"query": {
"query_string": {
"query": "name:Smart AND price:[50 TO 100]"
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Смартфон",
"price": 89.99
}
}
]
}
}
24. Користувацький аналізатор
Створити користувацький аналізатор для описів продуктів, розбиваючи текст на слова і перетворюючи їх у малий регістр.
Запит:
PUT /products/_settings
{
"analysis": {
"tokenizer": {
"custom_tokenizer": {
"type": "pattern",
"pattern": "\\W+"
}
},
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "custom_tokenizer"
}
}
}
}
25. Токенізатор Edge NGram
Використовувати токенізатор edge ngram для автозаповнення під час пошуку продуктів.
Запит:
PUT /products/_settings
{
"analysis": {
"tokenizer": {
"edge_ngram_tokenizer": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 25,
"token_chars": ["letter", "digit"]
}
},
"analyzer": {
"edge_ngram_analyzer": {
"type": "custom",
"tokenizer": "edge_ngram_tokenizer"
}
}
}
}
26. Сортування
Сортувати продукти за ціною у спадному порядку.
Запит:
GET /products/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
Виведення:
{
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 2,
"name": "Кросівки для бігу",
"price": 89.99
}
},
{
"_source": {
"product_id": 3,
"name": "Смартфон",
"price": 79.99
}
},
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"price": 59.99
}
}
]
}
}
27. Пагінація (From/Size)
Отримати другу сторінку з 2 продуктами.
Запит:
GET /products/_search
{
"from": 2,
"size": 2,
"query": {
"match_all": {}
}
}
Виведення:
{
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 3,
"name": "Смартфон"
}
},
{
"_source": {
"product_id": 4,
"name": "Розумні годинники"
}
}
]
}
}
28. Агрегації (Aggregation)
Отримати середню ціну продуктів.
Запит:
GET /products/_search
{
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
Виведення:
{
"aggregations": {
"average_price": {
"value": 79.99
}
}
}
## 29. Агрегація за термінами
Отримати топ категорій за кількістю.
Запит:
GET /products/search
{
"aggs": {
"categoryterms": {
"terms": {
"field": "category.keyword"
}
}
}
}
Виведення:
{
"aggregations": {
"categoryterms": {
"buckets": [
{
"key": "Електроніка",
"doccount": 3
},
{
"key": "Спорт",
"doc_count": 2
}
]
}
}
}
```
30. Агрегація за гістограмою дат
Агрегувати продукти за ціновим діапазоном (наприклад, кожні $20).
Запит:
GET /products/_search
{
"aggs": {
"price_histogram": {
"histogram": {
"field": "price",
"interval": 20
}
}
}
}
Виведення:
{
"aggregations": {
"price_histogram": {
"buckets": [
{
"key": 40,
"doc_count": 1
},
{
"key": 60,
"doc_count": 2
},
{
"key": 80,
"doc_count": 1
}
]
}
}
}
31. Агрегація за кастомними метриками
Обчислити кастомну метрику (наприклад, загальна вартість всіх продуктів).
Запит:
GET /products/_search
{
"aggs": {
"total_value": {
"scripted_metric": {
"init_script": "state.total = 0",
"map_script": "state.total += doc['price'].value",
"combine_script": "return state.total",
"reduce_script": "return states.sum()"
}
}
}
}
Виведення:
{
"aggregations": {
"total_value": {
"value": 299.97
}
}
}
32. Виділення
Виділяти терміни пошуку в описах продуктів.
Запит:
GET /products/_search
{
"query": {
"match": {
"description": "smartphone"
}
},
"highlight": {
"fields": {
"description": {}
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 3,
"name": "Смартфон",
"description": "Останній смартфон з дивовижними характеристиками"
},
"highlight": {
"description": [
"Останній смартфон з дивовижними характеристиками"
]
}
}
]
}
}
33. Булевий запит (AND, OR, NOT)
Знайти продукти з категорії Electronics
і ціною менше $100.
Запит:
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "category": "Electronics" } },
{ "range": { "price": { "lt": 100 } } }
]
}
}
}
Виведення:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"_source": {
"product_id": 1,
"name": "Безпровідні навушники",
"price": 59.99
}
},
{
"_source": {
"product_id": 2,
"name": "Смартфон",
"price": 79.99
}
}
]
}
}
34. Вкладений запит
Знайти продукти з вкладеним масивом reviews
і відфільтрувати за рейтингом, більшим за 4.
Запит:
GET /products/_search
{
"query": {
"nested": {
"path": "reviews",
"query": {
"range": {
"reviews.rating": {
"gte": 4
}
}
}
}
}
}
35. Геопросторові запити
Знайти продукти в межах 50 км від певного місця.
Запит:
GET /products/_search
{
"query": {
"geo_distance": {
"distance": "50km",
"location": [40.7128, -74.0060]
}
}
}
36. Підвищення з використанням затухання
Використовувати функцію затухання для підвищення продуктів на основі їхньої дати додавання.
Запит:
GET /products/_search
{
"query": {
"gauss": {
"date_added": {
"origin": "now",
"scale": "10d",
"decay": 0.5
}
}
}
}
37. Згорнення
Згорнути результати пошуку на основі поля category
.
Запит:
GET /products/_search
{
"query": {
"match_all": {}
},
"collapse": {
"field": "category.keyword"
}
}
38. Перколяторний запит
Попередньо визначені умови запиту для нових документів.
Запит:
POST /queries/_doc/1
{
"query": {
"match": {
"name": "Смартфон"
}
}
}
GET /products/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"name": "Смартфон"
}
}
}
}
## 39. API для підрахунку
Підрахувати, скільки продуктів існує в базі даних.
Запит:
GET /products/count
{
"query": {
"matchall": {}
}
}
Виведення:
{
"count": 5
}
```
40. API для оновлення
Оновити ціну конкретного продукту.
Запит:
POST /products/_update/1
{
"doc": {
"price": 69.99
}
}
41. API для видалення
Видалити продукт за product_id
.
Запит:
DELETE /products/_doc/1
42. Bulk API
Виконати кілька дій в одному запиті (індексація, оновлення, видалення).
Запит:
POST /_bulk
{ "index": { "_index": "products", "_id": 1 } }
{ "product_id": 1, "name": "Смартфон", "price": 79.99 }
{ "delete": { "_index": "products", "_id": 3 } }
Перекладено з: [Mastering Elasticsearch Search APIs: A Comprehensive Guide for Developers](https://medium.com/@aifuture/mastering-elasticsearch-search-apis-a-comprehensive-guide-for-developers-b0df30a3a99f)