CodeZine(コードジン)

特集ページ一覧

Zend Framework入門(19):
PHPによるテキスト検索エンジンの活用 - Zend_Search_Lucene -

Zend Frameworkによる実践的なPHPアプリケーション開発 19

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2009/05/15 14:00
目次

索引の作成

 Zend_Search_Luceneでは、検索を実行するために必要な情報をあらかじめ索引という形で作成しておきます。この索引はZend_Search_Luceneのインスタンスそのもので、そこに検索対象の文書を登録していくことで索引を作成します。

 ここで登録する文書は、生のテキストデータそのものではなく、含まれている単語や構造などが解析してあるものを登録します。実はここがミソで、この「解析」の結果はユーザーが準備するため、どのような文書をどのように検索できるようにするかは完全にユーザーの側で決めることができます(決める必要がある、とも言えます)。

 索引の構造は図1のようになっています。このように、索引には文書がいくつか登録されており、それぞれの文書の中にはその文書にどのような情報が含まれているかが、フィールドという単位で整理して記録されています。

図1:索引の構造
図1:索引の構造

 それぞれのフィールドには、どのような検索に合致するかの情報や、解析前の生のデータが登録されています。

索引の操作

 索引を作成・操作するにはZend_Search_Luceneのメソッドを利用します。一番最初に、まず索引を作成する際には静的メソッドのZend_Search_Lucene::createを利用しZend_Search_Luceneのインスタンスを作ります。既に作成した索引を次回以降使うには、同じく静的メソッドのZend_Search_Lucene::openを使用します。このZend_Search_Luceneのインスタンスに対してaddDocumentメソッドで文書を登録したり、findメソッドで検索したりする、というのが基本的な使い方です。

[リスト3]索引の利用の方法
(1)索引の作成
<?php
$index = Zend_Search_Lucene::create('索引の名前');
//$doc1, $doc2... に文書を作成
$index->addDocument($doc1);
$index->addDocument($doc2);
...

(2)索引への文書の追加
<?php
$index = Zend_Search_Lucene::open('索引の名前');
//$doc1, $doc2... に文書を作成
$index->addDocument($doc1);
$index->addDocument($doc2);
...

(3)検索の実行
<?php
$index = Zend_Search_Lucene::open('索引の名前');
//$query にクエリを作成
$hits = $index->find($query);
...

 ここで、Zend_Search_Luceneの主なメソッドの一覧を示しておきます。

Zend_Search_Luceneクラスの主なメソッド
分類 メソッド 引数 説明
静的 create $directory $directoryという名前の索引を作成し、それを返す。
open $directory $directoryという名前の索引を開き、それを返す。
setDefaultSearchField $fieldName 検索対象のフィールドを$fieldNameに指定する。$fieldNameは標準はnullで、その場合にはすべてのフィールドが検索対象となる。
getDefaultSearchField (なし) 検索対象のフィールドを返す。
インスタンス getDirectory (なし) 索引の名前を返す。
numDocs (なし) この索引に実際に登録されている文書の数を返す。
count (なし) この索引に登録されている文書の数を、既に削除したものも含めて返す。
maxDoc (なし) この索引に登録されている文書のIDの最大値より、一つ大きい値を返す。
isDeleted $id IDが$idである文書が削除されているかを調べる。
find $query 検索を実行する
getFieldNames $indexed 登録されているフィールドの名前を、配列として返す。
addDocument $document 文書$documentを登録する。
getDocument $id IDが$idである文書を返す。
delete $id IDが$idである文書を削除する。

 主なメソッドだけでも結構ありますが、基本的な使い方をする分には静的メソッドのcreateopen、インスタンスメソッドのaddDocumentだけで、一通りのことはできます。

文書の操作

 次に、索引に登録する文書について見ていきます。先程も述べたとおり、ここで言う文章は生のデータそのものではなく、データを検索に便利なように加工したものをフィールドという単位で整理したものになっています。

 例えば写真を整理するための索引を作ろうとしているとしましょう。写真のデータ自体は別のウェブサーバに置きますが、写真に関するメモや写真のサムネイルは索引に登録するとして、必要そうな情報を表にしてみました。

写真を登録する場合のフィールド設定の例
項目 説明 検索対象 データを格納 文として解析
location 撮影した場所 ×
date 撮影した日付 ×
url 写真のURL × ×
thumbnail サムネイル × ×
note メモ

 ここで、必要な情報の項目一つが文書のフィールドに対応します。Zend_Search_Luceneでは、サムネイルのようにバイナリデータを格納するフィールドも作成することもできれば、URLのように検索の対象としない情報を格納するためのフィールドを準備することもできます。

 また、メモは文章になっているので検索する場合には単語に分ける必要がありますが、そのような処理を行うかも指定することもできます。なお、ここでは登場しませんが、「データを格納しない」フィールドも作成することができます。これは、例えば巨大なHTMLファイルに対応する文書を作成する場合、そのHTMLファイルを索引に登録してしまうと索引のファイルサイズが大きくなり過ぎてしまうため、検索用のデータのみを登録して生データを索引に登録しないということも可能になっているのです。

 このような文書を作成するサンプルコードをリスト4に示します。

[リスト4]文書の作成(make_index.php)
<?php
require_once 'Zend/Search/Lucene.php';

//文字コードに関するおまじない(次回説明)
Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8());

// (1) - 索引インスタンスの作成
$index = Zend_Search_Lucene::create('codezine-index');

// (2) - 文書の作成
// インスタンスの作成
$doc = new Zend_Search_Lucene_Document();
// フィールドの登録
$doc->addField(Zend_Search_Lucene_Field::keyword("location",
                                                 "Here"));
$doc->addField(Zend_Search_Lucene_Field::keyword("date",
                                                 "2009-01-01"));
$doc->addField(Zend_Search_Lucene_Field::unIndexed("url",
                                                   "http://localhost/pics/01.jpg"));
//サムネイルを登録する場合には下のようにします
//(今回は画像ファイルを準備していないのでコメントアウトしています)
//$doc->addField(Zend_Search_Lucene_Field::binary("thumbnail", $thumbnail);
$doc->addField(Zend_Search_Lucene_Field::text("note",
                                              "Took for CodeZine article.");

// (3) - 索引へ文書の登録
$index->addDocument($doc);
...

 文書の作成はリスト4の(2)で行っており、Zend_Search_Lucene_Documentのインスタンスを作成した後、addFieldメソッドで順番にフィールドを登録しています。各フィールドはZend_Search_Lucene_Fieldの静的メソッドを利用して作成しています。

Zend_Search_Lucene_Documentクラスのメソッド
メソッド 引数 説明
__get $offset (文書変数)->(フィールド名)という形式でフィールドにアクセスできる。
addField $field フィールド$fieldを追加する。
getFieldNames (なし) 登録されているフィールドの名前の配列を返す。
getField $fieldName 名前が$fieldNameであるフィールドを返す。
getFieldValue $fieldName 名前が$fieldNameであるフィールドの中身のテキストを返す。
getFieldUtf8Value $fieldName 名前が$fieldNameであるフィールドの中身のテキストをUTF-8で返す。

 またZend_Search_Lucene_Fieldには次のようなメソッドがあります。

Zend_Search_Lucene_Fieldクラスのメンバ
分類 メンバ 引数 説明
静的メソッド keyword $name, $value, $encoding 名前$nameで値が$valueのフィールドを作成する。このフィールドは検索対象で、値も記録され、値は単語として処理される。
unIndexed $name, $value, $encoding 名前$nameで値が$valueのフィールドを作成する。このフィールドは検索対象ではないが、値は記録される。また、値は文章として処理される。
binary $name, $value, $encoding 名前$nameで値が$valueのフィールドを作成する。このフィールドは検索対象ではないが、値は記録される。値はバイナリデータとして処理される。
text $name, $value, $encoding 名前$nameで値が$valueのフィールドを作成する。このフィールドは検索対象で、値も記録され、値は文章として処理される。
unStored $name, $value, $encoding 名前$nameで値が$valueのフィールドを作成する。このフィールドは検索対象だが、値も記録されない。値は文章として処理される。
プロパティ name (なし) このフィールドの名前。
value (なし) このフィールドの値。
isStored (なし) 値が記録されているか。標準ではfalse。
isIndexed (なし) 検索対象か。標準ではtrue。
isTokenized (なし) 文章として処理されるか。標準ではtrue。
インスタンスメソッド getUtf8Value (なし) 値をUTF-8に変換して返す。

 上の例では使用しませんでしたが、unStored静的メソッドが「値は記録されないが検索対象となるフィールド」を作成するための静的メソッドになっています。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Zend Framework入門

もっと読む

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト 風田 伸之(カゼタ ノブユキ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5