用Sphinx给dedecms 5.5添加全文检索的功能
2010-01-20 16:24
288 查看
一、前言
dede内容管理系统,算是国内比较主流的一款cms了。
今年做项目时也接触了两次。它的搜索功能比较薄弱,默认情况下只是对文章标题和关键字进行搜索,而且使用的是数据库的like方式查询,数据量一旦突破10W可能就会产生一些性能的瓶颈。
这里我们对它进行一些改造,让它的搜索不仅仅只是搜索标题和关键字,还包括文章内容。使用全文检索引擎,替换性能低下的like查询方式。
开源免费的全文检索引擎比较主流的选择有:lucene和sphinx,由于我们是php环境,方便起见,这里选择可以和mysql数据库完美结合的sphinx
二、Sphinx 简介
出自俄罗斯的开源全文搜索引擎软件Sphinx
,
单一索引最大可包含1亿条记录,在1千万条记录情况下的查询速度为0.x秒(毫秒级)。Sphinx创建索引的速度为:创建100万条记录的索引只需
3~4分钟,创建1000万条记录的索引可以在50分钟内完成,而只包含最新10万条记录的增量索引,重建一次只需几十秒。
官方网站:
http://www.sphinxsearch.com
推荐博文:
http://blog.s135.com/post/360/
三、Coreseek 简介
Coreseek是基于Sphinx的一款软件,对Sphinx做了一些改动,主要是中文切分词方面更合理一些
变更如下:
改进MMSeg切词策略,支持产品型号的切分
修正MMSeg切分结果不一致的问题
增加MMSeg的Python接口(Win32 Only)
修正了PySource的若干错误
为主流的Linux平台提供的预编译二进制包
官方网站:
http://www.coreseek.cn/
帮助手册pdf下载:
http://www.coreseek.cn/uploads/pdf/sphinx_doc_zhcn_0.9.pdf
四、准备工作
在对dedecms进行改动前,首先要安装Coreseek。Coreseek的安装可以查看上面提到的帮助手册,需要提醒的是:
1、Coreseek可以跑在windows环境下,但仅可用于测试
2、安装前需要首先安装python环境
Coreseek的安装方法还可以通过搜索得到
http://www.google.cn/search?hl=zh-CN&newwindow=1&q=coreseek+%E5%AE%89%E8%A3%85&btnG=Google+%E6%90%9C%E7%B4%A2&aq=f&oq=
这里就不做重复了,我的这次测试是在windows xp环境下进行的(公司有个discuz论坛也是用的Sphinx做全文检索,跑在linux下)。
五、Sphinx的config设置
六、在dedecms数据库中建立sphinx表
前面的安装过程中,给mysql增加了一个sphinx模块,可以创建sphinx类型的表。
建表sql如下:
七、修改dede的搜索类 include/arc.searchview.class.php
改两个方法:
1、CountRecord
2、GetArcList
八、运行
到这里dedecms就可以借助sphinx进行全文检索了,当然,在生产环境下,还要做些优化。
下面是一些操作:
1、启动sphinx
在sphinx/bin目录下
searchd --config d:/csft
/csft.conf
这里csft.conf是上面的sphinx的config文件
命令为dos命令
2、创建索引
在sphinx/bin目录下
indexer dedecms –config d:/csft
/csft.conf
写的比较仓促,而且这个测试是前两个月做的,所以可能总结的不够好,如果有问题,欢迎发邮件给我:warran(at)qq.com
dede内容管理系统,算是国内比较主流的一款cms了。
今年做项目时也接触了两次。它的搜索功能比较薄弱,默认情况下只是对文章标题和关键字进行搜索,而且使用的是数据库的like方式查询,数据量一旦突破10W可能就会产生一些性能的瓶颈。
这里我们对它进行一些改造,让它的搜索不仅仅只是搜索标题和关键字,还包括文章内容。使用全文检索引擎,替换性能低下的like查询方式。
开源免费的全文检索引擎比较主流的选择有:lucene和sphinx,由于我们是php环境,方便起见,这里选择可以和mysql数据库完美结合的sphinx
二、Sphinx 简介
出自俄罗斯的开源全文搜索引擎软件Sphinx
,
单一索引最大可包含1亿条记录,在1千万条记录情况下的查询速度为0.x秒(毫秒级)。Sphinx创建索引的速度为:创建100万条记录的索引只需
3~4分钟,创建1000万条记录的索引可以在50分钟内完成,而只包含最新10万条记录的增量索引,重建一次只需几十秒。
官方网站:
http://www.sphinxsearch.com
推荐博文:
http://blog.s135.com/post/360/
三、Coreseek 简介
Coreseek是基于Sphinx的一款软件,对Sphinx做了一些改动,主要是中文切分词方面更合理一些
变更如下:
改进MMSeg切词策略,支持产品型号的切分
修正MMSeg切分结果不一致的问题
增加MMSeg的Python接口(Win32 Only)
修正了PySource的若干错误
为主流的Linux平台提供的预编译二进制包
官方网站:
http://www.coreseek.cn/
帮助手册pdf下载:
http://www.coreseek.cn/uploads/pdf/sphinx_doc_zhcn_0.9.pdf
四、准备工作
在对dedecms进行改动前,首先要安装Coreseek。Coreseek的安装可以查看上面提到的帮助手册,需要提醒的是:
1、Coreseek可以跑在windows环境下,但仅可用于测试
2、安装前需要首先安装python环境
Coreseek的安装方法还可以通过搜索得到
http://www.google.cn/search?hl=zh-CN&newwindow=1&q=coreseek+%E5%AE%89%E8%A3%85&btnG=Google+%E6%90%9C%E7%B4%A2&aq=f&oq=
这里就不做重复了,我的这次测试是在windows xp环境下进行的(公司有个discuz论坛也是用的Sphinx做全文检索,跑在linux下)。
五、Sphinx的config设置
source dedecms { type= mysql sql_host= localhost #mysql主机地址 sql_user= root #mysql用户名 sql_pass= tear #mysql密码 sql_db= dede #dede库名 sql_port= 3306 #mysql端口 sql_query_pre= SET NAMES utf8 #数据库字符类型 sql_query_pre= SET SESSION query_cache_type=OFF sql_query= SELECT aid, typeid, body FROM dede_addonarticle sql_ranged_throttle= 0 sql_query_info= SELECT * FROM dede_addonarticle WHERE aid=$id } index cgfinal { source= dedecms path= d:/csft/data/test1 #索引文件存放的地址 docinfo= extern mlock= 0 morphology= none min_word_len= 1 charset_type= zh_cn.utf-8 charset_dictpath= d:/csft/data #分词字典的存放位置 html_strip= 0 } indexer { mem_limit= 32M } searchd #这里都是默认的,没做修改,还是linux的路径,因为只是测试,就不管它了,如果要好好设置的话要查看手册对照着做 { log= /usr/local/sphinx/var/log/searchd.log query_log= /usr/local/sphinx/var/log/query.log read_timeout= 5 client_timeout= 3 max_children= 30 pid_file= /usr/local/sphinx/var/log/searchd.pid max_matches= 10000 seamless_rotate= 1 preopen_indexes= 0 unlink_old= 1 mva_updates_pool= 1M max_packet_size= 8M max_filters= 256 max_filter_values= 4096 }
六、在dedecms数据库中建立sphinx表
前面的安装过程中,给mysql增加了一个sphinx模块,可以创建sphinx类型的表。
建表sql如下:
CREATE TABLE IF NOT EXISTS `sphinx` ( `id` int(11) NOT NULL, `weight` int(11) NOT NULL, `query` varchar(255) NOT NULL, KEY `Query` (`query`) ) ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION='sphinx://localhost:3312/cgfinal';
七、修改dede的搜索类 include/arc.searchview.class.php
改两个方法:
1、CountRecord
//统计列表里的记录 function CountRecord() { $this->TotalResult = -1; if(isset($GLOBALS['TotalResult'])) { $this->TotalResult = $GLOBALS['TotalResult']; } if(isset($GLOBALS['PageNo'])) { $this->PageNo = $GLOBALS['PageNo']; } else { $this->PageNo = 1; } $ksql = $this->GetKeywordSql(); $ksqls = array(); if($this->StartTime > 0) { $ksqls[] = " arc.senddate>'".$this->StartTime."' "; } if($this->TypeID > 0) { $ksqls[] = " typeid in (".GetSonIds($this->TypeID).") "; } if($this->ChannelType > 0) { $ksqls[] = " arc.channel='".$this->ChannelType."'"; } if($this->mid > 0) { $ksqls[] = " arc.mid = '".$this->mid."'"; } $ksqls[] = " arc.arcrank > -1 "; $this->AddSql = ($ksql=='' ? join(' And ',$ksqls) : join(' And ',$ksqls)." And ($ksql)" ); $cquery="select dede_addonarticle.* from dede_addonarticle, sphinx where dede_addonarticle.aid=sphinx.id and query='".$this->Keyword."'"; //$cquery = "Select * From `#@__archives` arc where ".$this->AddSql; $hascode = md5($cquery); $row = $this->dsql->GetOne("Select * From `#@__arccache` where `md5hash`='".$hascode."' "); $uptime = time(); if(is_array($row) && time()-$row['uptime'] < 3600 * 24) { $aids = explode(',', $row['cachedata']); $this->TotalResult = count($aids)-1; $this->RsFields = $row['cachedata']; } else { if($this->TotalResult==-1) { $this->dsql->SetQuery($cquery); $this->dsql->execute(); $aidarr = array(); $aidarr[] = 0; while($row = $this->dsql->getarray()) { $aidarr[] = $row['id']; } $nums = count($aidarr)-1; $aids = implode(',', $aidarr); $delete = "Delete From `#@__arccache` where uptime<".(time() - 3600 * 24); $this->dsql->SetQuery($delete); $this->dsql->executenonequery(); $insert = "insert into `#@__arccache` (`md5hash`, `uptime`, `cachedata`) values('$hascode', '$uptime', '$aids')"; $this->dsql->SetQuery($insert); $this->dsql->executenonequery(); $this->TotalResult = $nums; } } }
2、GetArcList
//获得文档列表 function GetArcList($limitstart=0,$row=10,$col=1,$titlelen=30,$infolen=250, $imgwidth=120,$imgheight=90,$achanneltype="all",$orderby="default",$innertext="",$tablewidth="100") { $typeid=$this->TypeID; if($row=='') $row = 10; if($limitstart=='') $limitstart = 0; if($titlelen=='') $titlelen = 30; if($infolen=='') $infolen = 250; if($imgwidth=='') $imgwidth = 120; if($imgheight='') $imgheight = 120; if($achanneltype=='') $achanneltype = '0'; $orderby = $orderby=='' ? 'default' : strtolower($orderby); $tablewidth = str_replace("%","",$tablewidth); if($tablewidth=='') $tablewidth=100; if($col=='') $col=1; $colWidth = ceil(100/$col); $tablewidth = $tablewidth."%"; $colWidth = $colWidth."%"; $innertext = trim($innertext); if($innertext=='') { $innertext = GetSysTemplets("search_list.htm"); } //排序方式 $ordersql = ''; if($orderby=="senddate") { $ordersql=" order by arc.senddate desc"; } else if($orderby=="pubdate") { $ordersql=" order by arc.pubdate desc"; } else if($orderby=="id") { $ordersql=" order by arc.id desc"; } else { $ordersql=" order by arc.sortrank desc"; } //搜索 $query = "Select arc.*,act.typedir,act.typename,act.isdefault,act.defaultname,act.namerule, act.namerule2,act.ispart,act.moresite,act.siteurl,act.sitepath from sphinx,`#@__archives` arc left join `#@__arctype` act on arc.typeid=act.id where arc.id=sphinx.id and query='".$this->Keyword."' $ordersql limit $limitstart,$row"; $this->dsql->SetQuery($query); $this->dsql->Execute("al"); $artlist = ""; if($col>1) { $artlist = "<table width='$tablewidth' border='0' cellspacing='0' cellpadding='0'>/r/n"; } $this->dtp2->LoadSource($innertext); for($i=0;$i<$row;$i++) { if($col>1) { $artlist .= "<tr>/r/n"; } for($j=0;$j<$col;$j++) { if($col>1) { $artlist .= "<td width='$colWidth'>/r/n"; } if($row = $this->dsql->GetArray("al")) { //处理一些特殊字段 $row["arcurl"] = GetFileUrl($row["id"],$row["typeid"],$row["senddate"],$row["title"], $row["ismake"],$row["arcrank"],$row["namerule"],$row["typedir"],$row["money"],$row['filename'],$row["moresite"],$row["siteurl"],$row["sitepath"]); $row["description"] = $this->GetRedKeyWord(cn_substr($row["description"],$infolen)); $row["title"] = $this->GetRedKeyWord(cn_substr($row["title"],$titlelen)); $row["id"] = $row["id"]; if($row['litpic'] == '-' || $row['litpic'] == '') { $row['litpic'] = $GLOBALS['cfg_cmspath'].'/images/defaultpic.gif'; } if(!eregi("^http://",$row['litpic']) && $GLOBALS['cfg_multi_site'] == 'Y') { $row['litpic'] = $GLOBALS['cfg_mainsite'].$row['litpic']; } $row['picname'] = $row['litpic']; $row["typeurl"] = GetTypeUrl($row["typeid"],$row["typedir"],$row["isdefault"],$row["defaultname"],$row["ispart"],$row["namerule2"],$row["moresite"],$row["siteurl"],$row["sitepath"]); $row["info"] = $row["description"]; $row["filename"] = $row["arcurl"]; $row["stime"] = GetDateMK($row["pubdate"]); $row["textlink"] = "<a href="".$row["filename"]."" mce_href="".$row["filename"]."">".$row["title"]."</a>"; $row["typelink"] = "[<a href="".$row["typeurl"]."" mce_href="".$row["typeurl"]."">".$row["typename"]."</a>]"; $row["imglink"] = "<a href="".$row["filename"]."" mce_href="".$row["filename"].""><img src="".$row["picname"]."" mce_src="".$row["picname"]."" border='0' width='$imgwidth' height='$imgheight'></a>"; $row["image"] = "<img src="".$row["picname"]."" mce_src="".$row["picname"]."" border='0' width='$imgwidth' height='$imgheight'>"; $row['plusurl'] = $row['phpurl'] = $GLOBALS['cfg_phpurl']; $row['memberurl'] = $GLOBALS['cfg_memberurl']; $row['templeturl'] = $GLOBALS['cfg_templeturl']; if(is_array($this->dtp2->CTags)) { foreach($this->dtp2->CTags as $k=>$ctag) { if($ctag->GetName()=='array') { //传递整个数组,在runphp模式中有特殊作用 $this->dtp2->Assign($k,$row); } else { if(isset($row[$ctag->GetName()])) { $this->dtp2->Assign($k,$row[$ctag->GetName()]); } else { $this->dtp2->Assign($k,''); } } } } $artlist .= $this->dtp2->GetResult(); }//if hasRow else { $artlist .= ""; } if($col>1) $artlist .= "</td>/r/n"; }//Loop Col if($col>1) { $artlist .= "</tr>/r/n"; } }//Loop Line if($col>1) { $artlist .= "</table>/r/n"; } $this->dsql->FreeResult("al"); return $artlist; }
八、运行
到这里dedecms就可以借助sphinx进行全文检索了,当然,在生产环境下,还要做些优化。
下面是一些操作:
1、启动sphinx
在sphinx/bin目录下
searchd --config d:/csft
/csft.conf
这里csft.conf是上面的sphinx的config文件
命令为dos命令
2、创建索引
在sphinx/bin目录下
indexer dedecms –config d:/csft
/csft.conf
写的比较仓促,而且这个测试是前两个月做的,所以可能总结的不够好,如果有问题,欢迎发邮件给我:warran(at)qq.com
相关文章推荐
- CentOS5.5 安装 Sphinx 全文检索
- sphinx全文检索功能 | windows下测试 (一)
- 对本地Solr服务器添加IK中文分词器实现全文检索功能
- CentOS5.5 安装 Sphinx 全文检索
- 为web项目添加Lucene全文检索功能(Spring集成Lucene)
- sphinx全文检索功能 | windows下测试 (二)
- [转]在应用中加入全文检索功能(基于Java的全文索引引擎Lucene简介)
- 实现Django的全文检索功能(三):进一步学习Haystack
- 利用Sphinx实现实时全文检索
- 基于Sphinx的中文全文检索引擎Coreseek的安装
- SQL Server 2000 的Standard Edition 和Enterprise Edition 版本提供了对表数据中字符串的复杂检索功能---全文检索(Full-Text Searches)。
- Apache Lucene全文检索引擎架构之搜索功能
- sphinx全文检索之PHP使用教程
- dedecms5.7文章二次开发实现阅读全文功能的方法
- 全文检索功能 --待完善
- Sphinx 全文检索引擎
- Django的全文检索功能(一):haystack全文检索的框架
- 使用SQL SERVER 2000的全文检索功能
- 如何在SQL中启用全文检索功能?
- 在应用中加入全文检索功能—基于Java的全文索引引擎Lucene简介(收藏)