2017.12.15 Friday
スポンサーサイト
一定期間更新がないため広告を表示しています
| スポンサードリンク | - | | - | - |
関口宏司のLuceneブログOSS検索ライブラリのLuceneおよびそのサブプロジェクト(Solr/Tika/Mahoutなど)について
2007.08.27 Monday
クチコミの評判の悪い店のランキングを下げる
私はLuceneおよびSolr(最近はこちらの方がLuceneよりも多い)のコンサルティングやサポートを顧客に提供することを生業としている。
いろいろな顧客の話を聞いていると、ランキング(検索結果のドキュメントの表示順のこと)を意図的に操作して出力したい、という要望が予想以上に多いのに驚く。 たとえば、「自分の家から一番近いレストランを探す(地理検索、地図検索)」で書いたようなある場所(現在地や最寄り駅)から近い順にお店情報を表示する、などである。 あるいは、「FunctionQueryの実用的なサンプル」で紹介したように、検索語の出現位置でランキングを操作する、という要求もあった。 この他にもサイト運営者への「掲載料」の支払い額で企業がランクわけがされていて、掲載料をたくさん支払っている優良顧客の情報をtf*idfとは関係なく上位に持ってきてほしい、という要望も意外に多い。 このような、ランキングへの顧客の多様な要求に柔軟に対応できるのもLuceneの隠れた大きな特徴のひとつである。 今回はBoostingQueryを使って「クチコミの評判の悪い店」のランキングを意図的に下げる、ということを実装してみる。 BoostingQueryとは BoostingQueryは、オリジナルのQueryインスタンスorigQueryに、マイナス評価を与えるnegativeQueryを組み合わせ、さらにマイナス評価に該当したときに指定した降格係数(まったくの私の造語だが、1未満のboost値のこと)を掛けて最終的なスコアとするQueryである。BoostingQueryのインスタンスを得るには、降格係数をdemoteBoostとすると、次のようにプログラミングする:
あとは普通にqueryをIndexSearcherのsearch()に渡せばよい。 BoostingQueryのnegativeQueryは、仕様をちょっと聞くとBooleanQueryのMUST_NOTとなんか似ている。しかし、両者はまったく異なるものである。 BooleanQueryのMUST_NOTは、指定したQueryにヒットするドキュメントは検索結果には含まれない、まったくの「否定」となる。 一方、BoostingQueryのnegativeQueryはMUST_NOTのように「否定」ではないので、negativeQueryにヒットしたドキュメントが検索結果からはじかれる、ということはない。ただ、negativeQueryにヒットしたドキュメントのスコアはdemoteBoostの値が掛けられるのである。それにより、origQueryにヒットしたドキュメントのうち、さらにnegativeQueryに該当するドキュメントのスコアを下げることができる(あるいは、demoteBoostを1より大きくとることで、negativeQuery(この場合はpositiveQueryと呼ぶべきであろう)に該当するドキュメントのスコアを上げることができる)。 なお、BoostingQueryはLucene coreではなくcontrib/queriesにあるので、contrib/queriesよりlucene-queries-x.x.jarを持ってきてクラスパス上に配置する必要がある。 BoostingQueryのサンプルプログラム まず、次のようなサンプルドキュメントとサンプルの検索文字列を用意する:
これをBoostingQueryを使わずに普通に検索すると、次のような結果になるだろう:
スコア(検索結果の前に表示されている実数)はどちらの検索文字列でも1.0と等しくなるので、この場合のランキングはドキュメントの登録順に表示されている。そして、「まずい」や「おいしくない」というマイナス評価のドキュメントを先に登録しているので、「おいしい」や「お奨めです」より前に表示されてしまっている。 このプログラムを、demoteBoost=0.1にしたBoostingQueryを使って検索すると、次のようになる:
BoostingQueryを使った全体のプログラムは次のとおりである:
NEGATIVE_EVALSという文字列配列に「まずい」や「おいしくない」などのマイナス評価を示す文言を登録してあり、それをもとにnegativeQueryのインスタンスを作成している。当然のことながら、これらに合致しない文言は評判が悪いとは認識されない。 2007.08.17 Friday
QueryParserでMatchAllDocsQueryを使う
少し古い話になるが、Lucene 2.1からQueryParserに"*:*"という文字列を指定すると、MatchAllDocsQueryに翻訳してくれる機能が追加された:
http://issues.apache.org/jira/browse/LUCENE-723 MatchAllDocsQueryはインデックス中の全ドキュメントを取得するためのQueryである。そのものずばり「インデックス中の全ドキュメントを取得する」目的で使用できるのはもちろんのこと、MUST_NOTと共に使用して「指定した単語やフレーズを含まない全ドキュメントを取得する」のにも使用できる(Lucene本 P.194-195)。 "*:*"がMatchAllDocsQueryに解釈される様子は、次のプログラムで簡単に確認できる:
このプログラムを実行すると、次のようになる:
「安倍晋三」を含まないすべてのドキュメントを得るためのQueryを取得するには、次のようにすればよい:
2007.08.11 Saturday
WildcardTermEnumを使う
Luceneのインデックスにはフィールドごとに整理された単語帳がある。単語帳の単語はソートされた状態で格納されており、TermEnumを使ってその中の単語を列挙することができる。
次のプログラムは「通」という単語から開始してTermを列挙する例である:
TermEnumはTerm(=フィールド名+フィールド値)を列挙するものであるから、ループをまわしていくとTermがいつの間にか目的外のフィールドを指していることがありえるので、赤字の判定行が必要となる。 このプログラムをあるインデックスに対して実行すると、次のような出力が得られる:
上記のように「通」から始まり、単語帳の指定フィールドの単語が尽きるまでTermが列挙されるのがわかる。 ここでTermEnumの代わりにWildcardTermEnumを使うと「通」で開始する単語だけを列挙することが可能となる。 WildcardTermEnumは、次のように使う:
このときの出力は、次のようになる:
「前方一致」だけでなく、「後方一致」も指定可能だ:
このときの出力は、次のようになる:
|
+ Solrによるブログ内検索
+ PROFILE
+ LINKS
+ Lucene&Solrデモ
+ ThinkIT記事
+ RECOMMEND
+ RECOMMEND
Lucene in Action (JUGEMレビュー »)
Erik Hatcher,Otis Gospodnetic,Mike McCandless FastVectorHighlighterについて解説記事を寄稿しました。
+ RECOMMEND
+ SELECTED ENTRIES
+ RECENT COMMENTS
+ RECENT TRACKBACK
+ CATEGORIES
+ ARCHIVES
+ MOBILE
+ SPONSORED LINKS
|
(C) 2024 ブログ JUGEM Some Rights Reserved.
|
PAGE TOP |