2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenSearch導入で学んだ「検索速度」と「Wildcard」の威力

2
Posted at

はじめに

エンジニア2年目、現在稼働中のシステムを刷新するリプレイスプロジェクトにバックエンドエンジニアとして参加しています。
これまでの業務経験ではRDB(SQL)しか触ったことがなく、「データといえばテーブル管理、検索といえば SELECT ... WHERE ...」 という世界で生きてきました。
そんな中、新システムの検索基盤として OpenSearch を導入することになり、初めてNoSQLの技術に触れることになりました。
本記事では、RDBしか知らなかった私が、OpenSearchの実装を通して感じた「RDBとの違い」や、実装時にハマって解決した「Wildcard型」の知見について共有します。

導入背景

私が参画した時点で既にOpenSearchの採用は決定していました。
当時の私は「なぜわざわざ新しい技術を使うの?」と思っていましたが、背景には「データ増大に伴うRDB(LIKE検索など)のパフォーマンス限界」を打破する狙いがありました。
実際にRDBでは、部分一致(LIKE %hoge%)の検索においてインデックスが効きづらく、レスポンス速度が課題になりがちだからです。

OpenSearch とは?(RDB脳での理解)

OpenSearchは、検索や分析を行うための分散型全文検索エンジンです。
詳細な概要は↓

RDBしか知らなかった私が最初に戸惑ったのが、「データの持ち方」と「用語」の違いでした。

RDBとは何が違うのか?

RDBが「テーブルに行(Row)と列(Column)でデータを管理する」のに対し、OpenSearch は「JSON形式のドキュメント」としてデータを保存します。

学習し始めの頃は、以下のようにRDBの用語に置き換えて理解していました。

RDB (SQL) OpenSearch 備考
Database Cluster データの集合体全体
Table Index データの種類ごとの入れ物
Row Document 1件ごとのデータ(JSON形式)
Column Field データの中の項目(key)

なぜ検索が早いのか?

RDBでいう「本の最初から最後までページをめくって探す(フルスキャン)」のとは異なり、OpenSearch は「転置インデックス(Inverted Index)」という仕組みを持っています。
これは、「本の巻末にある索引」のようなものです。
「どの単語が、どのドキュメントに含まれているか」があらかじめ整理されているため、膨大なデータの中からでも一瞬で目的のデータを見つけることができます。

技術的にハマった点と解決策:Wildcard型の活用

概念は理解できたものの、実装当初、RDBと同じ感覚で進めていた私は「アンダーバー(_)を含む文字列」の検索精度で躓きました。

直面した課題

標準の text 型フィールドでも部分一致検索は可能ですが、アナライザーによって単語が分割(Tokenize)されてしまい、「アンダーバーを跨ぐような検索がヒットしない」という問題や「Text型へのワイルドカード検索はスキャンが重く、パフォーマンスが出ない」という課題がありました。

解決策:Wildcard型フィールド

そこで採用したのが Wildcard型フィールドです。
これを適用することで、SQLのLIKE検索に近い感覚で、かつ高速に特殊文字を含むパターンマッチングが可能になりました。
「こんな便利な型があるのか!」と、RDBにはない柔軟さに驚きました。

マッピング定義(Mapping)の例
{
    "mappings": {
        "properties": {
            "product_name": {
                "type": "wildcard"
            },
            "category": {
                "type": "keyword"
            },
            "status": {
                "type": "keyword"
            }
        }
    }
}

RDB脳のための「クエリ翻訳ガイド」

OpenSearchのクエリ(Query DSL)はJSON形式で記述するため、SQLしか書いてこなかった私は最初かなり戸惑いました。
自分の整理も兼ねて、よく使う条件の対応表と書き方の違いをまとめました。

条件 RDB (SQL) OpenSearch (Query DSL)
AND条件 WHERE A AND B bool > must (または filter)
OR条件 WHERE A OR B bool > should
NOT条件 WHERE A != B bool > must_not
LIKE検索 WHERE name LIKE '%abc%' wildcard (または match)

具体的なクエリ比較

RDB(SQL)の場合
SELECT * FROM products
WHERE status = 'active'
    AND product_name LIKE '%product%'
OpenSearchの場合
{
    "query": {
        "bool": {
            "filter": [
                { 
                    "term": {
                        "status": "active"
                    }
                }
            ],
            "must": [
                {
                    "wildcard": {
                        "product_name": {
                            "value": "*product*"
                        }
                    }
                }
            ]
        }
    }
}

Point: filterとmustの使い分け

SQLの AND はすべて同じ扱いですが、OpenSearchには must(スコア計算あり)と filter(スコア計算なし・キャッシュ有効)があります。
「単に条件に一致するか(Yes/No)」だけの条件は filter に入れることで、検索速度がさらに向上します。これを知ったとき、OpenSearchの奥深さを感じました。

業務で使用して感じたメリット

実際に新システムで運用してみて、検索速度以外にも開発体験としてのメリットを強く感じました。

仕様変更に強い

開発途中、「やっぱりこの条件でも絞り込みたい」「権限によって表示を変えたい」という要望が頻発しました。
RDBではSQLの組み直しが大変ですが、OpenSearchのDSLなら、JSONの配列に条件を追加・削除するだけで済みます。
経験の浅い私でも、「クエリ構築の柔軟性」のおかげで、度重なる変更にスピーディに対応できました。

また、今回はバックエンド言語にJavaを使用しましたが、OpenSearch はREST API ベースなので、Python や Go 、Node.js など他の言語でも同様に扱えます。

Javaでクエリを構築する場合
final String status = request.getStatus
if (ObjectsUtils.isNotEmpty(status)) {
    boolQuery.filter(termQuery("status", status))
}

文字列を操作するのではなく、ブロックを組み立てるようにクエリを構築できるため、複雑な条件分岐があってもバグを生みにくく、アジャイル開発と非常に相性が良いと感じました。

権限まわりのフィルタリングが容易

「特定の部署の人には、このデータを見せない」といった複雑な権限ロジックも、検索クエリの filter 部分に条件を差し込むだけで完結します。アプリケーション側でデータを全件取得してから間引く必要がないため、パフォーマンスを落とさずにセキュリティ要件を満たすことができました。

まとめ

導入の結果、検索処理が高速化され、ユーザーからも「検索結果が出るのを待たなくて良くなった」と非常に良いフィードバックをいただくことができました。
2年目の私にとって、RDB以外のデータストアを扱うのは大きな挑戦でしたが、「Wildcard型」や「Filterコンテキスト」など、適切な機能を使いこなすことでRDBでは実現できないパフォーマンスが出せることを学びました。

今後も食わず嫌いせず、新しい技術に挑戦していきたいと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?