With Zend_Search_Lucene you can build a search function on your web page. The difference between searching via MySQL like most websites do is that you have to create an index and keep it up to date.
Create index folder
Create a folder where you store your search index and set write rights. In this tutorial we use the path /application/data/search of our Zend application.
Create controller
Create the controller for our functionality.
<?php
class SearchController extends Zend_Controller_Action
{
protected $_indexPath = '../application/data/search';
public function buildindexAction()
{
}
public function searchAction()
{
}
}
Set the path to the search storage in a protected variable. We implement a buildindexAction where the index will be build and a searchAction where the index will be searched.
Build index
You can build a Zend_Search_Lucene index with a lot of document types like websites, word documents etc. The most websites use a SQL database to store their data. In Zend you normally use models so that our controller has not to know where the data comes from. I assume you have a working Zend project and can get users or any data to index.
<?php
class SearchController extends Zend_Controller_Action
{
protected $_indexPath = '../application/data/search';
public function buildindexAction()
{
Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num());
/**
* Create index
*/
$index = Zend_Search_Lucene::create($this->_indexPath);
/**
* Get all users
*/
$mapper = new User_Mapper();
$users = $mapper->fetchAll();
/**
* Create a document for each user and add it to the index
*/
foreach ($users as $user) {
$doc = new Zend_Search_Lucene_Document();
/**
* Fill document with data
*/
$doc->addField(Zend_Search_Lucene_Field::keyword('userId', $user->getId(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('username', $user->getUsername(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('birthday', $user->getBirthday(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('city', $user->getData()->getCity(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('zodiac', $user->getZodiac(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('age', $user->getAge()), 'UTF-8');
/**
* Add document
*/
$index->addDocument($doc);
}
$index->optimize();
}
public function searchAction()
{
}
}
In the buildindexAction first we set our index to utf8. Then we create it with our path. After creating we load our data we want to index. We go through every record and create a Zend_Search_Lucene_Document for it. This document we can fill with different data. I only used keyword as field type. There are a few other field types you can also use that have different behaviour. You can read more about field types in the Zend documentation. Finally we add the document to the index. After adding every record to the index we optimize the index.
Now you can call http://yourdomain.com/search/buildindex to create the index or configure a cron job that creates the index every day. You could also put the functionality in a class and build the index only if something changes in the user data.
Search index
Zend Search Lucene has it's own query language. You can read detailled information about the query language in thedocumentation. You should build your query to your needs. In this tutorial we use the POST variables to build the query.
<?php
class SearchController extends Zend_Controller_Action
{
protected $_indexPath = '../application/data/search';
public function buildindexAction()
{
Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num());
/**
* Create index
*/
$index = Zend_Search_Lucene::create($this->_indexPath);
/**
* Get all users
*/
$mapper = new User_Mapper();
$users = $mapper->fetchAll();
/**
* Create a document for each user and add it to the index
*/
foreach ($users as $user) {
$doc = new Zend_Search_Lucene_Document();
/**
* Fill document with data
*/
$doc->addField(Zend_Search_Lucene_Field::keyword('userId', $user->getId(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('username', $user->getUsername(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('birthday', $user->getBirthday(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('city', $user->getData()->getCity(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('zodiac', $user->getZodiac(), 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::keyword('age', $user->getAge()), 'UTF-8');
/**
* Add document
*/
$index->addDocument($doc);
}
$index->optimize();
}
public function searchAction()
{
if ($request->isPost()) {
$post = $request->getPost();
/**
* Open index
*/
$index = Zend_Search_Lucene::open($this->_indexPath);
Zend_Search_Lucene_Search_Query_Wildcard::setMinPrefixLength(0);
$query = 'username:"' . $post['username'] . '" OR city:"' . $post['city'] . '"';
$this->view->result = $index->find($query);
} else {
$this->view->form = new Search_Form();
}
}
}
In your view script you can print the results in a foreach loop.
<?php foreach($this->result as $_user): ?>
<?php echo $_user->username ?><br/>
<?php endforeach; ?>
Một vài nhận xét của những người :
Còn về vấn đề Zend Search Lucene, tôi cũng đã dùng, nếu cài trên hosting, set timeout chỉ 30s, nên bạn sẽ không index được, cách tốt nhất là đưa về localhost index thôi (chỉnh thời gian trong php.ini cho phù hợp)
Về cách sử dụng khá đơn giản, lúc đầu mình cũng không biết cách dùng, nhưng bây giờ mình đã sử dụng được cả trên hosting linux, bạn có thể pm cho mình qua nick haitruonginfotech, mình sẽ hướng dẫn cho bạn ... thân.
3. Tôi sử dụng Zend Search Lucene để tạo index, tuy nhiên không hiểu tại sao khi addDocument đến mục thứ 10.004 thì nó bị đơ, đứng im tại hàm addDocument, có phải là tràn 1 cái gì đó không? Mong các bác giúp đỡ cách khắc phục. Thông tin thêm: tổng lượng file cần index là 468MB (16.000 file), hiện giờ với 10.003 document thì chạy optimize() bị báo thiếu bộ nhớ (đã set memory_limit trong php.ini lên 128MB). Do tình hình server cùi bắp nên ko thể set thêm lên nữa.
4. Tôi khuyên bạn không nên sử dụng Zend_Search_Lucene ở thời điểm này, nó chưa ổn định, chưa hỗ trợ Unicode tốt và còn thiếu rất nhiều chức năng ! Với điều kiện bạn có nhiều server riêng phục vụ cho index/search thì có thể tham khảo Solr, một search server dựa trên Java Lucene. Nó chạy trên một server riêng với Tomcat và giao tiếp với phần còn lại của ứng dụng bằng REST. Tuy nhiên nó chỉ hỗ trợ một index / 1 cá thể Solr, nếu muốn nó linh hoạt hơn thì bạn có thể sửa code nó.
Nguồn : http://www.tutorial-portal.com/tutorial/show/id/19.
Download file Pdf : http://www.tutorial-portal.com/tutorial/pdf/id/19Tham khảo http://forum.gocit.vn/threads/mysql-full-text-search.323/, http://kynangiphone.blogspot.com/2012/07/php-zend-search-lucene-tieng-viet.html
http://www.phpriot.com/articles/zend-search-lucene
Đăng nhận xét