ADOC TECH BLOG
2025-07-31
- ADOC インターナショナル
- ブログ
- Elasticsearchにおけるキーワード検索、ベクトル検索、ハイブリッド検索の比較
Elasticsearchにおけるキーワード検索、ベクトル検索、ハイブリッド検索の比較
はじめに
データエンジニアのsenariです。普段はElasticsearchに関わる業務を担当しています。
近年、AIや機械学習という言葉を耳にする機会が増え、「ベクトル検索」に興味を持つ方も多いのではないでしょうか。私自身も、ベクトル検索や「ハイブリッド検索」といった新しい手法を知った時、「最新技術なのだから、従来のキーワード検索より優れているに違いない」と直感的に感じました。しかし、調査を進めると、各検索手法には固有のメリット・デメリットがあり、用途によって最適なアプローチが異なることに気づきました。
今回は、Elasticsearchでキーワード検索、ベクトル検索、ハイブリッド検索を実際に試し、その結果を比較することで、それぞれの違いと使い分けのポイントを解説します。
PAGE INDEX
環境情報
Elasticsearch (Elastic Cloud) 8.12.0
MLノード(RAM 4GB以上)※機械学習モデルの使用時に必要になります。
事前準備
ベクトル検索用に自然言語処理(NLP)モデルcl-tohoku/bert-base-japanese-v3をElasticsearchにインポートしています。また、検索用のデータはChat GPTに作成してもらい、Elasticsearchに取り込んでいます(取り込んだデータの詳細は後述)。その際にベクトル化も行っています。
参考
・Elasticsearchで日本語NLPモデルを利用してセマンティック検索を実現する
https://www.elastic.co/jp/blog/elasticsearch-nlp-ja
キーワード検索
本記事ではベクトル検索を使わない全文検索のことをキーワード検索と呼びます。
キーワード検索は明確なキーワードや特定の単語に基づく検索が得意です。そのため商品名や型番などの特定のキーワードでの精度が高いです。ただし、曖昧な表現や検索ワードの意味をくみ取ることはできないため、検索したいものに対してある程度正確な検索ワードが必要になります。
ベクトル検索
ベクトル検索は、機械学習モデルを使用してテキストデータや画像、音声等の非構造化データをベクトル化し、意味的な類似度に基づいて検索結果を返すことが出来ます。検索時に検索ワードがベクトル化され、事前にベクトル化されているデータとベクトル的に距離が近いものを検索結果として返します。
検索ワードに対して意味的に近いものを検索結果として返すため、名前が分からないものに対しての検索であったり、ドキュメントのワードと一致していなくても意味的に一致していれば検索結果を返すことが出来ます。その代わり、検索したワードと一致していないものも検索結果として返ってきたり、固有名詞の意味を理解できないなどの弱点があります。
ハイブリッド検索
ハイブリッド検索は、キーワード検索とベクトル検索を組み合わせた手法で、両者の強みを活かした結果を返します。キーワードによる検索とベクトルによる意味的な検索を組み合わせることでより関連性の高い検索結果を得ることが出来る検索手法です。
どのような条件で比較するか
まず、それぞれの検索を比較するための条件を決めます。
検索用のデータ
今回比較に使用する検索データは、Chat GPTに作成してもらいました。
name | description |
りんご | りんごは甘くてシャキシャキした食感で知られる果物です。 |
みかん | みかんは明るい色とジューシーな味わいで人気のある柑橘類です。 |
バナナ | バナナはエネルギー補給に最適な果物で、スポーツ選手に好まれます。 |
ぶどう | ぶどうは甘く、ワインの原料としても広く利用されています。 |
いちご | いちごはその鮮やかな赤色と甘酸っぱい味で人気があります。 |
パイナップル | パイナップルは南国の果物で、甘みと酸味が特徴的です。 |
スイカ | スイカは夏の定番の果物で、みずみずしさが魅力です。 |
マンゴー | マンゴーは濃厚な甘みと滑らかな食感で知られています。 |
キウイ | キウイはビタミンCが豊富で、健康に良い果物です。 |
レモン | レモンはその酸味が料理や飲み物によく使われます。 |
キーワード検索条件
kuromoji analyzerを適用したdescriptionフィールドと、果物の名前が入っているkeyword型のnameフィールドに対してmulti_matchクエリで検索します。
kuromoji analyzerは、日本語の文章などを検索可能な形に直す処理を行うものです。例えば「人気がある果物はどれ?」を「人気」、「果物」、「どれ」のように検索しやすいトークンに分割、変換するものです。
GET search_compare/_search
{
"_source": [
"name",
"description"
],
"query": {
"multi_match": {
"query": "りんご",
"fields": [
"name",
"description"
]
}
}
}
ベクトル検索条件
cl-tohoku/bert-base-japanese-v3というNLPモデルでベクトル化したフィールドをknn検索します。
knn(k-nearest neighbor)とはk近傍法という機械学習アルゴリズムであり、ベクトル検索でよく使われる手法です。
参考
・k-nearest neighbor (kNN) search
https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html
GET search_compare/_search
{
"_source": ["name", "description"],
"knn": {
"field": "text_embedding.predicted_value",
"k": 10,
"num_candidates": 100,
"query_vector_builder": {
"text_embedding": {
"model_id": "cl-tohoku__bert-base-japanese-v3",
"model_text": "りんご"
}
}
}
}
ハイブリッド検索条件
キーワード検索、ベクトル検索をrrfで組み合わせて検索します。
rrfは関連性の指標が異なる複数のランキングを1つのランキングに結合する方法です。
参考
・Reciprocal rank fusion
https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html
GET search_compare/_search
{
"_source": [
"name",
"description"
],
"query": {
"multi_match": {
"query": "りんご",
"fields": [
"name",
"description"
]
}
},
"knn": {
"field": "text_embedding.predicted_value",
"k": 10,
"num_candidates": 100,
"query_vector_builder": {
"text_embedding": {
"model_id": "cl-tohoku__bert-base-japanese-v3",
"model_text": "りんご"
}
}
},
"rank": {
"rrf": {
"window_size": 10,
"rank_constant": 60
}
}
}
検索ワード
単語での検索、曖昧な表現での検索、複数単語の検索、文章での検索で比較します。
- りんご
- 酸っぱい果物
- みかん 味
- 人気がある果物はどれ?
検索結果
各種検索の結果をまとめています。(表2参照)
比較の参考のためにRanking evaluation APIのmetric_scoreの値を記載しています。このAPIは検索結果の妥当性を評価するためのAPIです。
・Ranking evaluation API
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-rank-eval.html
metric_scoreには検索結果に対する評価値が入ります。
今回はmetricにnDCGを使用します。ratingで定義したランキングと検索結果のランキングがどの程度一致しているかで評価値が変わります。1に近いほど定義したランキングの検索結果に近く、0に近いほど定義したランキングと離れた検索結果となります。
GET search_compare/_rank_eval
{
"requests": [
{
"id": "query",
"request": {
"query": {
"match": {
"description": {
"query": "酸っぱい果物"
}
}
}
},
"ratings": [
{
"_index": "search_compare",
"_id": "ZipRbJMBUld2niYGBU7r",
"rating": 10
},
{
"_index": "search_compare",
"_id": "EypPbJMBUld2niYG40Ov",
"rating": 8
},
{
"_index": "search_compare",
"_id": "2ypRbJMBUld2niYGO08K",
"rating": 7
},
{
"_index": "search_compare",
"_id": "tCpPbJMBUld2niYGQTb3",
"rating": 7
},
{
"_index": "search_compare",
"_id": "nSpQbJMBUld2niYG7E3t",
"rating": 7
}
]
}
],
"metric": {
"dcg": {
"k": 10,
"normalize": true
}
}
}
検索ワード | キーワード検索 | ベクトル検索 | ハイブリッド検索 | |||
---|---|---|---|---|---|---|
上位ヒット (TOP3) |
metric score |
上位ヒット (TOP3) |
metric score |
上位ヒット (TOP3) |
metric score |
|
りんご | ①りんご | 1 |
①みかん ②ぶどう ③りんご |
0.5 |
①りんご ②みかん ③ぶどう |
1 |
酸っぱい果物 |
①スイカ ②りんご ③パイナップル |
0.13 |
①パイナップル ②みかん ③レモン |
0.68 |
①パイナップル ②スイカ ③りんご |
0.54 |
みかん 味 |
①いちご ②みかん |
0.63 |
①みかん ②パイナップル ③レモン |
1 |
①みかん ②いちご ③パイナップル |
1 |
人気がある果物どれ? |
①いちご ②みかん ③スイカ |
0.92 |
①みかん ②パイナップル ③バナナ |
0.87 |
①みかん ②いちご ③パイナップル |
0.94 |
検索ワードごとの検索結果の比較
- 「りんご」:キーワード検索では単純なキーワードマッチが有効で、スコアが高くなりました。ハイブリッド検索でもキーワード検索に引っ張られる形で高いスコアが得られました。
- 「酸っぱい果物」:テキスト検索では「スイカ」がヒットしましたが、これはdescriptionフィールド内の「果物」という単語に反応した結果です。一方、ベクトル検索では意味的な関連性が重視され、パイナップルやレモンが検索上位にいます。
- 「みかん 味」:キーワード検索では「味」という単語が影響し、「いちご」が上位に表示されました。しかし、ベクトル検索では「みかん」がトップに表示され、意味的な関連性が考慮されました。
- 「人気がある果物はどれ?」:キーワード検索では「人気」「果物」という単語に依存した結果が表示されましたが、ハイブリッド検索ではキーワードと意味的関連性の両方が反映され、精度の高い結果が得られました。
まとめ
検索結果からは明確なキーワードマッチが求められる場合はキーワード検索、意味的な関連性を重視するならベクトル検索、広範かつ精度の高い結果を求めるならハイブリッド検索が適していることがわかりました。
今回の比較ではハイブリッド検索の最も精度が高かったと言えますが、「酸っぱい果物」で検索したときのようにキーワード検索とベクトル検索のどちらか一方の精度が極端に低いとそちらに検索結果が引っ張られてしまう場合もあります。要件、用途に合わせて、検索の種類やスコアリングのチューニングしていくことが必要になると思います。
———
当社のデータ分析サービスの詳細はこちら:https://adoc.co.jp/solutions/service/big-data/