Elasticsearch
分散型RESTful検索・分析エンジン。Apache Luceneベースで、リアルタイム検索、ログ分析、ビジネス分析機能を提供。2024年にAGPLv3ライセンスでオープンソース回帰。
Elasticsearch
Elasticsearchは、Apache Luceneベースの分散検索・分析エンジンです。フルテキスト検索、構造化検索、分析機能を備え、大量のデータをリアルタイムで検索・分析できます。RESTful APIを通じてアクセスでき、スケーラブルな分散アーキテクチャを提供します。
主な特徴
分散・スケーラブル
- 自動シャーディングとレプリケーション
- ノードの動的追加・削除対応
- 水平スケーリングによる高可用性
- 自動負荷分散とフェイルオーバー
高速検索・分析
- Luceneベースの高性能インデックス
- リアルタイム検索とNear Real-Time更新
- 複雑なクエリと集計の高速実行
- 分散並列処理による高いスループット
豊富な機能
- フルテキスト検索とファジー検索
- 地理空間データの検索と分析
- 時系列データの効率的な処理
- 機械学習による異常検知
インストール
Ubuntu/Debian
# ElasticsearchのGPGキー追加
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
# リポジトリ追加
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
# インストール
sudo apt update
sudo apt install elasticsearch
# サービス有効化・開始
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
CentOS/RHEL
# リポジトリ設定
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat <<EOF | sudo tee /etc/yum.repos.d/elasticsearch.repo
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
EOF
# インストール
sudo yum install --enablerepo=elasticsearch elasticsearch
# サービス有効化・開始
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
Docker
# 単一ノード構成
docker run --name es01 \
--net elastic \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-it docker.elastic.co/elasticsearch/elasticsearch:8.12.0
# データ永続化付き
docker run --name es01 \
--net elastic \
-p 9200:9200 \
-p 9300:9300 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-v es_data:/usr/share/elasticsearch/data \
-it docker.elastic.co/elasticsearch/elasticsearch:8.12.0
Docker Compose
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.security.enabled=false
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- es_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
- "9300:9300"
networks:
- elastic
volumes:
es_data:
driver: local
networks:
elastic:
driver: bridge
基本設定
elasticsearch.yml
# クラスタ設定
cluster.name: my-application
node.name: node-1
# ネットワーク設定
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
# ディスカバリ設定
discovery.type: single-node
# discovery.seed_hosts: ["host1", "host2"]
# cluster.initial_master_nodes: ["node-1", "node-2"]
# パス設定
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
# メモリ設定
bootstrap.memory_lock: true
# セキュリティ設定
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: false
xpack.security.transport.ssl:
enabled: false
# 監視設定
xpack.monitoring.collection.enabled: true
JVM設定 (jvm.options)
# ヒープサイズ(物理メモリの50%以下)
-Xms2g
-Xmx2g
# GCの詳細ログ
-Xlog:gc*,gc+age=trace,safepoint:gc.log:utctime,pid,tags:filecount=32,filesize=64m
基本操作
クラスタ状態確認
# クラスタヘルス確認
curl -X GET "localhost:9200/_cluster/health?pretty"
# ノード情報確認
curl -X GET "localhost:9200/_nodes?pretty"
# クラスタ設定確認
curl -X GET "localhost:9200/_cluster/settings?pretty"
インデックス管理
# インデックス作成
curl -X PUT "localhost:9200/my-index" -H 'Content-Type: application/json' -d'
{
"settings": {
"index": {
"number_of_shards": 3,
"number_of_replicas": 2
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard"
},
"content": {
"type": "text",
"analyzer": "standard"
},
"timestamp": {
"type": "date"
},
"location": {
"type": "geo_point"
}
}
}
}'
# インデックス一覧
curl -X GET "localhost:9200/_cat/indices?v"
# インデックス削除
curl -X DELETE "localhost:9200/my-index"
ドキュメント操作
# ドキュメント追加
curl -X POST "localhost:9200/my-index/_doc/1" -H 'Content-Type: application/json' -d'
{
"title": "Elasticsearch入門",
"content": "Elasticsearchは強力な検索エンジンです",
"timestamp": "2024-01-15T10:00:00",
"location": {
"lat": 35.6814,
"lon": 139.7670
}
}'
# ドキュメント取得
curl -X GET "localhost:9200/my-index/_doc/1"
# ドキュメント更新
curl -X POST "localhost:9200/my-index/_update/1" -H 'Content-Type: application/json' -d'
{
"doc": {
"content": "Elasticsearchは非常に強力な検索エンジンです"
}
}'
# ドキュメント削除
curl -X DELETE "localhost:9200/my-index/_doc/1"
バルク操作
# バルクインサート
curl -X POST "localhost:9200/_bulk" -H 'Content-Type: application/json' -d'
{"index":{"_index":"my-index","_id":"1"}}
{"title":"記事1","content":"これは最初の記事です","timestamp":"2024-01-15T10:00:00"}
{"index":{"_index":"my-index","_id":"2"}}
{"title":"記事2","content":"これは2番目の記事です","timestamp":"2024-01-15T11:00:00"}
{"index":{"_index":"my-index","_id":"3"}}
{"title":"記事3","content":"これは3番目の記事です","timestamp":"2024-01-15T12:00:00"}
'
検索操作
基本検索
# マッチオール検索
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"match_all": {}
}
}'
# テキスト検索
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"content": "Elasticsearch"
}
}
}'
# フレーズ検索
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"match_phrase": {
"content": "強力な検索エンジン"
}
}
}'
高度な検索
# ブール検索
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{"match": {"title": "Elasticsearch"}}
],
"filter": [
{"range": {"timestamp": {"gte": "2024-01-01"}}}
],
"must_not": [
{"match": {"content": "old"}}
]
}
}
}'
# ファジー検索
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"fuzzy": {
"title": {
"value": "Elasticsarch",
"fuzziness": "AUTO"
}
}
}
}'
# ワイルドカード検索
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"wildcard": {
"title": "*search*"
}
}
}'
集計クエリ
# 基本集計
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"daily_posts": {
"date_histogram": {
"field": "timestamp",
"calendar_interval": "1d"
}
},
"avg_score": {
"avg": {
"field": "score"
}
}
}
}'
# ネストした集計
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category.keyword"
},
"aggs": {
"avg_views": {
"avg": {
"field": "views"
}
}
}
}
}
}'
クラスタ構成
3ノードクラスタ設定
# ノード1 (elasticsearch.yml)
cluster.name: production-cluster
node.name: node-1
node.roles: ["master", "data", "ingest"]
network.host: 192.168.1.10
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
# ノード2 (elasticsearch.yml)
cluster.name: production-cluster
node.name: node-2
node.roles: ["master", "data", "ingest"]
network.host: 192.168.1.11
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
# ノード3 (elasticsearch.yml)
cluster.name: production-cluster
node.name: node-3
node.roles: ["master", "data", "ingest"]
network.host: 192.168.1.12
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
専用ノード構成
# マスターノード
node.roles: ["master"]
# データノード
node.roles: ["data", "data_content", "data_hot", "data_warm", "data_cold"]
# Ingestノード
node.roles: ["ingest"]
# 検索専用ノード
node.roles: ["search"]
# 機械学習ノード
node.roles: ["ml", "remote_cluster_client"]
インデックス設定
マッピング定義
# 詳細マッピング設定
curl -X PUT "localhost:9200/products" -H 'Content-Type: application/json' -d'
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "keyword",
"filter": ["lowercase", "stop"]
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"description": {
"type": "text",
"analyzer": "my_analyzer"
},
"price": {
"type": "double"
},
"created_date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"tags": {
"type": "keyword"
},
"location": {
"type": "geo_point"
},
"metadata": {
"type": "object",
"properties": {
"category": {"type": "keyword"},
"brand": {"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,
"number_of_replicas": 1,
"index.lifecycle.name": "logs_policy"
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date"
},
"level": {
"type": "keyword"
},
"message": {
"type": "text"
},
"source": {
"type": "keyword"
}
}
}
}
}'
パフォーマンス最適化
検索パフォーマンス
# プロファイル有効化
curl -X GET "localhost:9200/my-index/_search" -H 'Content-Type: application/json' -d'
{
"profile": true,
"query": {
"match": {
"content": "Elasticsearch"
}
}
}'
# 検索実行計画確認
curl -X GET "localhost:9200/my-index/_validate/query?explain" -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{"match": {"title": "search"}},
{"range": {"timestamp": {"gte": "2024-01-01"}}}
]
}
}
}'
インデックス最適化
# インデックス最適化
curl -X POST "localhost:9200/my-index/_forcemerge?max_num_segments=1"
# インデックス統計確認
curl -X GET "localhost:9200/my-index/_stats"
# セグメント情報確認
curl -X GET "localhost:9200/_cat/segments/my-index?v"
キャッシュ設定
# elasticsearch.yml
indices.queries.cache.size: 10%
indices.fielddata.cache.size: 40%
indices.requests.cache.size: 1%
監視とメンテナンス
ヘルスチェック
# クラスタヘルス詳細
curl -X GET "localhost:9200/_cluster/health?level=indices&pretty"
# ノード統計
curl -X GET "localhost:9200/_nodes/stats?pretty"
# インデックス統計
curl -X GET "localhost:9200/_stats?pretty"
# タスク確認
curl -X GET "localhost:9200/_tasks?detailed&pretty"
ログ分析
# スローログ設定
curl -X PUT "localhost:9200/my-index/_settings" -H 'Content-Type: application/json' -d'
{
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.query.debug": "2s",
"index.search.slowlog.threshold.query.trace": "500ms",
"index.indexing.slowlog.threshold.index.warn": "10s",
"index.indexing.slowlog.threshold.index.info": "5s"
}'
バックアップ・リストア
# スナップショットリポジトリ作成
curl -X PUT "localhost:9200/_snapshot/my_backup" -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" -H 'Content-Type: application/json' -d'
{
"indices": "my-index",
"ignore_unavailable": true,
"include_global_state": false
}'
# スナップショットからリストア
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "my-index",
"ignore_unavailable": true,
"include_global_state": false
}'
セキュリティ設定
# 基本認証有効化
bin/elasticsearch-setup-passwords auto
# APIキー作成
curl -X POST "localhost:9200/_security/api_key" -u elastic:password -H 'Content-Type: application/json' -d'
{
"name": "my-api-key",
"role_descriptors": {
"my_role": {
"cluster": ["monitor"],
"indices": [
{
"names": ["my-index"],
"privileges": ["read", "write"]
}
]
}
}
}'
Elasticsearchは、その柔軟性と高性能により、ログ分析、検索システム、リアルタイム分析、ビジネスインテリジェンスなど様々な用途で活用されています。適切な設計と設定により、大規模なデータでも高速な検索・分析を実現できます。