Elasticsearch チートシート: 必須コマンドとヒント

検索、インデクシングおよび分析用のElasticsearchコマンド

目次

Elasticsearch は、Apache Lucene に基づいて構築された強力な分散型検索および分析エンジンです。 この包括的なチートシートでは、Elasticsearch クラスターを使用する際の必須コマンド、ベストプラクティス、およびクイックリファレンスをカバーしています。

elasticsearch

注意: このガイドのほとんどの例では、HTTP リクエストに cURL を使用しています。cURL に初めて触れるか、高度なオプションのクイックリファレンスが必要な場合は、cURL チートシート を確認してください。詳細なコマンドライン HTTP リクエスト技術について記載されています。

クラスタ管理

クラスタの健康状態の確認

このセクションのすべてのコマンドでは、Elasticsearch の REST API と cURL を使用してやり取りしています。必要に応じて、これらのリクエストに追加のヘッダー、認証、その他のオプションをカスタマイズできます。

# 基本的な健康状態チェック
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": "Laptop",
  "price": 999.99,
  "tags": ["electronics", "computers"]
}
'

# 特定のIDでドキュメントをインデックス
curl -X PUT "localhost:9200/products/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "name": "Laptop",
  "price": 999.99
}
'

# バルクインデックス
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 }
'

ドキュメントの読み取り

# 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
    }
  }
}
'

# 更新または挿入(アップサート)
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": "laptop"
    }
  }
}
'

# マルチマッチクエリ
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "laptop gaming",
      "fields": ["name", "description"]
    }
  }
}
'

テルムレベルクエリ

# テルムクエリ(正確なマッチ)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "tags": "electronics"
    }
  }
}
'

# テルムズクエリ(複数値)
curl -X GET "localhost:9200/products/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "terms": {
      "tags": ["electronics", "computers"]
    }
  }
}
'

# レンジクエリ
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": "laptop" }}
      ],
      "filter": [
        { "range": { "price": { "gte": 500 }}}
      ],
      "should": [
        { "term": { "tags": "gaming" }}
      ],
      "must_not": [
        { "term": { "tags": "refurbished" }}
      ]
    }
  }
}
'

高度な検索

# ワイルドカードクエリ
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": {} }
}
'

# 深いページネーション用のsearch_after
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": "gaming laptop" }
  },
  "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"

リインデックス

# 1つのインデックスから別のインデックスにリインデックス
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': 'Laptop',
    'price': 999.99,
    'tags': ['electronics']
}
es.index(index='products', id=1, document=doc)

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

# バルクインデックス
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)

JavaScript/Node.jsクライアントの例

Elasticsearch JavaScriptクライアントは、クラスタとやり取りするための型安全な方法を提供します。生産アプリケーションでは、型安全性とオートコンプリートのためにTypeScriptを使用することを検討してください。TypeScriptチートシート を参照して、型定義とインターフェースに関するベストプラクティスを確認してください。

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: 'Laptop',
      price: 999.99
    }
  });
}

// 検索
async function search() {
  const result = await client.search({
    index: 'products',
    query: {
      match: { name: 'laptop' }
    }
  });
  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: `Product ${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〜50GBに保つ
  • 時系列データに対してインデックスライフサイクル管理(ILM)を使用する
  • データをインデックスする前にマッピングを慎重に設計する
  • 適切なフィールドタイプを使用する(キーワードとテキスト、日付フォーマット)
  • 必要なければ_sourceを無効にする(大規模なドキュメントの場合)

クエリ最適化

  • スコアリングが不要な場合はフィルタを使用する
  • 構造化データに対してテルムレベルクエリを優先する
  • boolクエリを使用して複数の条件を効率的に組み合わせる
  • 深いページネーションにはsearch_afterを使用する
  • 頻繁に使用されるフィルタをキャッシュする

インデックスングパフォーマンス

  • バッチインデックスングにバルクAPIを使用する(1000〜5000ドキュメントごとに1回のリクエスト)
  • バルク操作中にリフレッシュを無効化する
  • 重いインデックスング中にindex.refresh_intervalを増やす
  • 複数のスレッド/ワーカーを使用して並列インデックスングを行う
  • シャードの分布を改善するためにルーティングを使用する

クラスタ管理

  • クラスタの健康状態を定期的に監視する
  • 適切なレプリカ構成を設定する
  • 大規模なクラスタでは専用のマスターノードを使用する
  • スナップショットを使用して適切なバックアップ戦略を実装する
  • JVMヒープ使用量を監視する(75%以下に保つ)

セキュリティ

  • 認証と認可(X-Packセキュリティ)を有効にする
  • 本番環境ではHTTPSを使用する(cURLに--cacert--cert--keyオプションでSSL/TLSを設定)
  • 適切なロールベースのアクセス制御を実装する
  • 定期的なセキュリティアップデートとパッチを適用する
  • データを静的および動的で暗号化する

一般的なユースケース

フルテキスト検索

Elasticsearchは、以下のような機能によりフルテキスト検索に優れています:

  • 関連性スコアリング
  • ファジーマッチ
  • フレーズマッチ
  • 同義語処理
  • 多言語サポート

ログ分析(ELKスタック)

  • Logstash/Filebeatでログを収集
  • Elasticsearchでログをインデックスおよび検索
  • Kibanaダッシュボードで可視化
  • 異常を検出するためのアラートを設定

エコマース検索

  • 商品カタログ検索
  • アグリゲーションを使用したファセットナビゲーション
  • オートコンプリートおよび提案
  • パーソナライズされた検索結果

アプリケーションパフォーマンスモニタリング

  • アプリケーションメトリクスをインデックス
  • リアルタイムモニタリングダッシュボード
  • 異常検出
  • パフォーマンストレンド分析

有用なリンク

公式Elasticsearchリソース

関連チートシート&ガイド