Skrócony przewodnik Elasticsearch: Kluczowe polecenia i wskazówki

Polecenia Elasticsearch do wyszukiwania, indeksowania i analizy

Page content

Elasticsearch to potężny, rozproszony silnik wyszukiwania i analityczny oparty na Apache Lucene. Ten kompleksowy skrypt zawiera podstawowe polecenia, najlepsze praktyki i szybkie odniesienia do pracy z klastrami Elasticsearch.

elasticsearch

Uwaga: Większość przykładów w tym przewodniku używa cURL do żądań HTTP. Jeśli jesteś nowy w cURL lub potrzebujesz szybkiego odniesienia do zaawansowanych opcji, sprawdź naszą Ściągię cURL dla szczegółowych technik żądań HTTP w wierszu poleceń.

Zarządzanie klastrami

Sprawdzenie stanu klastra

Wszystkie polecenia w tej sekcji wykorzystują cURL do interakcji z REST API Elasticsearch. Możesz dostosować te żądania, dodając dodatkowe nagłówki, uwierzytelnianie i inne opcje w zależności od potrzeb.

# Podstawowa kontrola stanu
curl -X GET "localhost:9200/_cluster/health?pretty"

# Szczegółowy stan klastra z informacjami o fragmentach (shards)
curl -X GET "localhost:9200/_cluster/health?level=shards&pretty"

# Sprawdzenie informacji o węzłach
curl -X GET "localhost:9200/_cat/nodes?v"

# Sprawdzenie ustawień klastra
curl -X GET "localhost:9200/_cluster/settings?pretty"

Operacje na węzłach

# Wyświetlenie wszystkich węzłów
curl -X GET "localhost:9200/_cat/nodes?v&h=name,node.role,heap.percent,ram.percent,cpu,load_1m"

# Statystyki węzłów
curl -X GET "localhost:9200/_nodes/stats?pretty"

# Gorące wątki (do rozwiązywania problemów)
curl -X GET "localhost:9200/_nodes/hot_threads"

Zarządzanie indeksami

Tworzenie i usuwanie indeksów

# Tworzenie indeksu
curl -X PUT "localhost:9200/my_index?pretty"

# Tworzenie indeksu z ustawieniami
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}
'

# Usuwanie indeksu
curl -X DELETE "localhost:9200/my_index?pretty"

# Wyświetlenie wszystkich indeksów
curl -X GET "localhost:9200/_cat/indices?v"

# Statystyki indeksu
curl -X GET "localhost:9200/my_index/_stats?pretty"

Mapowania indeksów (Mappings)

# Definiowanie mapowania
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"
      }
    }
  }
}
'

# Pobranie mapowania
curl -X GET "localhost:9200/products/_mapping?pretty"

# Aktualizacja mapowania (dodawanie pola)
curl -X PUT "localhost:9200/products/_mapping" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "category": { "type": "keyword" }
  }
}
'

Szablony indeksów

# Tworzenie szablonu indeksu
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" }
      }
    }
  }
}
'

# Wyświetlenie szablonów
curl -X GET "localhost:9200/_index_template?pretty"

Operacje na dokumentach (CRUD)

Tworzenie dokumentów

# Indeksowanie dokumentu z automatycznie generowanym ID
curl -X POST "localhost:9200/products/_doc?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99,
  "tags": ["electronics", "computers"]
}
'

# Indeksowanie dokumentu z konkretnym ID
curl -X PUT "localhost:9200/products/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99
}
'

# Indeksowanie wsadowe (bulk)
curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index": { "_index": "products", "_id": "1" }}
{ "name": "Laptop", "price": 999.99 }
{ "index": { "_index": "products", "_id": "2" }}
{ "name": "Mouse", "price": 29.99 }
'

Odczyt dokumentów

# Pobranie dokumentu po ID
curl -X GET "localhost:9200/products/_doc/1?pretty"

# Pobranie wielu dokumentów
curl -X GET "localhost:9200/_mget?pretty" -H 'Content-Type: application/json' -d'
{
  "docs": [
    { "_index": "products", "_id": "1" },
    { "_index": "products", "_id": "2" }
  ]
}
'

# Sprawdzenie istnienia dokumentu
curl -I "localhost:9200/products/_doc/1"

Aktualizacja dokumentów

# Aktualizacja dokumentu
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  }
}
'

# Aktualizacja ze skryptem
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 (aktualizacja lub wstawienie)
curl -X POST "localhost:9200/products/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": {
    "price": 899.99
  },
  "doc_as_upsert": true
}
'

Usuwanie dokumentów

# Usunięcie po ID
curl -X DELETE "localhost:9200/products/_doc/1?pretty"

# Usunięcie na podstawie zapytania
curl -X POST "localhost:9200/products/_delete_by_query?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "old"
    }
  }
}
'

Zapytania wyszukiwania

Podstawowe zapytania

# Zgodność ze wszystkimi (Match all)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'

# Zapytanie Match
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "name": "laptop"
    }
  }
}
'

# Zapytanie Multi-match
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "laptop gaming",
      "fields": ["name", "description"]
    }
  }
}
'

Zapytania na poziomie terminów

# Zapytanie Term (dokładna zbieżność)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "tags": "electronics"
    }
  }
}
'

# Zapytanie Terms (wiele wartości)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "terms": {
      "tags": ["electronics", "computers"]
    }
  }
}
'

# Zapytanie Range (zakres)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 1000
      }
    }
  }
}
'

# Zapytanie Exists
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "exists": {
      "field": "description"
    }
  }
}
'

Zapytania booleanowe

# Zapytanie Bool (must, should, must_not, filter)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "laptop" }}
      ],
      "filter": [
        { "range": { "price": { "gte": 500 }}}
      ],
      "should": [
        { "term": { "tags": "gaming" }}
      ],
      "must_not": [
        { "term": { "tags": "refurbished" }}
      ]
    }
  }
}
'

Zaawansowane wyszukiwanie

# Zapytanie Wildcard
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "wildcard": {
      "name": "lap*"
    }
  }
}
'

# Zapytanie Fuzzy (tolerancja błędów literowych)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "laptpo",
        "fuzziness": "AUTO"
      }
    }
  }
}
'

# Zapytanie Prefix
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "prefix": {
      "name": "lap"
    }
  }
}
'

Agregacje

Agregacje metryczne

# Średnia, suma, minimum, maksimum
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" }}
  }
}
'

# Agregacja statystyk
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "price_stats": {
      "stats": { "field": "price" }
    }
  }
}
'

Agregacje kubełkowe (Bucket Aggregations)

# Agregacja Terms (grupowanie)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "size": 0,
  "aggs": {
    "popular_tags": {
      "terms": {
        "field": "tags",
        "size": 10
      }
    }
  }
}
'

# Agregacja Range (zakresy)
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 }
        ]
      }
    }
  }
}
'

# Histogram daty
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"
      }
    }
  }
}
'

Agregacje zagnieżdżone

# Agregacje zagnieżdżone
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" }
        }
      }
    }
  }
}
'

Sortowanie i paginacja

# Sortowanie po polu
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "sort": [
    { "price": { "order": "desc" }},
    { "_score": { "order": "desc" }}
  ]
}
'

# Paginacja z from/size
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "from": 0,
  "size": 10,
  "query": { "match_all": {} }
}
'

# Search after (do głębokiej paginacji)
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"]
}
'

Wybór pól i podświetlanie (Highlighting)

# Wybór konkretnych pól
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}
'

# Podświetlanie (Highlighting)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": { "description": "gaming laptop" }
  },
  "highlight": {
    "fields": {
      "description": {}
    }
  }
}
'

Aliasy indeksów

# Tworzenie aliasu
curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d'
{
  "actions": [
    { "add": { "index": "products_v1", "alias": "products" }}
  ]
}
'

# Przełączenie aliasu na nowy indeks (bez przestoju)
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" }}
  ]
}
'

# Wyświetlenie aliasów
curl -X GET "localhost:9200/_cat/aliases?v"

Ponowne indeksowanie (Reindex)

# Ponowne indeksowanie z jednego indeksu do drugiego
curl -X POST "localhost:9200/_reindex?pretty" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "old_products"
  },
  "dest": {
    "index": "new_products"
  }
}
'

# Ponowne indeksowanie z zapytaniem
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"
  }
}
'

Snapshots i kopie zapasowe

# Rejestracja repozytorium snapshotów
curl -X PUT "localhost:9200/_snapshot/my_backup?pretty" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/mount/backups/my_backup"
  }
}
'

# Tworzenie snapshotu
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true&pretty"

# Przywracanie snapshotu
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore?pretty"

# Wyświetlenie snapshotów
curl -X GET "localhost:9200/_snapshot/my_backup/_all?pretty"

# Usuwanie snapshotu
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_1?pretty"

Optymalizacja wydajności

Ustawienia indeksu

# Wyłączenie odświeżania podczas indeksowania wsadowego
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "-1"
  }
}
'

# Ponowne włączenie po indeksowaniu wsadowym
curl -X PUT "localhost:9200/products/_settings?pretty" -H 'Content-Type: application/json' -d'
{
  "index": {
    "refresh_interval": "1s"
  }
}
'

# Wymuszenie scalania (optymalizacja)
curl -X POST "localhost:9200/products/_forcemerge?max_num_segments=1&pretty"

Czyszczenie pamięci podręcznej

# Wyczyść wszystkie pamięci podręczne
curl -X POST "localhost:9200/_cache/clear?pretty"

# Wyczyść konkretną pamięć podręczną
curl -X POST "localhost:9200/products/_cache/clear?query=true&pretty"

Monitoring i rozwiązywanie problemów

# Zadania oczekujące
curl -X GET "localhost:9200/_cat/pending_tasks?v"

# Statystyki puli wątków
curl -X GET "localhost:9200/_cat/thread_pool?v"

# Informacje o segmentach
curl -X GET "localhost:9200/_cat/segments?v"

# Informacje o odzyskiwaniu (recovery)
curl -X GET "localhost:9200/_cat/recovery?v&h=index,stage,time"

# API zadań
curl -X GET "localhost:9200/_tasks?detailed=true&pretty"

Przykłady klienta Python

from elasticsearch import Elasticsearch

# Połączenie z Elasticsearch
es = Elasticsearch(['http://localhost:9200'])

# Indeksowanie dokumentu
doc = {
    'name': 'Laptop',
    'price': 999.99,
    'tags': ['electronics']
}
es.index(index='products', id=1, document=doc)

# Wyszukiwanie
resp = es.search(index='products', query={'match': {'name': 'laptop'}})
for hit in resp['hits']['hits']:
    print(hit['_source'])

# Indeksowanie wsadowe (bulk)
from elasticsearch.helpers import bulk

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

Przykłady klienta JavaScript/Node.js

Klient JavaScript dla Elasticsearch zapewnia bezpieczny typowo sposób interakcji z klastrem. W aplikacjach produkcyjnych rozważ użycie TypeScript dla lepszej bezpieczeństwa typów i autouzupełniania. Zobacz naszą Ściągię TypeScript, aby poznać najlepsze praktyki dotyczące definicji typów i interfejsów.

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

// Indeksowanie dokumentu
async function indexDoc() {
  await client.index({
    index: 'products',
    id: 1,
    document: {
      name: 'Laptop',
      price: 999.99
    }
  });
}

// Wyszukiwanie
async function search() {
  const result = await client.search({
    index: 'products',
    query: {
      match: { name: 'laptop' }
    }
  });
  console.log(result.hits.hits);
}

// Indeksowanie wsadowe
async function bulkIndex() {
  const operations = [];
  for (let i = 0; i < 1000; i++) {
    operations.push({ index: { _index: 'products', _id: i } });
    operations.push({ name: `Product ${i}`, price: i * 10 });
  }
  await client.bulk({ operations });
}

Przykład TypeScript z silną typowością

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);
}

Najlepsze praktyki

Projektowanie indeksów

  • Utrzymuj rozmiar fragmentów (shardów) między 20 a 50 GB dla optymalnej wydajności
  • Używaj zarządzania cyklem życia indeksów (ILM) dla danych szeregów czasowych
  • Starannie projektuj mapowania przed indeksowaniem danych
  • Używaj odpowiednich typów pól (keyword vs text, formaty dat)
  • Wyłącz _source dla dużych dokumentów, jeśli nie jest potrzebny

Optymalizacja zapytań

  • Używaj filtrów zamiast zapytań, gdy nie jest potrzebne punktowanie (scoring)
  • Preferuj zapytania na poziomie terminów dla danych strukturalnych
  • Używaj zapytania bool do efektywnego łączenia wielu warunków
  • Implementuj paginację z search_after do głębokiej paginacji
  • Cachuj często używane filtry

Wydajność indeksowania

  • Używaj API wsadowego do indeksowania partiami (1000-5000 dokumentów na żądanie)
  • Wyłącz odświeżanie podczas operacji wsadowych
  • Zwiększ index.refresh_interval podczas intensywnego indeksowania
  • Używaj wielu wątków/pracowników do równoległego indeksowania
  • Rozważ użycie routingu dla lepszej dystrybucji fragmentów

Zarządzanie klastrami

  • Regularnie monitoruj stan klastra
  • Ustaw odpowiednią konfigurację replik
  • Używaj dedykowanych węzłów master dla dużych klastrów
  • Implementuj odpowiednią strategię kopii zapasowych za pomocą snapshotów
  • Monitoruj zużycie pamięci JVM (utrzymuj poniżej 75%)

Bezpieczeństwo

  • Włącz uwierzytelnianie i autoryzację (X-Pack Security)
  • Używaj HTTPS w wdrożeniach produkcyjnych (skonfiguruj cURL z opcjami --cacert, --cert i --key dla SSL/TLS)
  • Implementuj odpowiednią kontrolę dostępu opartą na rolach (RBAC)
  • Regularnie stosuj aktualizacje i łaty bezpieczeństwa
  • Szyfruj dane w spoczynku i podczas transmisji

Typowe przypadki użycia

Pełnotekstowa wyszukiwarka

Elasticsearch excelsuje w wyszukiwaniu pełnotekstowym z funkcjami takimi jak:

  • Punktowanie trafności (relevance scoring)
  • Zgodność fuzzy (fuzzy matching)
  • Zgodność fraz (phrase matching)
  • Obsługa synonimów
  • Obsługa wielu języków Jeśli oceniasz, czy zachować wyszukiwanie wewnątrz Postgres, czy przenieść się do dedykowanego silnika wyszukiwania, to porównanie pełnotekstowego wyszukiwania w PostgreSQL z Elasticsearch analizuje praktyczne kompromisy.

Analiza logów (Stack ELK)

  • Zbieranie logów z Logstash/Filebeat
  • Indeksowanie i wyszukiwanie logów w Elasticsearch
  • Wizualizacja na dashboardach Kibana
  • Konfigurowanie alertów dla anomalii

Wyszukiwanie w e-commerce

  • Wyszukiwanie katalogu produktów
  • Nawigacja fasetowa z agregacjami
  • Autouzupełnianie i sugestie
  • Spersonalizowane wyniki wyszukiwania

Monitorowanie wydajności aplikacji

  • Indeksowanie metryk aplikacji
  • Dashboardy monitoringu w czasie rzeczywistym
  • Wykrywanie anomalii
  • Analiza trendów wydajności

Przydatne linki

Oficjalne zasoby Elasticsearch

Powiązane ścigi i przewodniki

Subskrybuj

Otrzymuj nowe wpisy o systemach, infrastrukturze i inżynierii AI.