データベース
OpenSearch
概要
OpenSearchは、AWS主導で開発された分散検索・分析エンジンです。Elasticsearchからフォークされたオープンソースプロジェクトで、Apache 2.0ライセンスの下で完全に自由に利用できます。高速な全文検索、リアルタイム分析、機械学習機能を提供し、ログ分析、メトリクス監視、アプリケーション検索など幅広い用途に対応します。
詳細
OpenSearchは2021年にElasticsearchのライセンス変更に対応してAWSが開始したプロジェクトです。2024年後半にはLinux Foundationの下でOpenSearch Software Foundation(OSSF)が設立され、中立的なガバナンスの下で開発が進められています。Elasticsearch 7.10.2をベースとしながら、独自の機能拡張と最適化を継続的に実施しています。
主要特徴
- 高速検索: 最大6倍の性能向上(初期バージョン比)
- ベクトル検索: Facebook FAISS統合による高性能セマンティック検索
- ハイブリッド検索: キーワード検索とベクトル検索の並列実行
- OpenSearch Dashboards: データ可視化と管理UI
- セキュリティ: 細粒度アクセス制御とマルチテナント対応
- アラート: リアルタイム監視とアラート機能
- Data Prepper: 強化されたデータ取り込みパイプライン
- Remote-backed storage: クラウドストレージへの直接インデックス作成
- Segment replication: 25%のデータ取り込み性能向上
- SIMD最適化: ハードウェアアクセラレーション対応
アーキテクチャ
- 分散システム: マルチノードクラスター対応
- RESTful API: Elasticsearch互換API提供
- プラグインシステム: 豊富な拡張機能
- OpenSearch Dashboards: Kibana互換の可視化ツール
- マルチテナンシー: テナント間の完全分離
- クロスクラスター: 複数クラスター間の検索・レプリケーション
メリット・デメリット
メリット
- 完全オープンソース: Apache 2.0ライセンスで商用制限なし
- Elasticsearch互換: 既存システムからの移行が容易
- 高性能: 最新最適化により大幅な性能向上
- 豊富な機能: 検索、分析、可視化、ML機能を統合
- 強固なセキュリティ: エンタープライズレベルのセキュリティ機能
- アクティブ開発: 1,400以上の貢献者による活発な開発
- AWS統合: AWSサービスとの緊密な連携
- コスト効率: クラウドストレージとの統合によるコスト削減
デメリット
- 比較的新しい: Elasticsearchと比べエコシステムが発展途上
- 移行複雑性: Elasticsearchからの移行時に一部機能差異
- 学習コスト: 新機能や独自拡張の学習が必要
- プラグイン制限: Elasticsearchの一部プラグインが利用不可
- 企業サポート: 商用サポートはAWS経由に限定的
主要リンク
書き方の例
インストール・セットアップ
# Dockerで起動(シングルノード)
docker run -d \
--name opensearch-node1 \
-p 9200:9200 -p 9600:9600 \
-e "discovery.type=single-node" \
-e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=MyStrongPassword123!" \
opensearchproject/opensearch:latest
# Docker Composeでクラスター構築
cat > docker-compose.yml << EOF
version: '3'
services:
opensearch-node1:
image: opensearchproject/opensearch:latest
container_name: opensearch-node1
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node1
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
- "OPENSEARCH_INITIAL_ADMIN_PASSWORD=MyStrongPassword123!"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data1:/usr/share/opensearch/data
ports:
- 9200:9200
- 9600:9600
networks:
- opensearch-net
opensearch-node2:
image: opensearchproject/opensearch:latest
container_name: opensearch-node2
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node2
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
- "OPENSEARCH_INITIAL_ADMIN_PASSWORD=MyStrongPassword123!"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data2:/usr/share/opensearch/data
networks:
- opensearch-net
opensearch-dashboards:
image: opensearchproject/opensearch-dashboards:latest
container_name: opensearch-dashboards
ports:
- 5601:5601
expose:
- "5601"
environment:
OPENSEARCH_HOSTS: '["https://opensearch-node1:9200","https://opensearch-node2:9200"]'
networks:
- opensearch-net
volumes:
opensearch-data1:
opensearch-data2:
networks:
opensearch-net:
EOF
docker-compose up -d
# 起動確認
curl -k -u admin:MyStrongPassword123! https://localhost:9200
基本操作(CRUD)
# インデックス作成
curl -k -X PUT "https://localhost:9200/products" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "standard" },
"brand": { "type": "keyword" },
"category": { "type": "keyword" },
"price": { "type": "double" },
"description": { "type": "text" },
"tags": { "type": "keyword" },
"created_at": { "type": "date" }
}
}
}'
# ドキュメント追加
curl -k -X POST "https://localhost:9200/products/_doc/1" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"name": "iPhone 15",
"brand": "Apple",
"category": "スマートフォン",
"price": 124800,
"description": "最新のiPhone、A17 Proチップ搭載",
"tags": ["smartphone", "apple", "mobile"],
"created_at": "2024-01-15"
}'
# バルクインサート
curl -k -X POST "https://localhost:9200/products/_bulk" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '
{"index": {"_id": "2"}}
{"name": "MacBook Pro", "brand": "Apple", "category": "ノートPC", "price": 248800, "description": "M3チップ搭載の高性能ノートパソコン", "tags": ["laptop", "apple"], "created_at": "2024-01-10"}
{"index": {"_id": "3"}}
{"name": "Galaxy S24", "brand": "Samsung", "category": "スマートフォン", "price": 98800, "description": "Android搭載の高性能スマートフォン", "tags": ["smartphone", "samsung", "android"], "created_at": "2024-01-20"}
'
# ドキュメント取得
curl -k -X GET "https://localhost:9200/products/_doc/1" \
-u admin:MyStrongPassword123!
# ドキュメント更新
curl -k -X POST "https://localhost:9200/products/_update/1" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"doc": {
"price": 119800,
"description": "最新のiPhone、A17 Proチップ搭載(価格改定)"
}
}'
# ドキュメント削除
curl -k -X DELETE "https://localhost:9200/products/_doc/3" \
-u admin:MyStrongPassword123!
検索クエリ
# シンプル検索
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"name": "iPhone"
}
}
}'
# 複合検索
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"query": {
"bool": {
"must": [
{ "match": { "description": "高性能" } }
],
"filter": [
{ "term": { "brand": "Apple" } },
{ "range": { "price": { "gte": 100000, "lte": 300000 } } }
]
}
},
"sort": [
{ "price": { "order": "asc" } }
],
"size": 10,
"from": 0
}'
# ファジー検索
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"query": {
"fuzzy": {
"name": {
"value": "iPhon",
"fuzziness": "AUTO"
}
}
}
}'
# ハイライト付き検索
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"query": {
"multi_match": {
"query": "Apple",
"fields": ["name", "description"]
}
},
"highlight": {
"fields": {
"name": {},
"description": {}
},
"pre_tags": ["<mark>"],
"post_tags": ["</mark>"]
}
}'
集約(Aggregations)
# 基本的な集約
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"size": 0,
"aggs": {
"brands": {
"terms": {
"field": "brand",
"size": 10
}
},
"avg_price": {
"avg": {
"field": "price"
}
},
"price_stats": {
"stats": {
"field": "price"
}
}
}
}'
# ネストした集約
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"size": 0,
"aggs": {
"brands": {
"terms": {
"field": "brand"
},
"aggs": {
"avg_price_per_brand": {
"avg": {
"field": "price"
}
},
"categories": {
"terms": {
"field": "category"
}
}
}
}
}
}'
# 範囲集約
curl -k -X GET "https://localhost:9200/products/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 50000 },
{ "from": 50000, "to": 150000 },
{ "from": 150000, "to": 300000 },
{ "from": 300000 }
]
}
}
}
}'
インデックス管理・最適化
# インデックス情報確認
curl -k -X GET "https://localhost:9200/products/_settings" \
-u admin:MyStrongPassword123!
curl -k -X GET "https://localhost:9200/products/_mapping" \
-u admin:MyStrongPassword123!
# インデックス統計
curl -k -X GET "https://localhost:9200/products/_stats" \
-u admin:MyStrongPassword123!
# インデックステンプレート作成
curl -k -X PUT "https://localhost:9200/_index_template/products_template" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"index_patterns": ["products*"],
"template": {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"refresh_interval": "5s"
},
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "standard" },
"brand": { "type": "keyword" },
"category": { "type": "keyword" },
"price": { "type": "double" },
"created_at": { "type": "date" }
}
}
}
}'
# インデックス最適化
curl -k -X POST "https://localhost:9200/products/_forcemerge?max_num_segments=1" \
-u admin:MyStrongPassword123!
# インデックス再作成
curl -k -X POST "https://localhost:9200/_reindex" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"source": {
"index": "products"
},
"dest": {
"index": "products_v2"
}
}'
JavaScript Client
// OpenSearchクライアントの設定
import { Client } from '@opensearch-project/opensearch'
const client = new Client({
node: 'https://localhost:9200',
auth: {
username: 'admin',
password: 'MyStrongPassword123!'
},
ssl: {
rejectUnauthorized: false // 開発環境のみ
}
})
// インデックス作成
await client.indices.create({
index: 'products',
body: {
settings: {
number_of_shards: 1,
number_of_replicas: 1
},
mappings: {
properties: {
name: { type: 'text' },
brand: { type: 'keyword' },
category: { type: 'keyword' },
price: { type: 'double' },
description: { type: 'text' }
}
}
}
})
// ドキュメント追加
await client.index({
index: 'products',
id: '1',
body: {
name: 'iPhone 15',
brand: 'Apple',
category: 'スマートフォン',
price: 124800,
description: '最新のiPhone、A17 Proチップ搭載'
}
})
// バルクインサート
const body = [
{ index: { _index: 'products', _id: '2' } },
{ name: 'MacBook Pro', brand: 'Apple', category: 'ノートPC', price: 248800 },
{ index: { _index: 'products', _id: '3' } },
{ name: 'Galaxy S24', brand: 'Samsung', category: 'スマートフォン', price: 98800 }
]
await client.bulk({ body })
// 検索実行
const searchResponse = await client.search({
index: 'products',
body: {
query: {
bool: {
must: [
{ match: { description: '高性能' } }
],
filter: [
{ term: { brand: 'Apple' } },
{ range: { price: { gte: 100000 } } }
]
}
},
sort: [
{ price: { order: 'asc' } }
],
size: 10
}
})
console.log('検索結果:', searchResponse.body.hits.hits)
// 集約
const aggregationResponse = await client.search({
index: 'products',
body: {
size: 0,
aggs: {
brands: {
terms: { field: 'brand' }
},
avg_price: {
avg: { field: 'price' }
}
}
}
})
console.log('集約結果:', aggregationResponse.body.aggregations)
ベクトル検索・AI機能
# ベクトル検索用インデックス作成
curl -k -X PUT "https://localhost:9200/documents" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"settings": {
"index": {
"knn": true,
"knn.algo_param.ef_search": 100
}
},
"mappings": {
"properties": {
"title": { "type": "text" },
"content": { "type": "text" },
"vector_field": {
"type": "knn_vector",
"dimension": 768,
"method": {
"name": "hnsw",
"space_type": "l2",
"engine": "faiss",
"parameters": {
"ef_construction": 128,
"m": 24
}
}
}
}
}
}'
# ベクトル付きドキュメント追加
curl -k -X POST "https://localhost:9200/documents/_doc/1" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"title": "OpenSearchの使い方",
"content": "OpenSearchは強力な検索エンジンです",
"vector_field": [0.1, 0.2, 0.3, /* ... 768次元のベクトル */]
}'
# k-NN検索
curl -k -X GET "https://localhost:9200/documents/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"size": 5,
"query": {
"knn": {
"vector_field": {
"vector": [0.1, 0.2, 0.3, /* ... 768次元のクエリベクトル */],
"k": 5
}
}
}
}'
# ハイブリッド検索(テキスト + ベクトル)
curl -k -X GET "https://localhost:9200/documents/_search" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"size": 10,
"query": {
"hybrid": {
"queries": [
{
"match": {
"content": "検索エンジン"
}
},
{
"knn": {
"vector_field": {
"vector": [0.1, 0.2, 0.3, /* ... */],
"k": 5
}
}
}
]
}
}
}'
セキュリティ設定
# ユーザー作成
curl -k -X PUT "https://localhost:9200/_plugins/_security/api/internalusers/developer" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"password": "DeveloperPassword123!",
"opendistro_security_roles": ["readall"],
"backend_roles": ["developer"],
"attributes": {
"department": "engineering"
}
}'
# ロール作成
curl -k -X PUT "https://localhost:9200/_plugins/_security/api/roles/products_reader" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"cluster_permissions": ["cluster_composite_ops"],
"index_permissions": [
{
"index_patterns": ["products*"],
"allowed_actions": ["read", "search"]
}
]
}'
# テナント作成
curl -k -X PUT "https://localhost:9200/_plugins/_security/api/tenants/development" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"description": "Development environment tenant"
}'
# ロールマッピング
curl -k -X PUT "https://localhost:9200/_plugins/_security/api/rolesmapping/products_reader" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"backend_roles": ["developer"],
"users": ["developer"]
}'
監視・アラート
# モニター作成
curl -k -X POST "https://localhost:9200/_plugins/_alerting/monitors" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"type": "monitor",
"name": "High Price Products Monitor",
"enabled": true,
"schedule": {
"period": {
"interval": 5,
"unit": "MINUTES"
}
},
"inputs": [
{
"search": {
"indices": ["products"],
"query": {
"query": {
"range": {
"price": {
"gte": 200000
}
}
}
}
}
}
],
"triggers": [
{
"name": "High price trigger",
"severity": "1",
"condition": {
"script": {
"source": "ctx.results[0].hits.total.value > 5"
}
},
"actions": [
{
"name": "Send email",
"destination_id": "email_destination_id",
"message_template": {
"source": "発見された高額商品: {{ctx.results.0.hits.total.value}}件"
}
}
]
}
]
}'
# 宛先設定(メール)
curl -k -X POST "https://localhost:9200/_plugins/_alerting/destinations" \
-u admin:MyStrongPassword123! \
-H 'Content-Type: application/json' \
-d '{
"name": "email-destination",
"type": "email",
"email": {
"email_account_id": "default_email",
"recipients": ["[email protected]"],
"subject": "OpenSearch Alert",
"message": "アラートが発生しました"
}
}'
本番環境設定
# opensearch.yml
cluster.name: production-cluster
node.name: opensearch-node-1
path.data: /var/lib/opensearch
path.logs: /var/log/opensearch
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["opensearch-node-1", "opensearch-node-2", "opensearch-node-3"]
cluster.initial_cluster_manager_nodes: ["opensearch-node-1", "opensearch-node-2", "opensearch-node-3"]
# メモリ設定
bootstrap.memory_lock: true
# セキュリティ設定
plugins.security.ssl.transport.enforce_hostname_verification: false
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: /path/to/cert.pem
plugins.security.ssl.http.pemkey_filepath: /path/to/key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: /path/to/ca.pem
# パフォーマンス設定
indices.memory.index_buffer_size: 20%
indices.memory.min_index_buffer_size: 96mb
thread_pool.search.queue_size: 10000
thread_pool.write.queue_size: 1000
# ロギング設定
logger.org.opensearch: INFO
logger.org.opensearch.index.search.slowlog: WARN, index_search_slow_log_file
logger.org.opensearch.index.indexing.slowlog: WARN, index_indexing_slow_log_file