Azure Cognitive Searchのしくみ

f:id:ecb_ssakagami:20220304115125p:plain

はじめに

お久しぶりです
みんなの手柄を自分の手柄のように横取りそして自慢する窓際社員 ガミさんです
さて今回はLightningSearchがローンチされ自慢する時期を逃してしまったのでさわりとして自慢をさせてください
その後、運用を開始してからLightningSearchの中核となっているAzure Cognitive Searchに焦点を当ててみました
またAmazon OpenSearchについてもAWS担当者とお話しができたので記事の後半で比較してみました
これから検索サービスを検討する方の役に立てば嬉しい限りです

LightningSearchローンチしました!

お披露目の機会を逃しローンチから1年が経ってしまいましたが2021年3月にLightningSearch (らいとにんぐさーち)をローンチしました
いままで当社ecbeingパッケージに検索エンジンを入れようとするとエンジン会社様と要件定義、組み込み、テストと案件ごとにかなり労力を必要としていました
餅は餅屋ということで出遅れていた感じがありましたが、これでようやく安価で高速な検索体験をユーザーにお届けできるようになりました

ファーストユーザーはなんと(株)リーガルコーポレーション
あまり詳細は明かせませんがかなりのパフォーマンス改善が見受けられました
その他にも色々なお客様からご相談を頂いております
少しずつではありますが認知度があがっていっております
ちょっとだけパフォーマンス改善を紹介させていただきます

標準パッケージからの検索パフォーマンス改善
商品一覧表示
LightningSearch導入前:3秒
LightningSearch導入後:150〜400ミリ秒

商品キーワード検索
LightningSearch導入前:8秒
LightningSearch導入後:150〜400ミリ秒

WebサーバCPU負荷
LightningSearch導入前:平均15%
LightningSearch導入後:平均10%

DBサーバCPU負荷
LightningSearch導入前:平均20%
LightningSearch導入後:平均6%


機能としてはまだまだ他社の検索エンジンにかなわない部分が多いですがこれからも機能改善・追加を重ねよりよい検索体験を提供していけるようにいたします。
導入検討のお客様はこちらからお問い合わせください

次から本題となります

今回のお題

LightningSearchの運用を開始してから課題となった点の共有となります
Azure Cognitive Searchのしくみについても少し踏み込んでいきます
インデックス、インデクサーについては今回言及していません
まずは運用開始後にお客様から伝えられた課題を列挙していきたいと思います

ひらがな⇔カタカナがヒットしない

「パーカー」を「ぱーかー」で検索できない等
⇨辞書登録(Azure Cognitive Searchのシノニム登録)で回避

絞込み項目の大文字⇔小文字がヒットしない

ecbeingで登録する絞り込みマスタは全部大文字なのに商品情報に登録されている候補が小文字の場合、Azure Cognitive Searchのインデックスに登録される絞込み条件と一致しなくなるため同じ絞り込み項目と認識してもらえない
キーワード検索としてはヒットする
要約するとCognitive Searchのインデックス構成で項目ごとで「検索可能」という設定と「フィルター可能」という設定があって検索可能はアナライザーが効くのですが、フィルター可能は絶対にその項目で指定される的な感じで完全一致となります

⇨Azure Cognitive Searchへの連携データを連携時に修正してもらい回避

同音文字がヒットしない

「ズ」 と 「ヅ」 「ベ」 と 「ヴェ」 などはヒットしない
⇨ある程度の固有名詞は辞書登録(Azure Cognitive Searchのシノニム登録)で回避

新旧漢字がヒットしない

「高」「髙」などはヒットしない
⇨ある程度の固有名詞は辞書登録(Azure Cognitive Searchのシノニム登録)で回避

数値項目が完全一致でないとヒットしない

JANコードや型番で全てが数値の場合、前方一致ではヒットせず完全一致とする必要がある
⇨ユーザーが入力しそうな単位に分割して辞書登録(Azure Cognitive Searchのシノニム登録)することで回避

と、まぁ結構できてて欲しいことができないジレンマがありました

Azure Cognitive Searchって結局どうなの?

数十万件の商品検索の検索結果がミリ秒単位で返ってきて爆速なのは確かなんですが痒いところに手が届かない
Microsoftの検索エンジンならSQLServerの照合順序的な検索してくれればいいのに!と思う今日この頃です
ちょっとSQLServerの照合順序もおさらいしながらCognitive Searchの解説をしていきたいと思います
ちなみに照合順序はAzure Cognitive Searchでいうとトークナイザー、アナライザーというものになります
トークナイザー、アナライザーについては後述します

SQLServerの照合順序

照合順序は日本語を使っているなら基本的にXJIS〜になると思うのでここは割愛します
照合順序オプションは次の通り

オプション 説明
CI Case Insensitive(大文字と小文字を区別しません。)
AI Accent Insensitive(アクセントを区別しません。)
KI Kana Insensitive(ひらがなとカタカナを区別しません。)
WI Width Insensitive(半角と全角を区別しません。)
CS Case Sensitive(大文字と小文字を区別します。)
AS Accent Sensitive(アクセントを区別します。)
KS Kana Sensitive(ひらがなとカタカナを区別します。)
WS Width Sensitive(半角と全角を区別します。)

自分としてはJapanese_XJIS_100_CI_AS相当の検索がAzure Cognitive Searchで実現できたらいいなと思ったのですが世の中そんなに甘くありませんでした
ちなみにSQLServerではCI_ASを指定した場合、暗黙でKI_WIが設定されます
Azure Cognitive SearchではCI,WIはできているはずなのでKIだけ補完できるように辞書登録(Azure Cognitive Searchのシノニム登録)をしてあげればいいかなと考えていましたがここも甘い考えでした
結果としては一部はヒットするが想定通りにヒットしない方が多かった印象です
※CI,WIができているかもというのはこのあたりを参照
 指定したトークナイザー、アナライザーによりalphanumericalが適用されます

Azure Cognitive Searchのトークナイザーとアナライザー

トークナイザーとアナライザー

トークナイザーとは検索対象となるテキストを単語区切りにしたりする機能になります
アナライザーは指定した言語に即した文法などを考慮して単語区切りの補助をしてくれる機能になります
Azure Cognitive Searchではここでトークン化されたワードの前方一致で検索する形となります
そのため部分一致という言葉で案内してしまうと「ヒットしないじゃないか!」というクレームの対象となります
JANコードや型番が完全一致のものしかヒットしない原因はトークナイザーが分割しないからということになります
なぜ半角英数字のものが前方一致もヒットしないのかはトークン化が1つで分割されないことが原因となります・・・が前方一致くらいしてくれてもいいのに
これを回避するにはトークナイザーをnGramに指定してほぼ文字単位にすること、または検索時にワイルドカードを指定して対応することが対処方法となるようですが以下の弊害が発生します

・トークナイザーをnGramに指定すると現状のインデックスが8倍程度増えて検索パフォーマンスに
 影響が出る(=スペックをあげたりレプリケーションが遅れたり・・・)
・検索時にワイルドカードを指定すると検索範囲が拡大してしまいパフォーマンスに影響が出ることと
 スコアがあまり意味をなさなくなってしまう
・オートコンプリートを併用すると検索API、オートコンプリートAPIと2重にAPIをコールすることと
 なるため検索効率が落ちてしまう


トークナイザーの解説
アナライザーの解説

アナライザーの分割例 【ギフトサンプル品0001】【4573239680238】というキーワードがどのように分割されるかの確認デモとなります f:id:ecb_ssakagami:20220324093614p:plain 【ギフトサンプル品0001】の場合、【ギフト】【サンプル】【品】【0001】【nn1】というように分割されます
そのためヒットするキーワードとしては【ギフトサンプル品】【ギフトサンプル品0001】【ギフト】【サンプル】【品】【0001】などとなります
モノによるのですが【ギフトサンプ】などトークンを跨いだ前方一致がヒットしないこともあります

f:id:ecb_ssakagami:20220324093620p:plain 一方全て数値のJANコードや型番などは例のように【4573239680238】【nn4573239680238】完全一致でないとヒットしないことになります
検索キーワードにワイルドカード【4573*】など指定すると前方一致でもヒットはしますが後方一致はできません
これをトークナイザーでnGramとすると【45】【57】【73】【23】...など細かく分割されすぎて不要なものがヒットすることが見てわかります

このようにトークナイザー、アナライザーは柔軟に設定することができますがこのヒット精度を求めると沼にハマります
そしてその度に頭を悩ませる羽目に・・・

カスタムアナライザーについて

自分で検索精度を作ることができるのですが、アナライザーの併用ができないためこれは非常に使いづらい
例)
・標準で用意されているアナライザーpatternを指定して正規表現可能なトークン分割を使いたい
・ひらがなとカタカナを区別しないカスタムアナライザーを作って使いたい
⇨上記2つを組み合わせたいけど指定は1つなのでカスタムアナライザーを指定してしまうとpatternアナライザーの内容はカスタムアナライザー内に自作する必要があります
カスタムアナライザーの解説

シノニムについて

上記で辞書、辞書言ってたのがこのシノニムです
ある単語の読み替えとして設定可能な辞書機能となります
現状LightningSearchはこのシノニムに頼っているところが大きいです
シノニムの解説

ここまで愚痴のように書き殴ってきましたがAzure Cognitive Searchの特性はわかっていただけたでしょうか・・・
次章からはAmazon OpenSearchについてAWSの営業さんとお話しすることができたので少し比較をしてみましょう
こちらはPoCなどして確認したわけではないのでもし乗り換えた場合に同様の沼にハマることがあるかもしれませんが話を聞く限り夢が広がりんぐな感じでした

Amazon OpenSearchについて

Azure Cognitive Searchと他の検索サービスの比較をしてみようとGoogleさん、Amazonさんに焦点をあててみました
※比較といってもAmazon OpenSearchについてはAWS担当者とのお話、資料ベースなので私の個人的主観となります
しかしECといえばAmazonさんということでAmazon OpenSearchを対象としてみました

Amazon OpenSearchとは

もともとElasticSeachとして開発されていたものが独立してAmazon OpenSearchとして独立したものになります
Amazon OpenSearchの解説

Azure Cognititve SearchとAmazon OpenSearchとの比較

インデックスへの登録方法

サービス 説明
Azure Cogtinive Search データソース(ファイルやSQLServer)を指定することで更新されたデータを定期的(最短15分)ごとにインデックス反映される
Amazon OpenSearch RestAPIを使ってJSONでインデックス反映
RestAPIを定期的に実行できる環境が必要

検索精度など

サービス 説明
Azure Cogtinive Search トークナイザーに合致すれば可能
半角文字はワイルドカード指定をしないとヒットしないものが多い
チューニングはAPIをコールするプログラムを修正する必要あり
あいまい検索に弱い
Amazon OpenSearch 半角文字にも強く前方一致検索が可能
1回の検索でオートコンプリート検索も可能
プログラムソースの修正なしにチューニング可能
あいまい検索に弱い

サポート面など

サービス 説明
Azure Cogtinive Search テクニカルサポートへの申請経路が複雑で回答を得るまで時間がかかる
改善方法を提供してくれる
Amazon OpenSearch テクニカルサポートへの申請が容易
改善方法の提供、実現方法の提案をシステムに合わせて提供してくれる

さいごに

ここまでLightningSearchを構築するにあたりAzure Cognitive Searchを利用してきました
その中で開発チームが手探りで構築した内容を記載してきました
そのため視野が狭くなっていて「こうやればもっと改善できる」案があるかもしれません
時間も工数も足りない開発チームですが常に前を向いて対応していきます
こんな開発チームと共に戦ってくれる仲間をいつでも募集しています!

俺たちの戦いはこれからだ!

ご愛読ありがとうございました
ガミさん先生の次回作にご期待ください!