1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20854 -->
4 <sect1 id="zend.search.lucene.searching">
5 <title>インデックスの検索</title>
7 <sect2 id="zend.search.lucene.searching.query_building">
11 インデックスを検索するには二通りの方法があります。
12 クエリパーサを使用して文字列からクエリを作成する方法と、
13 <classname>Zend_search_Lucene</classname> <acronym>API</acronym> を使用して独自のクエリを作成する方法です。
17 提供されているクエリパーサを使用する前に、以下の点を考慮してください。
22 プログラムで生成したクエリ文字列をクエリパーサに渡そうとしているなら、
23 クエリ <acronym>API</acronym> を使用してクエリを直接作成すべきです。言い換えると、
24 クエリパーサというのは人間が入力したテキストのために設計されたものであり、
25 プログラムが生成したテキストのためのものではないのです。
30 トークン化されていないフィールドについては、
31 クエリパーサを使用するよりも直接クエリに追加するほうが適しています。
32 フィールドの値がアプリケーションによって生成されるのなら、
33 フィールドのクエリ条件についても自動処理で作成すべきです。
34 クエリパーサが使用している解析器は、人間が入力したテキストを
36 日付やキーワードなどのプログラムが生成した値は、
37 クエリ <acronym>API</acronym> で追加しなければなりません。
43 テキストで入力された内容はクエリパーサを使用すべきでしょう。
44 その他のフィールド、例えば範囲指定やキーワードなどについては、
45 クエリ <acronym>API</acronym> に直接渡すようにしましょう。
46 限られた内容、例えばプルダウンメニューで選択するフィールドは、
48 その代わりに、TermQuery 条件として使用します。
53 論理クエリにより、複数のクエリをひとつにまとめることができます。
54 これは、クエリ文字列で定義されるユーザ検索に条件を追加するための最良な方法です。
62 どちらの方法を使用したとしても、インデックスを検索する <acronym>API</acronym> メソッドは同じです。
65 <programlisting language="php"><![CDATA[
66 $index = Zend_Search_Lucene::open('/data/my_index');
71 <methodname>Zend_Search_Lucene::find()</methodname> メソッドは、
72 入力の型を自動的に判別し、クエリパーサを使用して文字列から
73 <classname>Zend_Search_Lucene_Search_Query</classname> オブジェクトを作成します。
77 重要なのは、クエリパーサは標準の解析器を使用してクエリ文字列をトークン化するということです。
78 インデックス化されたテキストに対するすべての変換は、クエリ文字列エントリに対しても行われます。
81 小文字変換を行うことで大文字小文字を区別しない検索を行えるようにしたり、
82 ストップワードを取り除いたりといったさまざまなことを行います。
85 それに対して、<acronym>API</acronym> メソッドは単語の変換やフィルタリングを行いません。これは、
86 コンピュータが生成したフィールドやトークン化されていないフィールドに適しています。
89 <sect3 id="zend.search.lucene.searching.query_building.parsing">
90 <title>クエリのパース</title>
92 <methodname>Zend_Search_Lucene_Search_QueryParser::parse()</methodname>
98 このオブジェクトをクエリ作成 <acronym>API</acronym> メソッドで使用し、
99 ユーザが入力したクエリと機械が生成したクエリを結合します。
104 トークン化されたいないフィールドを検索する唯一の方法となることもあります。
106 <programlisting language="php"><![CDATA[
107 $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
109 $pathTerm = new Zend_Search_Lucene_Index_Term(
110 '/data/doc_dir/' . $filename, 'path'
112 $pathQuery = new Zend_Search_Lucene_Search_Query_Term($pathTerm);
114 $query = new Zend_Search_Lucene_Search_Query_Boolean();
115 $query->addSubquery($userQuery, true /* required */);
116 $query->addSubquery($pathQuery, true /* required */);
118 $hits = $index->find($query);
123 <methodname>Zend_Search_Lucene_Search_QueryParser::parse()</methodname>
124 メソッドはオプションのパラメータでエンコーディングを受け取ることができます。
125 ここで、クエリ文字列のエンコーディングを指定します。
126 <programlisting language="php"><![CDATA[
127 $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr,
133 エンコーディングを省略した場合は、現在のロケールを使用します。
137 デフォルトのクエリ文字列エンコーディングを
138 <methodname>Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding()</methodname>
140 <programlisting language="php"><![CDATA[
141 Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-5');
143 $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
148 <methodname>Zend_Search_Lucene_Search_QueryParser::getDefaultEncoding()</methodname>
149 は、デフォルトのクエリ文字列エンコーディングを返します
150 (空文字列は "現在のロケール" を表します)。
155 <sect2 id="zend.search.lucene.searching.results">
158 検索結果は <classname>Zend_Search_Lucene_Search_QueryHit</classname> オブジェクトの配列となります。
159 各オブジェクトは、2 つのプロパティを保持しています。
160 <code>$hit->id</code> がインデックス内のドキュメント番号、
161 <code>$hit->score</code> が検索結果のスコアを表します。
162 結果はスコア順に並べられます (スコアの高い結果が最初になります)。
166 <classname>Zend_Search_Lucene_Search_QueryHit</classname> オブジェクトでは、
167 検索結果としてヒットした <classname>Zend_Search_Lucene_Document</classname>
170 title と author の 2 つのフィールドが含まれています。
172 <programlisting language="php"><![CDATA[
173 $index = Zend_Search_Lucene::open('/data/my_index');
175 $hits = $index->find($query);
177 foreach ($hits as $hit) {
185 保存されたフィールドは、常に UTF-8 エンコーディングで返されます。
190 <classname>Zend_Search_Lucene_Search_QueryHit</classname> から元の <classname>Zend_Search_Lucene_Document</classname>
194 インデックスオブジェクトの <code>getDocument()</code>
195 メソッドを使用し、その <code>getFieldValue()</code>
198 <programlisting language="php"><![CDATA[
199 $index = Zend_Search_Lucene::open('/data/my_index');
201 $hits = $index->find($query);
202 foreach ($hits as $hit) {
203 // ヒットした結果の Zend_Search_Lucene_Document オブジェクトを返します
204 echo $document = $hit->getDocument();
206 // Zend_Search_Lucene_Document から
207 // Zend_Search_Lucene_Field オブジェクトを返します
208 echo $document->getField('title');
210 // Zend_Search_Lucene_Field オブジェクトを値を文字列で返します
211 echo $document->getFieldValue('title');
213 // getFieldValue() と同じです
214 echo $document->title;
218 <classname>Zend_Search_Lucene_Document</classname> オブジェクトで使用可能なフィールドは、
219 インデックス化の際に決まります。ドキュメントのフィールドは、
220 インデックス化用アプリケーション (例えば LuceneIndexCreation.jar)
221 によってインデックス化、あるいはインデックス化して保存されます。
225 ドキュメントを識別するフィールド (例では 'path')
226 もインデックス化して取得できるようにしなければならないことに注意しましょう。
230 <sect2 id="zend.search.lucene.searching.results-limiting">
234 検索処理の中でいちばん時間がかかるのが、スコアの計算です。
235 検索結果の数が多い (数万件程度) 場合、これには数秒程度かかることもあります。
239 <classname>Zend_Search_Lucene</classname> では、結果セットの件数を制限するためのメソッドとして
240 <code>getResultSetLimit()</code> と
241 <code>setResultSetLimit()</code> を用意しています。
242 <programlisting language="php"><![CDATA[
243 $currentResultSetLimit = Zend_Search_Lucene::getResultSetLimit();
245 Zend_Search_Lucene::setResultSetLimit($newLimit);
247 0 (デフォルト値) は、'制限しない' という意味です。
251 このメソッドが返す結果は、'スコアの高いほうから N 件' ではなく
254 しかし、返される結果はスコア順 (あるいはその他指定した順)
261 <sect2 id="zend.search.lucene.searching.results-scoring">
262 <title>結果の重み付け</title>
264 <classname>Zend_Search_Lucene</classname> は、Java Lucene と同じ重み付けアルゴリズムを使用します。
265 検索結果に一致したものが、デフォルトで重み順に並べ替えられます。スコアの高いものが先頭となり、
266 スコアの高いもののほうが低いものよりクエリにマッチするようになります。
270 大雑把に言うと、文書の中に検索語句が頻繁に登場するほどスコアが高くなります。
274 検索結果のスコアを取得するには <code>score</code> プロパティを使用します。
276 <programlisting language="php"><![CDATA[
277 $hits = $index->find($query);
279 foreach ($hits as $hit) {
287 <classname>Zend_Search_Lucene_Search_Similarity</classname> クラスです。詳細は
288 <link linkend="zend.search.lucene.extending.scoring">拡張性
289 - 重み付けのアルゴリズム</link> を参照ください。
294 <sect2 id="zend.search.lucene.searching.sorting">
295 <title>検索結果の並べ替え</title>
297 検索結果は、デフォルトではスコアで並べ替えられます。
298 これを変更するには、並べ替え用の (ひとつあるいは複数の)
299 フィールドと並べ替えの形式、そして並べ替えの方向をパラメータで指定します。
303 <code>$index->find()</code> のコール時に、オプションのパラメータを指定できます。
304 <programlisting language="php"><![CDATA[
305 $index->find($query [, $sortField [, $sortType [, $sortOrder]]]
306 [, $sortField2 [, $sortType [, $sortOrder]]]
312 <code>$sortField</code> は、結果の並べ替えを行う保存されたフィールドの名前です。
316 <code>$sortType</code> は省略可能です。
317 <code>SORT_REGULAR</code> (通常の並べ替え。デフォルト)、
318 <code>SORT_NUMERIC</code> (数値として並べ替え)、
319 <code>SORT_STRING</code> (文字列として並べ替え) のいずれかとなります。
323 <code>$sortOrder</code> は省略可能です。
324 <code>SORT_ASC</code> (昇順で並べ替え。デフォルト)、
325 <code>SORT_DESC</code> (降順で並べ替え) のいずれかとなります。
330 <programlisting language="php"><![CDATA[
331 $index->find($query, 'quantity', SORT_NUMERIC, SORT_DESC);
333 <programlisting language="php"><![CDATA[
334 $index->find($query, 'fname', SORT_STRING, 'lname', SORT_STRING);
336 <programlisting language="php"><![CDATA[
337 $index->find($query, 'name', SORT_STRING, 'quantity', SORT_NUMERIC, SORT_DESC);
342 デフォルト以外の並び順を使用する際には注意しましょう。
343 並べ替えのためにはドキュメント全体をインデックスから読み込む必要があり、
344 検索のパフォーマンスが著しく低下してしまいます。
348 <sect2 id="zend.search.lucene.searching.highlighting">
349 <title>検索結果の強調</title>
351 <classname>Zend_Search_Lucene</classname> では、2 とおりの方法で検索結果を強調させることができます。
354 まず最初の方法が、<classname>Zend_Search_Lucene_Document_Html</classname> クラス
355 (詳細は <link linkend="zend.search.lucene.index-creation.html-documents">HTML ドキュメントの節</link>
356 を参照ください) を用いて次のようにすることです。
357 <programlisting language="php"><![CDATA[
361 * @param string|array $words
362 * @param string $colour
365 public function highlight($words, $colour = '#66ffff');
367 <programlisting language="php"><![CDATA[
369 * テキストを、指定したビューヘルパーあるいはコールバック関数で強調する
371 * @param string|array $words 強調したい単語。配列あるいは文字列で指定します
372 * @param callback $callback コールバックメソッド。テキストの変換 (強調) に使用します
373 * @param array $params コールバックのパラメータとして渡す配列
374 * (最初の必須パラメータは、強調させる HTML 片となります)
376 * @throws Zend_Search_Lucene_Exception
378 public function highlightExtended($words, $callback, $params = array())
382 強調方法をカスタマイズするには <code>highlightExtended()</code>
383 メソッドにコールバックを指定して使用します。このコールバックは、ひとつ以上のパラメータを受け取ります
384 <footnote><para>最初のパラメータは強調対象の HTML 片、
385 そしてその他のパラメータはコールバックの振る舞いによって変わります。
386 返り値は、強調済みの HTML 片となります。</para></footnote>。
387 あるいは、<classname>Zend_Search_Lucene_Document_Html</classname> クラスを継承して
388 <code>applyColour($stringToHighlight, $colour)</code> メソッドを再定義することもできます。
389 このメソッドは、デフォルトの強調コールバックとして用いられるものです。
392 どちらの場合についても、返される HTML は自動的に正しい <acronym>XHTML</acronym> 形式に変換されます。
397 <link linkend="zend.view.helpers">ビューヘルパー</link> も、ビュースクリプトのコンテキストでコールバックとして使えます。
398 <programlisting language="php"><![CDATA[
399 $doc->highlightExtended('word1 word2 word3...', array($this, 'myViewHelper'));
403 強調した結果を取得するには <code>Zend_Search_Lucene_Document_Html->getHTML()</code> メソッドを使用します。
408 強調処理は、現在の解析器を使って行われます。つまり、解析器が理解するすべての形式の単語が強調されます。
411 たとえば、大文字小文字を区別しない解析器を使っている場合に 'text' を強調するよう指定すると、
412 'text' や 'Text' そして 'TEXT' といった単語も強調されます。
415 同様に、語幹抽出機能を持つ解析器を使っている場合に 'indexed' を強調するよう指定すると、
416 'index' や 'indexing' そして 'indices' といった単語も強調されます。
419 一方、現在の解析器が処理をスキップするような単語
420 (短い単語に対するフィルタが解析器に適用されている場合など)
427 <code>Zend_Search_Lucene_Search_Query->highlightMatches(string $inputHTML[, Zend_Search_Lucene_Search_Highlighter_Interface $highlighter])</code>
429 <programlisting language="php"><![CDATA[
430 $query = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
431 $highlightedHTML = $query->highlightMatches($sourceHTML);
436 デフォルトの HTML ドキュメントエンコーディングです。
437 省略した場合は、Content-type HTTP-EQUIV meta タグを使用します。
441 <classname>Zend_Search_Lucene_Search_Highlighter_Interface</classname>
442 インターフェイスを実装したオブジェクトです。
443 <programlisting language="php"><![CDATA[
444 interface Zend_Search_Lucene_Search_Highlighter_Interface
449 * @param Zend_Search_Lucene_Document_Html $document
451 public function setDocument(Zend_Search_Lucene_Document_Html $document);
456 * @return Zend_Search_Lucene_Document_Html $document
458 public function getDocument();
461 * 指定した単語を強調します (サブクエリ単位でこのメソッドが起動されます)
463 * @param string|array $words 強調したい単語。配列あるいは文字列で指定します
465 public function highlight($words);
468 ここでの <classname>Zend_Search_Lucene_Document_Html</classname> オブジェクトは、
469 <classname>Zend_Search_Lucene_Search_Query->highlightMatches()</classname> メソッドに渡された
470 HTML から作成されるオブジェクトです。
473 <code>$highlighter</code> パラメータを省略すると、
474 <classname>Zend_Search_Lucene_Search_Highlighter_Default</classname>
475 オブジェクトのインスタンスを作成してそれを使用します。
478 <code>highlight()</code> メソッドはサブクエリ単位で起動されるので、
479 サブクエリ単位で異なる強調処理を行うことができます。
482 実際のところ、デフォルトの処理は定義済みの色テーブルを使用しているだけです。
483 自前の強調処理を実装することもできますし、デフォルトの処理を継承して色テーブルだけを再定義することもできます。
486 <code>Zend_Search_Lucene_Search_Query->htmlFragmentHighlightMatches()</code>
487 も同じような動きをします。唯一の違いは、入力を受け取って、
488 <>HTML>, <HEAD>, <BODY> tags タグを含まない HTML 片を返すことです。
489 それでも、返される HTML 片は自動的に正しい <acronym>XHTML</acronym> に変換されます.