検索に出ない・古い結果が出る原因を調べる:日本語解析・refresh・インデックス再構築
商品検索の不具合を、転置インデックス、日本語の語の分け方、配送とrefreshの遅れ、別名による切り替えへ分解。4件のTipsから、調査と安全な作り直しの手順を解説します。
検索に出ない・古い結果が出るときの調査順
架空の商品検索で、登録直後の商品が出ず、型番の検索も漏れ、解析を直した後には古い価格が戻ったとします。これらを「検索精度が悪い」でまとめず、登録・配送・解析・検索・切り替えの境界に分けます。この記事はElasticsearchの公式資料を中心に、検索基盤の4件のTipsをつなぎます。
| 確認 | 観測するもの | 原因の候補 |
|---|---|---|
| 正本(せいほん:正しい値の基準とする元データ)にあるか | 商品ID、版、認可された参照 | 保存失敗や別テナントの参照 |
| 索引に届いたか | 配送位置、失敗記録、索引内のIDと版 | 配送遅延、変換失敗、削除漏れ |
| どう語に分かれたか | 登録側と検索側の解析結果 | 辞書、正規化、フィールドの違い |
| どの索引を検索したか | 別名、フィルタ、検索可能になった時点 | 旧索引の参照、認可条件、refresh待ち |
転置インデックスは語から文書を探す
転置インデックスは、語を含む文書IDの一覧を持ちます。たとえばRedisの一覧とキャッシュの一覧の共通部分を求めれば、AND検索の候補を絞れます。実際の検索は順位付けやクエリの条件も含むため、常に単純な共通部分だけを返す仕組みではありません。
語A → 文書1・3・5 → 語B → 文書2・3・5 → 共通する候補は文書3・5 → 必要な文書を取得して順位付け
通常のB木があるだけではLIKEの先頭ワイルドカードから選択的に絞りにくい一方、PostgreSQLのpg_trgmにはLIKE・ILIKE向けのGIN/GiST索引があります。「LIKEは必ず全件走査」と断定せず、必要な一致の意味と実行計画で判断します。DB内の検索で要件を満たせるなら、別エンジンの同期運用を増やす必要はありません。
日本語解析:見逃しと誤一致を両方調べる
日本語の文字bi-gramでは、東京都から東京と京都という並びを切り出せます。京都の地域情報が欲しい人には誤一致です。形態素解析なら東京都を1語とする設定が候補ですが、実際の辞書・モード・フィルタによって結果は変わります。新しい商品名や型番も含め、実際に出るトークンを調べます。
POST /_analyze
{
"analyzer": "kuromoji",
"text": "東京都に住む"
}登録時と検索時の解析がどこで異なるかを確認し、表記揺れ・新語・型番・地域名を評価セットへ入れます。N-gramと形態素解析を別フィールドに持つ案はありますが、容量と順位調整の負担が増えます。索引時の解析を変えるなら、既存文書も作り直す必要があるかを確認します。
保存成功と検索反映:配送とrefreshを分ける
Elasticsearchのrefreshは、書き込んだ変更を検索できるようにする処理です。正本DBから索引へ届くまでの配送遅延は、それより前にあります。refresh=wait_forはその索引への書き込みを次のrefreshまで待つ指定で、まだキューにある変更を速めるものではありません。既定間隔をすべての提供形態で同じと扱わず、採用環境の設定を確認します。
ある1件で配送に2秒、書き込み後の検索待ちに0.7秒なら、検索可能まで2.7秒です。これは仮定の1件の直列時間で、平均と最大を混ぜた上限ではありません。登録完了画面は認可済みの正本から返し、検索一覧には反映中の状態を示す設計にすると、再登録による重複も避けやすくなります。
インデックスの作り直し:コピー・追従・切り替えをつなぐ
新しい解析やマッピングを別のproducts-v2に用意し、既存の検索はproducts-readという別名でproducts-v1を参照させます。全件コピーだけで終わらず、その間の更新・削除を変更ログから再適用します。元データのスナップショットとログ位置を接続し、古い版が新しい値を上書きしない規則を使います。
- 新索引の解析・マッピングを用意し、負荷と容量の余力を確認する。
- 整合したコピーと、それを覆う変更ログの範囲を確保する。
- コピー中の更新・削除へ追いつき、失敗イベントとキー・版の差を照合する。
- 検索の評価セットと反映遅延を確認し、更新が逃げない切り替え境界を作る。
- 別名を1回の操作で切り替え、応答全体と失敗の詳細を確認する。
Elasticsearchは別名の付け替えをまとめて要求できます。複数アクションには一部だけ成功する失敗形があるため、must_exist=trueなど、1つの失敗で要求全体を失敗させる条件を確認し、応答のアクション別の結果も検査します。切り替え前に旧索引を残すだけでは、後から安全に戻せるとは限りません。旧側も更新を受け続けるか、戻す前に追従し直す手順が必要です。実行中の要求まで同じ瞬間に新索引へ移るとは扱いません。
検索の検証は、正解集合と更新・削除も含める
型番で必ず見つかる商品、京都の検索で除外したい商品、新語を含む商品を用意し、上位結果・取りこぼし・誤一致を変更前後で比べます。コピー中に更新と削除を行い、切り替え後の版と不在も確認します。件数が合っても別の文書が入れ替わっている可能性があるため、同じ締め時点のIDと版を照合します。
参考にした一次資料
以下の公式資料は2026年10月27日に確認しました。数値例とシナリオは独自の仮定です。設定例は説明用で、実サービスでの実行や性能測定は行っていません。
- PostgreSQL 18 — GIN
- PostgreSQL 18 — pg_trgm
- Elasticsearch — Kuromoji tokenizer
- Elasticsearch — Near real-time search
- Elasticsearch — refresh parameter
- Elasticsearch — Aliases