Closed25

Elastic Searchをざっくり理解する2

ハガユウキハガユウキ
  • 全文検索とは、複数文書を対象として、特定の文字列が含まれる文章を検索すること

  • 全文検索は大きく分けて2種類あって、逐次検索(grepコマンドなど)と、索引型検索の2種類ある。

    • 逐次検索はシンプルではあるが、検索の対象となる文書の数や量が大きいと現実的な時間内に処理が完了しない
    • 索引型検索は事前に索引(= インデックス)を構成しておいて、検索時にはこのインデックスをもとにキーから目的の文章を探す。
    • インデックスを作るのがめんどくさいが、検索対象のサイズが大きいときは索引型検索の方が効率的に検索できる。
  • ESは索引型検索を行うソフトウェア。

https://ja.wikipedia.org/wiki/全文検索

ハガユウキハガユウキ

https://www.elastic.co/docs/solutions/search/full-text/how-full-text-works

ElasticSearchにドキュメントを投入すると、ドキュメントのフィールドのテキストがアナライザーによってトークン化(特定のルールに従って分離したもの)して、それらのトークンとそれらのトークンを含む文書をマッピングしたインデックスが作られる(この種類のインデックスを転置インデックスと呼ぶ)。
https://ja.wikipedia.org/wiki/転置インデックス

この転置インデックスを使用して文書を検索するから、検索スピードがはやい。

ハガユウキハガユウキ

The index option controls whether field values are indexed. It accepts true or false and defaults to true.

indexオプションは、フィールド値にインデックスを付けるかどうかを制御します。trueかfalseを受け取り、デフォルトはtrueです。

デフォルトでは、各フィールドに対してインデックスが作られる
そのため、クエリを実行する際には、基本的にはフィールド単位で検索をする

https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/mapping-index

ハガユウキハガユウキ

The analyzer parameter specifies the analyzer used for text analysis when indexing or searching a text field.

analyzerパラメータは、テキストフィールドのインデックス作成や検索時にテキスト解析に使用する解析器を指定します。

text型の値だけアナライザーによってトークン化される。keyword型の値はトークン化されると検索結果として出てきて欲しくないものが出てきてしまい、バイアスになるので、keyword型は完全一致での検索の用途で使われる

そして、テキストフィールドの検索の時だけ、アナライザーでトークン化される。

https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/analyzer

ハガユウキハガユウキ

マルチフィールド型という特殊なデータ型があって、これを使うと1つのフィールドに同時に複数のデータ型を定義できる

  • あるフィールドに対して、text型による形態素解析された単語単位の検索をしたい
  • あるフィールドに対して、keyword型による完全一致検索をしたい

上の2つの要件を満たす際に、マルチフィールド型が必要になってくる。

https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/multi-fields
https://www.elastic.co/jp/blog/how-to-implement-japanese-full-text-search-in-elasticsearch

ハガユウキハガユウキ

This version of Elastic® is built on Apache Lucene 9.9,

ESはApatch Luceneをベースに作られている

https://www.elastic.co/jp/blog/whats-new-elastic-search-8-12-0

ESでは、検索機能のコアの部分はApatch Luceneが担っていていて、それにプラスしてREST API経由での操作や分散処理対応できるような仕組みを提供している。
(LuceneはJavaを書いて実行する必要があるので、ESを使うと、REST APIのインターフェースでLuceneを操作できるから、そこが便利)

ハガユウキハガユウキ

ESでインデックスを作成すると、シャードと呼ばれる単位で分割されて、ノードに配置される。
(デフォルトのシャード数は1)

https://www.elastic.co/jp/blog/what-is-an-elasticsearch-index#:~:text=て済みます。-,Elasticsearchが分散システムでスケーラビリティを実現するしくみ,-インデックスには

シャードに分割して各ノードに配置するメリット

  • シャードを複数のノードに分散して配置することで、ノード1台あたりのリソース負荷を減らすことができる(= シャーディング or パーティショニングと呼ばれている)
    (格納するデータ量が増大するにつれて、サーバーのCPU、メモリ、I/O負荷が上昇して、性能が徐々に低下することがある)
  • インデックスの検索が分散されて並列で実行できるので、検索性能が向上する

また、可用性を高める仕組みとして、各シャードに対して、レプリカと呼ばれる複製を1つ以上持たせることができる(デフォルトでは各シャードに対して1つのレプリカが自動的に複製される)。このレプリカを使うことで、シャードを保持するノードが1台ダウンしても、レプリカをもとに自動復旧することができるようになる。

ハガユウキハガユウキ

プライマリーシャードとは、レプリカシャードの元になったオリジナルのシャードのこと

ハガユウキハガユウキ

シャードとは、インデックスのデータを一定数に分割した各部分のこと。

ハガユウキハガユウキ

Logstashは、データ、ログを収集・加工・転送するためのデータ処理パイプラインを実現するツールです。
Logstashは「Input」「Filter」「Output」の3つの要素から構成されます

ハガユウキハガユウキ

ESにおいてドキュメントを保存する場所がインデックス。
ドキュメントがそのままインデックスに格納されているわけではなくて、アナライザーで単語分割したりして、転置インデックス情報を構成した上で、保存されている。

ハガユウキハガユウキ

特定idのドキュメントをreadするだけなら、queryキーとかいらない。ただAPIを叩けばいい。
_search APIなどの検索APIを叩く際にqueryキーをリクエストボディに指定する必要がある。

検索クエリは省略版と、明示的に書いた場合の2パターンある

# 明示的に書いた場合
curl -X GET "http://localhost:9200/articles/_search" -H "Content-Type: application/json" -d '{"query":{"match":{"pdf_attachments.pages.content":{"query":"test_content2"}}}}' | jq

# 省略して書いた場合
curl -X GET "http://localhost:9200/articles/_search" -H "Content-Type: application/json" -d '{"query":{"match":{"pdf_attachments.pages.content":"test_content2"}}}' | jq
ハガユウキハガユウキ

このコマンド使えば、存在するindexを確認できる。

curl -X GET "http://localhost:9200/_cat/indices?v&bytes=mb"
ハガユウキハガユウキ

mappingはproperties句を書いて定義する。
properties句の中にはインデックスに含まれる各データ型定義(フィールドおよびデータ型)やアナライザーを指定する。

{
  "properties": {
    "user_name": { "type": "text"}
  }
}
ハガユウキハガユウキ

Elasticsearchでは、基本的に一度定義したマッピングを差し替えることはできないので注意してください。差し替えたい場合は、新しいマッピングを定義した新しいインデックスにデータを移し替える操作が必要となります。

なるほど

ハガユウキハガユウキ

クエリDSLは大きく次のように分類できる

  • 基本クエリ
    • 全文検索クエリ
    • Termレベルクエリ
  • 複合クエリ
    • Boolクエリ
ハガユウキハガユウキ

Termは指定したキーワードに完全一致するフィールドを含む文章を探す時に使うクエリ
matchクエリは全文検索の用途で使うクエリ。
termを使うべき場面でmatchクエリなどを使うと、New JerseyやNew Orleansなどもヒットしてしまう。それが意図する使い方なら良いが。

{
  "query": {
    "term": {
      "city": {
        "value": "New York"
      }
    }
  }
}
ハガユウキハガユウキ

Boolクエリのmustクエリに指定されたものはAND条件で、shouldクエリに指定されたものはOR条件。

ハガユウキハガユウキ

形態素解析は辞書にない単語を認識できないので、新語や人名などに弱い。
また、品詞の抽出結果によっては細かい検索漏れが起こる可能性がある。

N-gramは意図しないクエリでヒットしてしまうので、検索精度の面で問題になることがある。
またインデックスデータのサイズが増大する傾向にある

ハガユウキハガユウキ

Analyzerは以下の要素で構成されている。

  • char filter(任意の数を指定できる)
  • tokenizer(1つだけ必要)
  • token filter(任意の数を指定できる)

char filterは文字単位の処理
token filterはトークン(単語)単位での処理

ハガユウキハガユウキ

Analyzer構成のカスタム定義

まず、ビルトインのAnalyzerを使わずに、Analyzerの構成をカスタム定義する方法を説明します。カスタムAnalyzerを利用するためには、以下のようにインデックス定義の"settings"句のなかに"analyzer"句を記述して、その中でAnalyzerの構成を定義します。

ハガユウキハガユウキ

再インデックス

再インデックスは、既存のインデックスにあるドキュメントを別のインデックスにコピーする機能です。単なるコピーに加えて、ある条件のデータのみをコピーする、コピー時にコピー先のインデックス定義を変更するといった様々な操作が可能です。

このスクラップは2025/04/20にクローズされました