Шпаргалка по Elasticsearch: Основные команды и советы

Команды Elasticsearch для поиска, индексирования и анализа

Содержимое страницы

Elasticsearch — это мощный распределенный поисковый и аналитический движок, построенный на Apache Lucene. Это подробное руководство содержит основные команды, лучшие практики и быстрые ссылки для работы с кластерами Elasticsearch.

elasticsearch

Примечание: Большинство примеров в этом руководстве используют cURL для HTTP-запросов. Если вы не знакомы с cURL или вам нужна быстрая справка по дополнительным опциям, ознакомьтесь с нашим cURL Cheatsheet для подробных техник командной строки HTTP-запросов.

Управление кластером

Проверка состояния кластера

Все команды в этом разделе используют cURL для взаимодействия с REST API Elasticsearch. Вы можете настроить эти запросы с дополнительными заголовками, аутентификацией и другими параметрами по мере необходимости.

# Базовая проверка состояния
curl -X GET "localhost:9200/_cluster/health?pretty"

# Подробное состояние кластера с информацией о шардах
curl -X GET "localhost:9200/_cluster/health?level=shards&pretty"

# Проверка информации о узлах
curl -X GET "localhost:9200/_cat/nodes?v"

# Проверка настроек кластера
curl -X GET "localhost:9200/_cluster/settings?pretty"

Операции с узлами

# Список всех узлов
curl -X GET "localhost:9200/_cat/nodes?v&h=name,node.role,heap.percent,ram.percent,cpu,load_1m"

# Статистика узлов
curl -X GET "localhost:9200/_nodes/stats?pretty"

# Горячие потоки (диагностика)
curl -X GET "localhost:9200/_nodes/hot_threads"

Управление индексами

Создание и удаление индексов

# Создать индекс
curl -X PUT "localhost:9200/my_index?pretty"

# Создать индекс с настройками
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}
'

# Удалить индекс
curl -X DELETE "localhost:9200/my_index?pretty"

# Список всех индексов
curl -X GET "localhost:9200/_cat/indices?v"

# Статистика индекса
curl -X GET "localhost:9200/my_index/_stats?pretty"

Карты индексов

# Определить карту
curl -X PUT "localhost:9200/products" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "price": { "type": "float" },
      "created_at": { "type": "date" },
      "tags": { "type": "keyword" },
      "description": {
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}
'

# Получить карту
curl -X GET "localhost:9200/products/_mapping?pretty"

# Обновить карту (добавить поле)
curl -X PUT "localhost:9200/products/_mapping" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "category": { "type": "keyword" }
  }
}
'

Шаблоны индексов

# Создать шаблон индекса
curl -X PUT "localhost:9200/_index_template/logs_template" -H 'Content-Type: application/json' -d'
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 1
    },
    "mappings": {
      "properties": {
        "timestamp": { "type": "date" },
        "message": { "type": "text" },
        "level": { "type": "keyword" }
      }
    }
  }
}
'

# Список шаблонов
curl -X GET "localhost:9200/_index_template?pretty"

Операции с документами (CRUD)

Создание документов

# Индексация документа с автоматически сгенерированным ID
curl -X POST "localhost:9200/products/_doc?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Ноутбук",
  "price": 999.99,
  "tags": ["электроника", "компьютеры"]
}
'

# Индексация документа с конкретным ID
curl -X PUT "localhost:9200/products/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Ноутбук",
  "price": 999.99
}
'

# Массовая индексация
curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index": { "_index": "products", "_id": "1" }}
{ "name": "Ноутбук", "price": 999.99 }
{ "index": { "_index": "products", "_id": "2" }}
{ "name": "Мышь", "price": 29.99 }
'

Чтение документов

# Получить документ по ID
curl -X GET "localhost:9200/products/_doc/1?pretty"

# Получить несколько документов
curl -X GET "localhost:9200/_mget?pretty" -H 'Content-Type: application/json' -d'
{
  "docs": [
    { "_index": "products", "_id": "1" },
    { "_index": "products", "_id": "2" }
  ]
}
'

# Проверить существование документа
curl -I "localhost:9200/products/_doc/1"

Обновление документов

# Обновить документ
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  }
}
'

# Обновить с помощью скрипта
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "script": {
    "source": "ctx._source.price *= params.discount",
    "params": {
      "discount": 0.9
    }
  }
}
'

# Upsert (обновить или вставить)
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  },
  "doc_as_upsert": true
}
'

Удаление документов

# Удалить по ID
curl -X DELETE "localhost:9200/products/_doc/1?pretty"

# Удалить по запросу
curl -X POST "localhost:9200/products/_delete_by_query?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "old"
    }
  }
}
'

Поисковые запросы

Базовый поиск

# Соответствие всем
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'

# Запрос соответствия
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "ноутбук"
    }
  }
}
'

# Множественный запрос соответствия
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "ноутбук гейминг",
      "fields": ["name", "description"]
    }
  }
}
'

Запросы уровня термина

# Запрос термина (точное соответствие)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "tags": "электроника"
    }
  }
}
'

# Запрос терминов (несколько значений)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "terms": {
      "tags": ["электроника", "компьютеры"]
    }
  }
}
'

# Запрос диапазона
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 1000
      }
    }
  }
}
'

# Запрос существования
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "exists": {
      "field": "description"
    }
  }
}
'

Логические запросы

# Логический запрос (must, should, must_not, filter)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "ноутбук" }}
      ],
      "filter": [
        { "range": { "price": { "gte": 500 }}}
      ],
      "should": [
        { "term": { "tags": "гейминг" }}
      ],
      "must_not": [
        { "term": { "tags": "б/у" }}
      ]
    }
  }
}
'

Расширенный поиск

# Запрос с подстановочными знаками
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "wildcard": {
      "name": "lap*"
    }
  }
}
'

# Нечеткий запрос (терпимость к опечаткам)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "laptpo",
        "fuzziness": "AUTO"
      }
    }
  }
}
'

# Запрос префикса
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "prefix": {
      "name": "lap"
    }
  }
}
'

Агрегации

Метрические агрегации

# Среднее, сумма, минимум, максимум
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "avg_price": { "avg": { "field": "price" }},
    "max_price": { "max": { "field": "price" }},
    "min_price": { "min": { "field": "price" }},
    "total_sales": { "sum": { "field": "price" }}
  }
}
'

# Статистическая агрегация
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_stats": {
      "stats": { "field": "price" }
    }
  }
}
'

Агрегации по корзинам

# Агрегация по терминам (группировка)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "popular_tags": {
      "terms": {
        "field": "tags",
        "size": 10
      }
    }
  }
}
'

# Агрегация по диапазонам
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 50 },
          { "from": 50, "to": 100 },
          { "from": 100 }
        ]
      }
    }
  }
}
'

# Гистограмма по дате
curl -X GET "localhost:9200/logs/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "logs_over_time": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "day"
      }
    }
  }
}
'

Вложенные агрегации

# Вложенные агрегации
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "categories": {
      "terms": { "field": "category" },
      "aggs": {
        "avg_price": {
          "avg": { "field": "price" }
        }
      }
    }
  }
}
'

Сортировка и пагинация

# Сортировка по полю
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "price": { "order": "desc" }},
    { "_score": { "order": "desc" }}
  ]
}
'

# Пагинация с from/size
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "from": 0,
  "size": 10,
  "query": { "match_all": {} }
}
'

# Поиск после (для глубокой пагинации)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 10,
  "query": { "match_all": {} },
  "sort": [{ "price": "asc" }, { "_id": "asc" }],
  "search_after": [100, "product_123"]
}
'

Выбор и выделение полей

# Выбор конкретных полей
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}
'

# Выделение
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": { "description": "игровая ноутбук" }
  },
  "highlight": {
    "fields": {
      "description": {}
    }
  }
}
'

Псевдонимы индексов

# Создание псевдонима
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "add": { "index": "products_v1", "alias": "products" }}
  ]
}
'

# Переключение псевдонима на новый индекс (без простоев)
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "remove": { "index": "products_v1", "alias": "products" }},
    { "add": { "index": "products_v2", "alias": "products" }}
  ]
}
'

# Список псевдонимов
curl -X GET "localhost:9200/_cat/aliases?v"

Переиндексация

# Переиндексация из одного индекса в другой
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "old_products"
  },
  "dest": {
    "index": "new_products"
  }
}
'

# Переиндексация с запросом
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "products",
    "query": {
      "range": {
        "price": { "gte": 100 }
      }
    }
  },
  "dest": {
    "index": "expensive_products"
  }
}
'

Снимки и резервные копии

# Регистрация репозитория снимков
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/mount/backups/my_backup"
  }
}
'

# Создание снимка
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true&pretty"

# Восстановление снимка
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore?pretty"

# Список снимков
curl -X GET "localhost:9200/_snapshot/my_backup/_all?pretty"

# Удаление снимка
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_1?pretty"

Оптимизация производительности

Настройки индекса

# Отключение обновления при массовой индексации
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "-1"
  }
}
'

# Включение после массовой индексации
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "1s"
  }
}
'

# Принудительное слияние (оптимизация)
curl -X POST "localhost:9200/products/_forcemerge?max_num_segments=1&pretty"

Очистка кэша

# Очистка всех кэшей
curl -X POST "localhost:9200/_cache/clear?pretty"

# Очистка конкретного кэша
curl -X POST "localhost:9200/products/_cache/clear?query=true&pretty"

Мониторинг и устранение неполадок

# Ожидающие задачи
curl -X GET "localhost:9200/_cat/pending_tasks?v"

# Статистика пула потоков
curl -X GET "localhost:9200/_cat/thread_pool?v"

# Информация о сегментах
curl -X GET "localhost:9200/_cat/segments?v"

# Информация о восстановлении
curl -X GET "localhost:9200/_cat/recovery?v&h=index,stage,time"

# API задач
curl -X GET "localhost:9200/_tasks?detailed=true&pretty"

Примеры клиента на Python

from elasticsearch import Elasticsearch

# Подключение к Elasticsearch
es = Elasticsearch(['http://localhost:9200'])

# Индексация документа
doc = {
    'name': 'Ноутбук',
    'price': 999.99,
    'tags': ['электроника']
}
es.index(index='products', id=1, document=doc)

# Поиск
resp = es.search(index='products', query={'match': {'name': 'ноутбук'}})
for hit in resp['hits']['hits']:
    print(hit['_source'])

# Массовая индексация
from elasticsearch.helpers import bulk

actions = [
    {
        '_index': 'products',
        '_id': i,
        '_source': {'name': f'Товар {i}', 'price': i * 10}
    }
    for i in range(1000)
]
bulk(es, actions)

Примеры клиента на JavaScript/Node.js

Клиент Elasticsearch для JavaScript предоставляет безопасный по типу способ взаимодействия с вашим кластером. Для производственных приложений рассмотрите использование TypeScript для лучшей безопасности типов и автозаполнения. Ознакомьтесь с нашим TypeScript Cheatsheet для лучших практик определения типов и интерфейсов.

const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });

// Индексация документа
async function indexDoc() {
  await client.index({
    index: 'products',
    id: 1,
    document: {
      name: 'Ноутбук',
      price: 999.99
    }
  });
}

// Поиск
async function search() {
  const result = await client.search({
    index: 'products',
    query: {
      match: { name: 'ноутбук' }
    }
  });
  console.log(result.hits.hits);
}

// Массовая индексация
async function bulkIndex() {
  const operations = [];
  for (let i = 0; i < 1000; i++) {
    operations.push({ index: { _index: 'products', _id: i } });
    operations.push({ name: `Товар ${i}`, price: i * 10 });
  }
  await client.bulk({ operations });
}

Пример TypeScript с сильной типизацией

import { Client } from '@elastic/elasticsearch';

interface Product {
  name: string;
  price: number;
  tags?: string[];
  created_at?: Date;
}

const client = new Client({ node: 'http://localhost:9200' });

async function indexProduct(product: Product, id: number): Promise<void> {
  await client.index<Product>({
    index: 'products',
    id: id.toString(),
    document: product
  });
}

async function searchProducts(query: string): Promise<Product[]> {
  const result = await client.search<Product>({
    index: 'products',
    query: {
      match: { name: query }
    }
  });

  return result.hits.hits.map(hit => hit._source as Product);
}

Лучшие практики

Дизайн индекса

  • Поддерживайте размер шарда между 20-50ГБ для оптимальной производительности
  • Используйте управление жизненным циклом индекса (ILM) для временных данных
  • Тщательно проектируйте маппинги перед индексацией данных
  • Используйте подходящие типы полей (keyword vs text, форматы дат)
  • Отключайте _source для больших документов, если это не требуется

Оптимизация запросов

  • Используйте фильтры вместо запросов, когда не требуется ранжирование
  • Предпочитайте запросы уровня термина для структурированных данных
  • Используйте bool запрос для эффективного объединения нескольких условий
  • Реализуйте пагинацию с search_after для глубокой пагинации
  • Кэшируйте часто используемые фильтры

Производительность индексации

  • Используйте API bulk для пакетной индексации (1000-5000 документов на запрос)
  • Отключайте обновление при массовых операциях
  • Увеличивайте index.refresh_interval при интенсивной индексации
  • Используйте несколько потоков/работников для параллельной индексации
  • Рассмотрите использование маршрутизации для лучшего распределения шардов

Управление кластером

  • Регулярно мониторьте состояние кластера
  • Настройте правильную конфигурацию реплик
  • Используйте выделенные мастер-узлы для больших кластеров
  • Реализуйте правильную стратегию резервного копирования со снимками
  • Мониторьте использование кучи JVM (поддерживайте ниже 75%)

Безопасность

  • Включите аутентификацию и авторизацию (X-Pack Security)
  • Используйте HTTPS для производственных развертываний (настройте cURL с --cacert, --cert, и --key опциями для SSL/TLS)
  • Реализуйте правильный контроль доступа на основе ролей
  • Регулярные обновления безопасности и патчи
  • Шифруйте данные как в покое, так и при передаче

Общие случаи использования

Полнотекстовый поиск

Elasticsearch преуспевает в полнотекстовом поиске с функциями, такими как:

  • Ранжирование по релевантности
  • Нечеткое соответствие
  • Соответствие фразам
  • Обработка синонимов
  • Поддержка нескольких языков

Анализ логов (ELK Stack)

  • Сбор логов с Logstash/Filebeat
  • Индексация и поиск логов в Elasticsearch
  • Визуализация с дашбордами Kibana
  • Настройка оповещений на аномалии

Поиск в интернет-магазинах

  • Поиск по каталогу товаров
  • Фасетная навигация с агрегациями
  • Автозаполнение и предложения
  • Персонализированные результаты поиска

Мониторинг производительности приложений

  • Индексация метрик приложений
  • Дашборды реального времени
  • Обнаружение аномалий
  • Анализ тенденций производительности

Полезные ссылки

Официальные ресурсы Elasticsearch

Связанные шпаргалки и руководства