関口宏司のLuceneブログ

OSS検索ライブラリのLuceneおよびそのサブプロジェクト(Solr/Tika/Mahoutなど)について
スポンサーサイト

一定期間更新がないため広告を表示しています

| スポンサードリンク | - | | - | - |
Solr あるある

弊社は Apache Solr に関する教育/コンサルティング/サポートの各サービスを提供しているが、業務を通じてユーザーによる Solr の残念な使い方に遭遇することもたびたびある。ここではそれを「Solr あるある」と総称して紹介してみよう。なお、大抵の話は Apache Lucene にも当てはまるがここでは簡単に「Solr あるある」と記載することにする。



前方一致検索、中間一致検索

フィールド f1 が abc で始まるものを検索するのに q=f1:abc* としたり、abc がフィールド f1 内に現れるものを検索するのに q=f1:*abc* とするのは誤りである。一般的に前者は前方一致検索、後者は中間一致検索などと呼ばれるが、転置インデックス方式の検索エンジンでは検索対象の最小単位が単語となり、単語の完全一致が基本となる。したがって、「前方一致検索」「中間一致検索」というような概念がない。検索対象フィールドが単語の場合は完全一致検索となるし、2単語以上のフィールドであれば中間一致検索となる。したがって、中間一致検索(単語の完全一致)をしたいのであれば、q=f1:*abc* とはせずに q=f1:abc とすればよろしい。q=f1:*abc* で検索できているように見えているのは、いろいろなパターンが考えられるが、文字列解析の過程で * が落とされて結果的に abc という単語検索になっている、などが考えられる。


では前方一致はどうだろう。前方一致検索をしたい場合は、転置インデックスの作り方を工夫する。具体的には EdgeNGramTokenizer(場面によっては EdgeNGramTokenFilter)を使ってインデックスを作成する。これを使うと、abcdefg というフィールド文字列は次のように単語分割され、インデックスが作られる。


a ab abc abcd abcde abcdef abcdefg

このフィールドに対し、abc という文字列で前方一致検索をしたければ、クエリ側はトークナイズせず、つまり KeywordTokenizer を使って(場合によっては LowerCaseFilter を組み合わせてもよい。その場合はインデックス側にも適用する。以下同じ)次のように検索する。

q=f1:abc

単語の完全一致検索が基本の検索エンジンで従来型の「前方一致検索」「中間一致検索」をしたい場合、* を使う検索は Solr あるあるであるが、気持ちはわかるが間違いである。これは次で述べる後方一致検索でも同様である。



後方一致検索

同じく、フィールド値が abc で終わる文書を探すという意味を込めて後方一致検索をしたいというので q=f1:*abc というクエリを発行するのも Solr あるあるであるが、誤りである。Lucene の転置インデックスは単語がソートされた状態で格納されていることを利用して二分探索される。したがって、単語の末尾が一致しているかどうかを確認するには、転置インデックス上の単語を総なめしなければならなくなってしまう。そのため、高速検索を信条とするLuceneにはそのような検索は用意されていない(APIを使って総なめすることは可能)。では Lucene/Solr で後方一致検索はできないのかというとそんなことはなく、「文字列を逆転させて前方一致にする」というテクニックを使う。具体的にはインデックス側、クエリ側双方で ReverseStringFilter を適用する。


インデックス側では、KeywordTokenizer+ReverseStringFilter+EdgeNGramTokenFilter を用いる。すると、abcdefg という文字列は、次のようにインデックス中に展開される。


g gf gfe gfed gfedc gfedcb gfedcba

クエリ側は KeywordTokenizer+ReverseStringFilter を適用する。すると、efg という文字列の後方一致検索は、q=f1:efg と投げればよい。すると当該フィールドで文字列が逆転された上で検索されることで、gfe がヒットする。



ファセットによる絞り込み検索で fq を使わない

ファセットによる絞り込み検索で fq を使わず、q パラメータに AND で絞り込み条件を追加していくのもよく見る Solr あるあるであるが、これも誤りである。fq による検索結果の絞り込みも、AND 条件追加による検索の絞り込みも、返される文書集合は同じである。しかし文書の順番(ランキング)を見てみれば両者は異なることがわかる。メインのクエリ(q パラメータ)に AND で絞り込み条件を追加してしまうと、それはスコア計算の対象になってしまうので、AND を使う方法だと絞り込むたびにランキングが異なってしまう。つまりユーザーから見ると、ファセットのリンクをクリックするたびに文書の表示順が異なってしまう。これではユーザーが混乱するだろう。また、filterCache がうまく使われない、という別の問題もはらんでいる。


ファセットによる絞り込み検索では、AND を使わず fq を使う、と覚えておこう。



スコアによる足切り

「スコアが0.5未満の文書は足切りして返却されないようにしたい」などといった要望も Solr あるあるであるが、これもナンセンスであり、実施しようとして奮闘すること自体、時間の無駄である。


スコア関数のパラメーターはそれがベクトル空間モデルベースの TFIDFSimilarity であれ、確率モデルベースの BM25Similarity であれ、クエリと各文書である。スコアはクエリを固定したときに、各文書に付与される当該クエリとの関連度合いを表現したものであるから、クエリが変わってしまうと相互に比較することに意味がない。クエリ A でスコア 0.4 を獲得した文書がクエリ A に非常に関連しているが、クエリ B でスコア 0.6 を獲得した文書がクエリ B にたいして関連しているとは見えない、ということがおおいにありえる。



自前のハイライト

ハイライト機能(検索キーワードを含む文書スニペットを切り出し、キーワードを太字など目立つように表示する機能)について、Solr が持っているハイライト機能を使わずに、Webアプリケーション(JavaScript含む)でがんばってしまう、というのもたまに見る Solr あるあるである。Solr にハイライト機能があることを知らずに自前で実装してしまうパターン、Solrにハイライト機能があることは知っているが、自前の方がよいと信じて自前で実装してしまうパターンがあるようだ。前者は知らなかったということでお気の毒という他ない。後者は、なぜそのような発想になるのかよくわからない。Solr のハイライト機能はそれほどよくできている。自前で頑張る方式のメリットをあえて上げるならば、たとえば、サーバ側のCPU負荷を下げるため、ユーザーのブラウザにてJavaScriptでハイライトする場合、が考えられるかもしれない。しかしそのメリットの裏で、次の機能を備える Solr の非常によくできたハイライト機能を使わないデメリットをアプリケーションに実装してしまっていることに気づいているだろうか。


  • 検索キーワードがなるべく多く含まれる任意長のスニペットを、任意の個数得ることができる。Solr ではスニペットにもスコアがつけられ、スコアの高いスニペットから返される。同じ機能をアプリケーションで頑張ろうとすると、スニペットを作成するデータソースをすべて転送してこなければならない。その転送元は Solr かもしれないし、RDB かもしれないが、Solr のハイライト機能で作成したスニペットよりも大きなサイズになることが多く、ネットワーク負荷の原因となる。
  • Solr では表記揺れを考慮した検索が可能であるが、ハイライトでも同じ表記揺れを考慮した上でハイライト表示が可能である。アプリケーションで頑張る場合は、同じ表記揺れ対応をしなければ検索にヒットしてもハイライト表示ができない場合が出てきてしまう。また対応する表記揺れルールが変わった場合、Solr でやっていれば設定ファイルの変更で検索もハイライトもどちらも対応できてしまうが、アプリケーションで頑張る方式の場合は、Solr の設定変更がアプリケーションの方に影響してしまうため管理が煩雑になる。
  • Solr のスニペットは単語境界区切りなど、自然な単位でスニペット生成ができるようになっている。さらに、Solr では検索キーワードがフレーズの場合、フレーズが一致している場合のみハイライトさせたり、単語単独でハイライトさせたりといった細かな制御が可能である。同様のことをアプリケーションでやらせようとすれば、簡易であれNLP的機能をアプリケーションに持たせなければならない。
  • Solr ではスニペットが作れない場合の代替表示を指定することができる(大抵はハイライト表示しようとする当該フィールドの先頭100文字など)。

ということで、Solr のハイライト機能は検索アプリケーションのことをよく考慮して用意されており、大変よくできている。自前で用意するというのはたいていの場合誤っていると断言できる。


なお、検索結果一覧表示時にハイライトスニペットを作成せず、ユーザーのクリックにより当該文書表示時に検索キーワードを太字など目立つように表示する機能は、ここでいうハイライト機能とは異なる。ここでいうハイライト機能は、検索結果一覧表示時に、ユーザーに適切な文書をすばやく選択してもらうためのアシスト機能に相当する。ユーザーはハイライトスニペットを、文書をクリックするかどうかの参考にするため、Solr のハイライト機能はぜひ積極的に利用しよう(ただし、商品の写真を検索結果一覧に表示するようなECサイトの検索アプリのようなものは除く)。



ここで上げた以外にも、RDB の正規化されたテーブルをそのまま Solr のインデックススキーマにマッピングし Solr の JOIN を使うあるあるや、親子階層のファセットを自前で頑張るあるある、クエリを投げる際に常にダブルクォーテーションでくくってしまうあるあるなどもある。



Solr は OSS になって10年を超えるソフトウェアとなった。機能も十分豊富で、やりたいことの多くはすでに Solr が持っていることも多い。アプリケーションで頑張る前にぜひマニュアルや書籍等で該当する機能がないか、使い方がアーキテクチャに沿ったものになっているか、今一度考えてみることをお勧めしたい。



さて、今年はおそらく本記事が最後となるでしょう。更新頻度が少なくなったのにもかかわらず、本年もご愛読いただきありがとうございました。皆様、よいお年をお迎えください!

| 関口宏司 | Solr | 18:56 | comments(5) | trackbacks(0) |
+ Solrによるブログ内検索
+ PROFILE
     12
3456789
10111213141516
17181920212223
24252627282930
31      
<< December 2017 >>
+ LINKS
検索エンジン製品 - 比較のポイント
商用検索エンジンを購入した企業担当者は読まないでください。ショックを受けますから・・・
>>製品比較 10のポイント
+ Lucene&Solrデモ
+ ThinkIT記事
+ RECOMMEND
Apache Solr入門 ―オープンソース全文検索エンジン
Apache Solr入門 ―オープンソース全文検索エンジン (JUGEMレビュー »)
関口 宏司,三部 靖夫,武田 光平,中野 猛,大谷 純
+ RECOMMEND
Lucene in Action
Lucene in Action (JUGEMレビュー »)
Erik Hatcher,Otis Gospodnetic,Mike McCandless
FastVectorHighlighterについて解説記事を寄稿しました。
+ RECOMMEND
+ SELECTED ENTRIES
+ RECENT COMMENTS
+ RECENT TRACKBACK
+ CATEGORIES
+ ARCHIVES
+ MOBILE
qrcode
+ SPONSORED LINKS