GitHub概要

elastic/elasticsearch

Free and Open Source, Distributed, RESTful Search Engine

スター73,370
ウォッチ2,665
フォーク25,351
作成日:2010年2月8日
言語:Java
ライセンス:Other

トピックス

elasticsearchjavasearch-engine

スター履歴

elastic/elasticsearch Star History
データ取得日時: 2025/7/30 02:37

データベース

Elasticsearch + Vector Search

概要

Elasticsearchは、元々はテキスト検索に特化した分散型検索・分析エンジンとして知られていますが、バージョン7.3以降でk-NN(k-nearest neighbor)検索機能を追加し、ベクトル検索にも対応しました。既存のElasticsearchインフラストラクチャに統合できるため、テキスト検索とベクトル検索を組み合わせたハイブリッド検索が可能です。

詳細

Elasticsearchは2010年にElastic社によって開発され、現在では世界中で最も広く使用されている検索エンジンの一つです。ベクトル検索機能の追加により、従来のテキスト検索に加えて、画像検索、類似文書検索、推薦システムなど、機械学習ベースのアプリケーションにも対応できるようになりました。

Elasticsearchのベクトル検索の主な特徴:

  • 既存のElasticsearchクラスタでベクトル検索が可能
  • k-NNアルゴリズムによる高速な類似性検索
  • HNSWアルゴリズムのサポート(v8.0以降)
  • テキスト検索とベクトル検索のハイブリッド検索
  • スケーラブルな分散アーキテクチャ
  • RESTful APIによる簡単な統合
  • Kibanaによる可視化とモニタリング
  • 豊富なプラグインエコシステム
  • マルチ言語対応のクライアントライブラリ

ベクトル検索の実装

  • dense_vectorフィールドタイプでベクトルデータを格納
  • script_scoreクエリやknnクエリによる類似性検索
  • コサイン類似度、ドット積、L2距離などのメトリクスをサポート
  • インデックス時の次元数制限(最大2048次元)

メリット・デメリット

メリット

  • 既存インフラの活用: すでにElasticsearchを使用している場合、追加の導入コストが低い
  • ハイブリッド検索: テキスト検索とベクトル検索を組み合わせた高度な検索が可能
  • 成熟したエコシステム: 豊富なツール、プラグイン、ドキュメントが利用可能
  • 高いスケーラビリティ: 分散アーキテクチャによる水平スケーリング
  • エンタープライズ機能: セキュリティ、モニタリング、バックアップなどの機能が充実
  • 統合の容易さ: RESTful APIにより様々なアプリケーションと簡単に統合

デメリット

  • ベクトル特化ではない: 専用のベクトルデータベースと比較してパフォーマンスが劣る場合がある
  • 次元数の制限: 最大2048次元までという制限がある
  • メモリ消費: 大規模なベクトルデータでメモリ使用量が増大
  • ライセンスコスト: 高度な機能はElastic Licenseで提供され、商用利用に制限がある
  • 学習コスト: Elasticsearchの概念を理解する必要がある

主要リンク

書き方の例

インストール・セットアップ

# Dockerでの実行
docker run -d --name elasticsearch \
  -p 9200:9200 -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  docker.elastic.co/elasticsearch/elasticsearch:8.11.3

# Elasticsearchクライアントのインストール(Python)
pip install elasticsearch

# Node.js
npm install @elastic/elasticsearch

ベクトル検索の基本操作

from elasticsearch import Elasticsearch
import numpy as np

# 接続
es = Elasticsearch(['http://localhost:9200'])

# インデックスの作成(ベクトルフィールド付き)
index_mapping = {
    "mappings": {
        "properties": {
            "title": {"type": "text"},
            "content": {"type": "text"},
            "embedding": {
                "type": "dense_vector",
                "dims": 768,
                "index": True,
                "similarity": "cosine"
            }
        }
    }
}

es.indices.create(index="documents", body=index_mapping)

# ドキュメントの追加
doc = {
    "title": "Elasticsearchベクトル検索",
    "content": "Elasticsearchでベクトル検索を実装する方法",
    "embedding": np.random.rand(768).tolist()
}

es.index(index="documents", body=doc)

# k-NN検索
query_vector = np.random.rand(768).tolist()

search_query = {
    "knn": {
        "field": "embedding",
        "query_vector": query_vector,
        "k": 10,
        "num_candidates": 100
    }
}

results = es.search(index="documents", body=search_query)

ハイブリッド検索

# テキスト検索とベクトル検索の組み合わせ
hybrid_query = {
    "query": {
        "script_score": {
            "query": {
                "match": {
                    "content": "ベクトル検索"
                }
            },
            "script": {
                "source": "cosineSimilarity(params.query_vector, 'embedding') + 1.0",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    }
}

results = es.search(index="documents", body=hybrid_query)

HNSWインデックスの使用(v8.0以降)

# HNSWアルゴリズムを使用したインデックス
hnsw_mapping = {
    "mappings": {
        "properties": {
            "embedding": {
                "type": "dense_vector",
                "dims": 768,
                "index": True,
                "similarity": "l2_norm",
                "index_options": {
                    "type": "hnsw",
                    "m": 16,
                    "ef_construction": 200
                }
            }
        }
    }
}

es.indices.create(index="hnsw_index", body=hnsw_mapping)

バッチ処理

from elasticsearch.helpers import bulk

# 複数のドキュメントを一括インデックス
documents = []
for i in range(1000):
    doc = {
        "_index": "documents",
        "_source": {
            "title": f"Document {i}",
            "content": f"Content of document {i}",
            "embedding": np.random.rand(768).tolist()
        }
    }
    documents.append(doc)

bulk(es, documents)

集約とフィルタリング

# フィルタリング付きベクトル検索
filtered_search = {
    "knn": {
        "field": "embedding",
        "query_vector": query_vector,
        "k": 10,
        "num_candidates": 100,
        "filter": {
            "term": {
                "category": "technology"
            }
        }
    }
}

results = es.search(index="documents", body=filtered_search)