[Yii Framework] Membuat Search Engine Dengan Zend Search Lucene

Anda ingin membuat fitur pencarian cepat pada website anda? Ada banyak cara anda bisa menggunakan Apache Solr seperti yang sudah pernah saya posting sebelumnya, menggunakan Sphinx, atau menggunakan Apache Lucene.. Untuk tutorial kali ini saya akan post membuat pencarian cepat menggunakan Apache Lucene, tetapi lucene yang dibuat oleh Zend Framework agar kita lebih mudah integrate nya pada PHP. Hal ini sendiri sebenarnya sudah ada pada wiki Yii Framework disini, tapi ga ada salahnya kan saya kemas ulang dan tambahkan sedikit hal disana..

Pertama-tama yang perlu anda lakukan adalah mendownload zend framework disini. Dan sebelum memulai, saya asumsikan anda sudah memahami masalah zend search lucene. Setelah anda mendownload zend lucene, extract file donlotan. Buat folder baru pada direktori “namaAplikasi/protected/”  misal saya beri nama “ZF”. Kemudian pindahkan hasil extractan tadi ke dalam direktori “namaAplikasi/protected/ZF”. Untuk memanggil dan menggunakan fungsi-fungsi yang ada pada zend search lucene, masukkan code berikut pada bagian atas controller yang ingin menggunakan Zend search lucene :

Yii::import('application.ZF.*');
require_once('Zend/Search/Lucene.php');

Code di atas digunakan untuk mendefinisikan file Zend  Framework agar dapat kita gunakan dalam aplikasi kita. Lalu bagaimana melakukan index data yang ada pada database kita? Saya asumsikan kita akan mengindex semua data pada suatu tabel yang kita miliki. Buatlah sebuah action seperti berikut :

public function actionAll()
 {
     $index = new Zend_Search_Lucene(Yii::getPathOfAlias('application.tempatSimpan'), true);

     $posts = NamaModel::model()->findAll();
     foreach($posts as $post)
     {
         $doc = new Zend_Search_Lucene_Document();

         $doc->addField(Zend_Search_Lucene_Field::Keyword('pk',CHtml::encode($post->namaAttribute1), 'utf-8')); 
         $doc->addField(Zend_Search_Lucene_Field::Text('isi',Chtml::encode($post->namaAttribute2), 'utf-8')); 
         $index->addDocument($doc);
     }
     $index->commit();
 }

Pada code di atas kita menyimpan data hasil index kita pada direktori “namaAplikasi/protected/tempatSimpan”, itu dapat dilihat dari definisi pertama fungsi zend search lucene. Kita memasukkan semua data yang ada pada tabel “Namamodel” ke dalam index lucene. Dari code tersebut yang saya index adalah field “namaAttribute1” dengan nama “pk” dan field “namaAttribute2” dengan nama “isi”.

Code di atas kita mengindex semua data dimana semua index akan di kosongkan terlebih dahulu, kemudian baru diisi kembali. Kenapa saya katakan dikosongkan? karena kita mendefinisikan ulang, tidak mengupdate. Bagaimana jika kita hanya ingin menambah satu buah data saja pada index kita? dengan kata lain kita melakukan update pada index data yang sudah ada dan menambahkan satu buah file index? Seperti berikut :

public function actionUpdateField()
 {
     $index = new Zend_Search_Lucene::open(Yii::getPathOfAlias('application.tempatSimpan'), true);

     $doc = new Zend_Search_Lucene_Document();

     $doc->addField(Zend_Search_Lucene_Field::Keyword('pk',CHtml::encode('3'), 'utf-8')); 
     $doc->addField(Zend_Search_Lucene_Field::Text('isi',Chtml::encode('hahahahahah'), 'utf-8')); 
     $index->addDocument($doc);
    $index->commit();
 }

Pada code di atas, saya mendefinisikan Zend Search Lucene dengan kata “Open” yang artinya index yang lama tidak akan dikosongkan melainkan di update. Setelah itu saya menambahkan sebuah document pada index tersebut yang memiliki “pk” =3 dan “isi”=’hahahahahah’. Okeh itu adalah proses update..

Contoh di atas kita melakukan penambahan satu buah document ke dalam index data kita. Lalu bagaimana jika kita ingin melakukan update suatu document yang sudah ada?? Zend Search Lucene sendiri tidak memiliki support untuk melakukan update data(hingga saat ini). Untuk itu, untuk melakukan proses update anda harus menghapus terlebih dahulu document tersebut, lalu menginputnya kembali.. Untuk lebih lengkap, dapat dilihat pada dokumentasinya.

Setelah kita telah melakukan index data, sekarang saatnya kita membuat fitur pencarian pada Zend Search Lucene.. Okeh buatlah action pencarian seperti berikut :

public function actionSearch()
 {
     $term=$_GET['keyword'];
     $index = new Zend_Search_Lucene(Yii::getPathOfAlias('application.tempatsimpan'));
     $results = $index->find($term);
     $query = Zend_Search_Lucene_Search_QueryParser::parse($term); 
     $pages=5;
     $page = new CPagination(count($results));
     $page->pageSize = $pages;

     $dataProvider=new CArrayDataProvider($results,array(
       'keyField' => 'id',
       'totalItemCount'=>count($results),
       'pagination'=>array(
          'pageSize'=>$pages,
         ),
       )
     );

     $this->render('search', compact('dataProvider','results', 'term', 'query','page'));
 }

Penjelasan : pada code di atas, kita melakukan pencarian berdasarkan keyword yang sudah diinput oleh user dari index data pada direktori “namaAplikasi/protected/tempatSimpan”. Setelah itu kita mendapatkan hasil pencariannya. Agar memperindah tampilan, kita membuat pagination pada hasil pencariannya, bisa jadi kan hasilnya sampe 10000 data maka dari itu amat diperlukan fitur pagination. Pagination sendiri kita buat dengan memanfaatkan fitur Carraydataprovider agar mudah diintergrasikan dengan componen yang ada pada Yii.

Lalu pada view, buatlah sebuah file “search.php” lalu isi seperti berikut :

<?php
  $this->pageTitle=Yii::app()->name . ' - Search';
  $this->breadcrumbs=array(
    'Search',
  );
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
   'id'=>'login-form',
   'enableClientValidation'=>true,
   'method'=>'GET',
)); ?>
<?php echo 'Kata Kunci : '; ?>
<?php echo Chtml::textField('keyword','',array('placeholder'=>'Masukan Kata kunci anda...','style'=>'width:340px;')); ?>
<?php echo CHtml::submitButton('Search'); ?>
<?php $this->endWidget(); ?>
</div>
<h3>Hasil Pencarian untuk "<?php echo CHtml::encode($term); ?>"</h3>
<?php 
   if (!empty($results))
   {
      foreach($dataProvider->data as $result)
      { 
 ?> 
     <p><?php echo Chtml::link($query->highlightMatches(CHtml::encode($result->pk)),array('namaModel/view','id'=>$result->pk));?></p>
     <p><?php echo $query->highlightMatches(CHtml::encode($result->isi)); ?></p>
     <hr/>
<?php }
   $this->widget('CLinkPager', array('pages'=>$page,));
  }
  else
  { 
?>
   <p class="error">Tidak ada hasil yang cocok untuk pencarian tersebut.</p>
<?php 
  }
?>

Apabila telah selesai dan anda tidak melakukan kesalahan, maka anda akan mendapati tampilan kurang lebih seperti berikut saat melakukan pencarian :

Anda tertarik membuatnya pada website anda??

Selamat mencoba… Semoga membantu… 😀