Elasticsearchの高速検索ロジックを理解する 【入門】

25卒の駆け出しの大学生エンジニアです。
普段のインターンでは主にサーバーサイドを担当しています。

前にサービス開発時に、サービスへのアクセスログの分析機能を作成した際にかなり簡易的ではありますがElasticsearchを用いました。
今回はElasticsearchに関する備忘と理解促進のためにまとめました。

どちらかというと概要部分になりますので上級者やSREゴリゴリの人向けではないです。ただアドバイスは欲しいです。

今回は高速な検索処理を可能にしているロジックについてをメインで書いています。そのため検索の実装方法を記載したものではありませんのでご了承ください。

## 想定読者

- Elasticsearch入門者
- 全文検索系の機能に興味がある
- 英語の長いドキュメントを読みたくない
- rest APIを通して使ったことはあるけど、中身の処理がよくわからない


## Elasticsearchの概要
![es.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470041/3c764176-30f3-b786-a29a-54876f635bd7.png)
(https://datascientest.com/en/elasticsearch-everything-you-need-to-know)

### Elasticsearchとは

ElasticsearchはElastic社が提供するElastic Stackの一部で、高速な全文検索とデータ分析を可能にする分散型検索エンジンです。
大量のデータをリアルタイムで処理し、従来のRDBMSでは難しい複雑な検索クエリに対応できます。

### 具体的な用途

以下のようなことを実現したい場合に利用されます。
特に膨大なデータを扱った検索や分析は通常のDBではレコードが多すぎて厳しいのでそういったところに使われるかなといった認識です。

- webサイトなどの検索処理
- ログやイベント等の分析


以下をはじめとしたアプリケーションで膨大データ量からの検索機能で実際に使用されています。

- Uber taxi (検索)
- メルカリ (検索)
- Line Music (検索)

LINE Developersで実際の運用について解説している動画があり、とてもためになりました。(この動画は実運用場の問題解消なので少し難しいかもです。Elasticsearchの話というより、アルゴリズムよりです。)
8,500万件という膨大な楽曲からの検索なので、Elasticsearchなどの全文検索サービスを使わなければ到底実現できないだろうということなんとなく想像ができるかなと思います。

https://www.youtube.com/watch?v=S1IqcVUtouY

### サービスの特長

Elasticsearchには以下のような重要な特徴があります。

- **スケーラビリティ**：大規模なデータセットに対応し、需要に応じてリソースを拡張できる能力が備わっています。
- **スキーマレス**：柔軟なデータ構造で、さまざまな形式のデータを扱うことが可能です。
- **高速な全文検索**：大量のデータから迅速に必要な情報を見つけ出すことができます。
- **開発者フレンドリー**：開発者はElasticsearchの内部構造を知らなくても、restAPIを通じて直感的なデータの操作が可能です。


## Elasticsearchの高速検索を可能にするロジック

このセクションでは、Elasticsearchの検索処理の中身を紐解くことで、どのようにして高速な検索機能を提供しているかをみていきます。
主にこれを実現しているのはこれから述べるような要因がありますのでそれぞれについて説明します。
裏側ではもっとたくさんの最適化処理があるかもしれませんが、重要だと思うものを抽出して解説いたします。

### 1️⃣ 転置インデックス

全文検索処理を実現するには「インデックス」(索引) を用いて効率的にデータを取得する必要があります。
それを実現するために行うのが転置インデックスの処理です。
テキストのみでは理解が難しいと思うので、図や例を用いつつElasticsearchが内部で行なっている転置インデックスを説明します。

今回は以下のデータを例に考えていきます
| ID | TEXT |
| --- | --- |
| 1 | Next is React framework |
| 2 | React is JavaScript library |
| 3 | Laravel is PHP framework |

 #### STEP 1. 文章の言語処理を行う

TEXTに対して以下のような言語処理を行います。

- 単語ごとに区切る
- 全てを小文字に揃える
- 不要な文字(is, aなど)を排除する

すると渡ってきた三つの文章は以下の6個の単語に分けることができます。
| next | react | framework | javascript | php | laravel |
| --- | --- | --- | --- | --- | --- |

#### STEP 2. 6個の単語をインデックスにして文書を格納する

前回取得した6個の単語をインデックスにして、そのバリューに対してデータ(Document)を格納します。

| word | id |
| --- | --- |
| next | 1 |
| react | 1, 2 |
| framework | 1, 3 |
| javascript | 2 |
| php | 3 |
| laravel | 3 |


#### 3. 検索する

2のように転置インデックスを施すことにより、webサイトによくある検索がRDBMSで直接探し出すよりも容易になったことがわかるかと思います。
例えばユーザーが「framework」と検索した場合はそれのidを返してあげれば良いだけなので、1と3のデータを返してあげれば良いのです。
また、「framework next」などの複数ワードで指定があった場合は、「framework」: 1,3「next」: 1, となるのでどちらにも含まれる1を返してあげれば良いことになります。

これは全文検索でもクエリ検索でも使用されており、Elasticsearchはクエリで指定した条件を全て満たしたものを抽出して返却しています。


### 2️⃣  分散型アーキテクチャ

Elasticsearchは内部では分散型のアーキテクチャをしています。
詳細なところはなるべく省いて、概念を理解するためにざっくりと説明していきます。

![スクリーンショット 2023-12-10 午後5.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470041/81b81010-e9fa-4585-e5e6-456d7ac5a9a2.png)

これはElasticsearchの内部を簡単に表した図です。
出てくる用語と、その働きについて詳しくみていきます。


#### **Cluster**

ClusterとはElasticsearchのインスタンス群を意味します。
同一Clusterに格納されているNodeはお互いに協力してデータの検索や格納を行うことができます。
Clusterに関する設定は適宜行う必要があります。

#### **Node**

NodeはCluster内部に存在するインスタンス(サーバー)を意味します。
Clusterの部分で述べたように、同一Cluster内のNodeは互いに協力しながら処理を行います。

##### - Data Node

主な働きは以下の４つに分類されます。
1. データの格納 ⇒ データの物理的な格納場所となっています。
2. 検索処理の実行 ⇒ 保存されているデータの中から、受け取ったクエリを元に検索を行います。
3. データ操作 ⇒ データの保存や削除、更新といったデータ処理を司ります。
4. アグリゲーション・分析 ⇒ データの収集・分析を行います。

##### - Master Node

Master Nodeはその名のとおり管理者です。

様々な働きがありますが、Cluster内の管理を司っているNodeがあると理解していただければ概要を掴むには問題ないかなと思います。

詳細な仕組みを知りたい方は以下のMercariの技術ブログなどがおすすめです。
(正直ここは私もなんとなくの理解なので自分でうまく説明するのが難しいです。。)

https://engineering.mercari.com/blog/entry/20220311-97aec2a2f8/

上記で述べたNodeの数は簡単に増やせるので、数を増やすだけで容易にスケールアウトすることができ、大規模なデータの処理を向上させかつ可用性を上げることができます。
これが容易なスケールアウト・高速検索を可能にしています。

また、Nodeは一つが不具合を起こしても処理が止まらないようになっているので、複数のNodeで動作させることにより、可用性(どこかに不具合があっても動作し続けられる)の向上にもつながっています。


### 3️⃣ キャッシングによる最適化

これは単純なことですが、よく使われる検索クエリに対する結果は、キャッシングをすることで、再度検索処理を回さずに前回の結果をそのまま返すことによって効率化を実現しています。


## 終わりに

内部のアルゴリズムをあまり気にせずにやっていたので、理解できてすこし腑に落ちました。
今回は概要に関してまとめてみましたが、今後学習を進めてより中核の処理や仕組みを理解できたらなと思います。
docker imageが無料配布されているのでローカルで少し動かしてみても面白いかもしれません。
私の関わったプロダクトでは使いませんでしたが、kibana と呼ばれるサービスを使うと、Elasticsearchに蓄積したログの分析を閲覧できるそうなので試してみたいところではあります。
Elasticsearch上級者様、重要点の過不足・誤りがもしありましたら教えていただけると幸いです。

## 参考

https://www.elastic.co/guide/index.html

https://dev.classmethod.jp/articles/devio2022-elasticsearch-prismatix/

https://www.youtube.com/watch?v=S1IqcVUtouY

https://engineering.mercari.com/blog/entry/20220311-97aec2a2f8/