【実践】 ElasticSearch × RAG 入門 (1) – RAGではRDB?Elasticsearch?初心者でもわかる選び方と違い

1. Elasticsearchの基本概念

RAGで検索エンジン + DBを構築するとき、

🤔「jsonでデータを管理して、検索はfaissを使って、前処理は…」

のような構成を1つ1つ実装していた時代はありませんでしたか。

Welcome to Faiss Documentation — Faiss documentation


ElasticSearchはこれらを簡単に扱えるよう抽象化しているため、複雑な検索機能を少ない労力で実現できるという嬉しさがあります。Elasticsearchは大量のデータを高速に検索・分析することができます。

ElasticSearchの主な用語は次のとおりです。

ElasticSearchの要素説明RDBとの対応
インデックス (Index)データを格納する場所データベース
ドキュメント (Document)データの単位行(レコード)
フィールド (Field)ドキュメント内のデータ項目列(カラム)
マッピング (Mapping)フィールドのデータ型やインデックス方法を定義するスキーマテーブル定義
シャード (Shard)インデックスを分割した単位で、分散処理の基本要素
ノード (Node)Elasticsearchを実行する個々のサーバー
クラスター (Cluster)複数のノードの集合体

2. ElasticsearchとRDBの違い:どんな時に使い分ける?

ElasticsearchとRDB(リレーショナルデータベース)は、データの見方が根本的に異なります。

RDBは表(テーブル)でデータを管理し、正規化されたスキーマを持ちます。
対してElasticsearchはドキュメント指向で、JSONライクな形式でデータを保存します。
スキーマは柔軟で、途中で変更も容易です。

それぞれの得意分野を見てみましょう:

  • RDBの得意なこと:トランザクション処理、複雑な結合操作、一貫性の高いデータ管理
  • Elasticsearchの得意なこと:全文検索、あいまい検索、大量データの高速検索、リアルタイム分析
ユースケースRDBElasticsearch
「赤い靴」で商品を検索(-) WHERE color = '赤' AND category = '靴' のような厳密な条件指定のみ(+) 「赤っぽい」「赤系」や「シューズ」「ブーツ」なども含めた関連性の高い結果が得られる
ブログ記事の全文検索(-) LIKEを使った検索は遅く、部分一致に限定される(+) 関連性の高い記事を瞬時に検索でき、類義語も考慮される
ECサイトの商品カタログ検索(-) 複雑な絞り込み条件を組み合わせると処理が重くなる(+) ファセット検索で複数条件を組み合わせても高速に結果が得られる
SNSの投稿分析(-) 感情分析や傾向把握のための集計が複雑で遅い(+) テキスト分析機能で感情や話題のトレンドを簡単に抽出できる
在庫管理システム(+) 正確な数値管理と複数テーブル間の整合性維持に強い(-) リアルタイム性は高いが、複雑な関連データの整合性管理は苦手

3. インストールと基本設定

Elasticsearchのインストールと基本設定の手順は次のとおりです。

(1) Docker と Docker Compose がインストールされていることを確認

docker --version
docker-compose --version

(2) プロジェクトディレクトリを作成

mkdir elasticsearch-demo
cd elasticsearch-demo

(3) docker-compose.yml ファイルを作成

version: '3.8'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.18.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es-data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
      - "9300:9300"
    networks:
      - elastic

  kibana:
    image: docker.elastic.co/kibana/kibana:8.18.0
    container_name: kibana
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
    networks:
      - elastic

volumes:
  es-data:
    driver: local

(4) Docker Compose でコンテナを起動

docker-compose up -d

上記のコマンドで、ElasticsearchとKibanaのコンテナが起動します。「-d」オプションでバックグラウンド実行します。

(5) 動作確認
起動から少し時間をおいてから、以下のコマンドでElasticsearchの状態を確認します:

curl http://localhost:9200

成功すると、以下のようなJSONレスポンスが返ってきます:

{
  "name" : "elasticsearch",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "...",
  "version" : {
    "number" : "8.18.0",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "...",
    "build_date" : "...",
    "build_snapshot" : false,
    "lucene_version" : "...",
    "minimum_wire_compatibility_version" : "...",
    "minimum_index_compatibility_version" : "..."
  },
  "tagline" : "You Know, for Search"
}

4. Elasticsearchのアナライザーとテキスト処理

Elasticsearchの強力な機能の一つが「アナライザー」です。アナライザーはテキストを検索に最適な形に変換する処理を担当します。

アナライザーは主に次の3つの要素で構成されています:

  • 文字フィルター:入力テキストの前処理(HTMLタグ除去など)
  • トークナイザー:テキストを単語(トークン)に分割
  • トークンフィルター:トークンの加工(小文字化、ステミング、同義語処理など)

日本語のような言語では形態素解析が特に重要です。例えば「東京駅前の喫茶店」という検索語は、適切なアナライザーを使うと「東京」「駅」「前」「喫茶」「店」などのトークンに分解されます。

アナライザーの設定例:

PUT /my-index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_ja_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer",
          "filter": ["kuromoji_baseform", "lowercase"]
        }
      }
    }
  }
}

このような設定により、「走る」で検索すると「走った」「走れ」なども検索結果に含めることができます。これがRDBの単純な「LIKE ‘%走る%’」検索との大きな違いです。

※ Analyzerは次回以降に詳しく紹介します。今は「こんな機能があるのかー」で大丈夫です🙆🏻

5. 実用的な検索クエリと活用例

Elasticsearchの基本的な検索クエリと活用例を見ていきましょう。

(1) 基本的なフルテキスト検索

GET /my-index/_search
{
  "query": {
    "match": {
      "description": "快適 オフィス"
    }
  }
}

これは「快適」または「オフィス」という単語を含むドキュメントを検索し、両方含むものを上位に表示します。

(2) フレーズ検索

GET /my-index/_search
{
  "query": {
    "match_phrase": {
      "description": "快適なオフィス環境"
    }
  }
}

単語の順序も考慮した検索ができます。

(3) 複合条件検索

GET /my-index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "category": "オフィス家具" } }
      ],
      "should": [
        { "match": { "description": "木製" } },
        { "match": { "description": "エルゴノミクス" } }
      ],
      "must_not": [
        { "match": { "availability": "在庫切れ" } }
      ],
      "filter": [
        { "range": { "price": { "lte": 50000 } } }
      ]
    }
  }
}

活用例として、ECサイトでの商品検索があります。ユーザーが「黒 ノートパソコン 軽量」と入力した場合、色、カテゴリ、特徴などを組み合わせて最適な検索結果を返せます。また、ユーザーの行動履歴などから「軽量」の重要度を上げるなど、検索結果のパーソナライズも可能です。

おわりに

次回は実際に「ElasticSearch」のインデックス(データベース)を作成して、柔軟な検索の実践をしていきます。

【実践】 ElasticSearch × RAG 入門 (2) – ElasticSearchのRAG用 データベースの作り方
第1回ではElasticSearchの簡単な概要について説明しました。この記事では夏目漱石:「坊っちゃん」のElasticSearch Index(データベース)を作成して、検索できるようになるまでを解説します。1. ElasticSear...

コメント