検索の詳細
前回の記事ではZend_Search_Luceneのfindメソッドを利用して検索をすることには触れました。このfindメソッドにクエリ条件を表すテキスト、ないしZend_Search_Lucene_Search_Queryのオブジェクトを渡し、その戻り値が検索の結果となっていました。
ここではこの検索を、さらに細かく制御する方法について見ていきます。具体的には検索結果の並び順と、クエリ生成の詳細について説明します。
検索結果の並び順
検索の結果は、デフォルトでは検索クエリに対しての各文書の「点数」(スコア)の順に並べて表示されます。この点数は、例えばクエリに含まれる単語の文書中での登場頻度などのいくつかの要素によって計算されたもので、クエリに対して文書がどれだけ合っているかを示しています。
検索結果の並び順はZend_Search_Luceneのfindメソッドに、追加で引数を与えることで変更することができます。追加で与える引数は、並べ替えに使うフィールド名と比較の方法、並び順の順で指定します。
$hits = $index->find($query [,field名1 [,比較の方法1 [,並び順1]]]
[,field名2 [,比較の方法2 [,並び順2]]]
[,field名3 [,比較の方法3 [,並び順3]]]
...);
比較方法、並び順の指定には、それぞれ以下の値を指定します。
| 設定値 | 概要 |
| SORT_REGULAR(デフォルト) | 通常の比較を行う |
| SORT_STRING | 文字列として比較を行う |
| SORT_NUMERIC | 数値として比較を行う |
| 設定値 | 概要 |
| SORT_ASC(デフォルト) | 昇順 |
| SORT_DESC | 降順 |
具体的なコードは、以下に示します。
// (1) - フィールド path を文字列として比較し、昇順に並べる
$hits = $index->find($query, 'path', SORT_STRING, SORT_ASC);
// (2) - 上に追加で、スコアを数値として比較し、降順に並べる
$hits = $index->find($query, 'path', SORT_STRING, SORT_ASC,
'score', SORT_NUMERIC, SORT_DESC);
// (3) - 比較方法・順番は省略も可能
$hits = $index->find($query, 'path',
'score', SORT_NUMERIC, SORT_DESC);
このようにフィールドを追加したり、引数を省略することも可能です。
クエリの生成の詳細
ここまでの例では、検索のためのクエリは直接文字列から生成してきましたが、この方法以外にもクエリはプログラム的に生成することもできます。これは、クエリの部品ごとに一つのオブジェクトとして作成し、そのオブジェクトを組み合わせることで一つのクエリを作成する方法です。少し例を見てみましょう。
//(1)- テキストから直接生成
$hits = index->find('date:([2009-01-01 TO 2009-12-31]) AND Code*');
// ここららは上と同じ意味のクエリをプログラム的に生成
//(2)- 範囲
$fromterm = new Zend_Search_Lucene_Index_Term('2009-01-01', 'date');
$to_term = new Zend_Search_Lucene_Index_Term('2009-12-31', 'date');
$range = new Zend_Search_Lucene_Search_Query_Range($from_term, $to_term, true);
//(3)- ワイルドカード
$pattern_term = new Zend_Search_Lucene_Index_Term('Code*');
$wildcard = new Zend_Search_Lucene_Search_Query_WildCard($pattern_term);
//(4)- 組合せ
$query = Zend_Search_Lucene_Search_Query_Boolean();
$query->addSubquery($range, true);
$query->addSubquery($wildcard, true);
$hits = $index->find($query);
リスト5で紹介した(1)と(2)- (4)は、どちらも同じ意味で、
- 「date」フィールドが2009年1月1日から2009年12月31日の間で、
- いずれかのフィールドに「Code」から始まる単語が含まれている
文書に合うクエリとなっています。このうち、(1)は直接テキストからの生成、(2)~(4)はプログラム的な生成になっています。
このように、テキストから直接でもプログラム的な方法でも同じクエリを生成することができます。原則としては
- 人間が直接入力したクエリはテキストから解析
- それ以外の場合はプログラム的な方法
でクエリを生成することが奨励されています。
プログラム的なクエリの生成に関するクラスは次のようなものがあります。
| クラス名 | コンストラクタ引数 | 説明 |
| Term | $word, $field | 特定の単語$wordをフィールド$fieldに含んでいるかを調べる。$filedは省略可能で、標準ではすべての$fieldについてみる |
| Fuzzy | $term, $similarity | Termオブジェクト$termに似ている文字列があるかを調べる。$similarityはどこまで似ているかものも許容するかを、0から1の間の小数で指定する |
| Range | $from, $to, $include_edges | Termオブジェクト$fromからTermオブジェクト$toまでの範囲にある文字列があるかを調べる。$include_edgesは末端を含むかどうかの指定 |
| Wildcard | $term | Termオブジェクト$termにあるワイルドカードを解釈し、あてはまる文字列があるかを調べる |
| Phrase | $terms, $offsets, $field | 配列$termsに含まれるTermオブジェクトが$offsetsで指定された順番でフィールド$field内に並んでいるかを調べる |
| MultiTerm | $terms, $signs | 配列 $term 内のTermオブジェクトが文書に含まれているかを調べる。$termsと$signsは両方とも配列で、中は true, false か null |
| Boolean | $subqueris, $signs | 複数のクエリを組み合わせる。$termsと$signsは両方とも配列で、中は true, false か null |
このうち、Phraseは$termsでTermを、$offsetsでその位置を指定します。例えば「PHP is * to」という並び(「*」は何でも良い)を調べたい場合はリスト6のように書くことができます。
$phrase =
new Zend_Search_Lucene_Search_Query_Phrase(array('PHP', 'is', 'to'),
array( 0, 1, 3));
ここで「*」に相当する「2」番目は飛ばし、「to」に対応する部分は 3になっています。
また、MultiTermとBooleanでは$signsで各要素が必要なのか(true)、あった場合はマッチしないのか(false)、それともどちらでも良いのか(null)を指定することができます。例えば、「PHP」という単語を含んでおり、「is」という単語を含んでいない文書を調べたい場合にはリスト7のように記述します。
$phrase =
new Zend_Search_Lucene_Search_Query_Multiterm(array('PHP', 'is', 'to'),
array( true, false, null));
なお、ここで「null」が指定されている「to」は、検索結果を絞り込むのには利用されませんが、並び換えのためのスコアを計算するためには利用されます。
