Joomla!-开源天空

2009-01-10
您所在的位置: 首页 > Joomla专栏 > 源代码分析 > 让Joomla! 支持中文全文检索,建立索引

让Joomla! 支持中文全文检索,建立索引

Joomla! 开源天空  作者:管理员  2008-03-05 09:16
  • 摘要:本文描述了如何在Joomla!中添加全文检索功能,本文中给出了如何建立索引。

实现Joomla!中文全文检索,有很多方式,其中之一是采用Mysql的全文检索,而且网络上有一个mysql支持中文全文检索的补丁,印象中是一位hightman写的,他的关于全文检索的东西还是很实用的。另外一种方式就是用lucene这样的全文检索系统,还可以选择xapian,但是由于这样的系统搭建起来稍有麻烦,比如lucene就需要安装关于java的东西,还要装php-javabridge。

最终采用ZendFramework的Zend_Lucene来解决这个问题,虽然评论这有点效率低,但是考虑到与php完美的融合,最终还是采用了,最终试验的效果也不错。反正要加入索引的文章也不多,估计对于Joomla!来说,只要Joomla!那些冗长的查询语句还允许服务器支撑,估计这个全文检索就没问题,呵呵!

我的解决过程如下:

1、安装,请参考这篇文章  ZendFramework安装配置指南    安装ZendFramework,如果你仅仅是用其中的Zend_Lucene,其实也可以不必安装pdo部分。

2、ZendFramework中文检索,请参考这篇文章 Zend_Search_Lucene 如何支持中文检索  ,实际工作中,这篇文章的代码存在一些错误,以后我会提到。

3、创建一个组件,如果你不熟悉组件的书写,还是要学习一下,也可以用一下这个试试  Joomla 组件自动生成器(Comgen)-测试版发布  。嘿嘿,不过还是要熟悉php啊。

4、增加索引建立,更新索引功能,你可以在组件的controller.php文件中,增加一个function,代码如下:

function createindex(){
 $db   = & JFactory::getDBO();  
 $categories = array();
 $sections = array();
 $query = 'select * from #__categories';
 $db->setQuery( $query );
 $items = $db->loadObjectList();  
 if($items){
  foreach ( $items as $item ){
   $categories[$item->id]=$item->alias;
  }
   }
 $query = 'select * from #__sections';
 $db->setQuery( $query );
 $items = $db->loadObjectList();  
 if($items){
  foreach ( $items as $item ){
   $sections[$item->id]=$item->alias;
  }
   }    
 $query='select * from #__content limit 10';
 $db->setQuery( $query );
 $items = $db->loadObjectList();
 if($items){
  $maxid = 0;
  $index = null;
    Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Phpbean_Lucene_Analyzer());
    if(file_exists('/home/apache/www/maycode/search/read.lock.file')){
     $index = new Zend_Search_Lucene('/tmp/search');
    }
    else{
     $index = new Zend_Search_Lucene('/tmp/search',true); 
    }     
      foreach ( $items as $item ){
      echo $item->title.'<br/>';
            
   $content=htmlentities(strip_tags($item->introtext),ENT_NOQUOTES,'UTF-8');
   if($item->alias){
    $slug = $item->id.':'.$item->alias;
   }
   else{
    $slug = $item->id;
   }
   
   if($categories[$item->catid]){
    $catslug = $item->catid.':'.$categories[$item->catid];
   }
   else{
    $catslug = $item->catid;
   }
   
   $sectionid= $item->sectionid;
   $createdate = $item->created;
   $title = $item->title;
   $doc = new Zend_Search_Lucene_Document();
   $doc->addField(Zend_Search_Lucene_Field::Text('title', $title,'utf-8'));
   $doc->addField(Zend_Search_Lucene_Field::Text('content', $content,'utf-8'));
   $doc->addField(Zend_Search_Lucene_Field::UnIndexed('slug', $slug,'utf-8'));
   $doc->addField(Zend_Search_Lucene_Field::UnIndexed('catslug', $catslug,'utf-8'));
   $doc->addField(Zend_Search_Lucene_Field::UnIndexed('sectionid', $sectionid,'utf-8'));
   $doc->addField(Zend_Search_Lucene_Field::UnIndexed('createdate', $createdate,'utf-8'));
   $index->addDocument($doc);
   $maxid = $item->id;   
  }
  $index->commit();
   } 
}
 

程序的3-20行,建立了Joomla! 文章category和section的散列数组,以备以后需要。

程序21-23行,从数据库中查询出了前10篇文章,你具体应用的时候,应该修改,加上发布状态等条件。

程序24-65行,则是循环将每个文章添加到索引中。让我们来逐一来看看。

程序27-33行,根据目的目录是否存在建立的索引文件,来判断是更新索引,还是新建索引。

注意程序第37行的对于文件内容的处理,因为我的数据库是utf-8字符集,所以htmlentities与我们最常用的方式稍有区别,以支持utf-8,否则,内容就会成为乱码了。

程序52-62行,是添加几个字段,其中只有title和content是需要索引的,而slug,catslug,sectionid主要都是用来建立链接用的。之所以不是直接把连接写进去,主要是为以后连接可能发生的变化,留下一个接口。

$index->commit(); 将更新写如文件。注意,有多少个commit就会有多少segement,所以这个最好不要常作。这点因为不能优化索引也是zend_lucene被诟病的地方。

索引的保存路径是/tmp/search,这个路径你可以自己设置,但是如果你是通过浏览器调用http://www.yourdomain.com/index.php?option=com_***&view=***&task=createindex ,那么这样你就需要那个目录有写入权限。

当然我推荐是后台定期调用,生成索引文件。

注意:我的数据库默认字符集是UTF-8,程序页面也都是。

(未完待续,接下来,将描述如何利用索引查询)

  发表您的文章评论

您的姓名 (昵称)
标题:
评分: 很差一般较好很好
评论:
验证码:
请输入验证码