`
kidiaoer
  • 浏览: 805635 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

对php,mysql全文搜索的完全分析

阅读更多

对php,mysql全文搜索的完全分析

March 2, 2007 23:31 · Filed under 技术文档
对dvbbs.php 全文搜索的完全分析

这次给大家渗透些比较高级些的.关于搜索的东西.
首先,大家先去下载一份dvbbs.php beta1的代码.解压放在手头上
已经有的同学们就可以继续往下看了.

首先抛开php代码.
找出你的mysql手册.(没有?那直接看下面的吧.)

mysql全文搜索,sql的写法:
MATCH (col1,col2,…) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])

比如:
SELECT * FROM articles WHERE MATCH (title,body) AGAINST (‘database’);

MATCH()函数对于一个字符串执行资料库内的自然语言搜索。一个资料库就是1套1个或2个包含在FULLTEXT内的列。搜索字符串作为对 AGAINST()的参数而被给定。对于表中的每一行, MATCH() 返回一个相关值,即, 搜索字符串和 MATCH()表中指定列中该行文字之间的一个相似性度量。

下面的例子则更加复杂。询问返回相关值,同时对行按照相关性渐弱的顺序进行排序。为实现这个结果,你应该两次指定 MATCH(): 一次在 SELECT 列表中而另一次在 WHERE子句中。这不会引起额外的内务操作,原因是MySQL 优化程序注意到两个MATCH()调用是相同的,从而只会激活一次全文搜索代码。

mysql> SELECT id, body, MATCH (title,body) AGAINST

-> (‘Security implications of running MySQL as root’) AS score

-> FROM articles WHERE MATCH (title,body) AGAINST

-> (‘Security implications of running MySQL as root’);

所以,到这里你应该会mysql 英文全文搜索了.
===
请注意一个问题.

一些词在全文搜索中会被忽略:
* 任何过于短的词都会被忽略。 全文搜索所能找到的词的默认最小长度为 4个字符。
* 停止字中的词会被忽略。

===
mysql还自带查询扩展功能.这里不做过多讨论.
===
下面进行php中文全文搜索的分析.

曾经有一个版本的mysql支持中文全文搜索(海量 mysql chinese+,说是GPL但是最终没有开源)
中文全文搜索的关键是在分词上.mysql本身不支持cjk的分词(cjk:chinese,japanese,korean),
所以

!!!!****如何用php模拟分词是mysql全文索引的关键****!!!!

中文分词是语言分词中最困难的.现在也没有人能够彻底完美的解决(虽然这些搜索引擎做的都还不错.)

//fcicq:下面给大家看看这里php的分词是怎么做的.
function &DV_ChineseWordSegment($str,$encodingName=’gbk’){

static $objEnc = null;

if( $objEnc === null ){

if( !class_exists(‘DV_Encoding’) ){

require_once ROOT_PATH.’inc/DV_Encoding.class.php’;

}

$objEnc =& DV_Encoding::GetEncoding($encodingName);

}

$strLen = $objEnc->StrLength($str);

$returnVal = array();

if( $strLen < = 1 ){

return $str;

}

$arrStopWords =& DV_GetStopWordList();

//print_r($arrStopWords);

//过滤所有HTML标签

$str = preg_replace('#<[a-zA-Z]+?.*?>|#is’, ”, $str);

//过滤所有stopword

$str = str_replace($arrStopWords['StrRepl'],’ ‘,$str);

$str = preg_replace($arrStopWords['PregRepl'],’ ‘,$str);

//echo “$str:{$str}
“;

$arr = explode(‘ ‘,$str);

//fcicq:好了,这下面的才是php分词关键 *******************************************
foreach( $arr as $tmpStr ){

if ( preg_match(“/^[x00-x7f]+$/i”,$tmpStr) === 1 ) { //fcicq:全是E文,没关系,mysql可以认识的

$returnVal[] = ‘ ‘.$tmpStr;

} else{ //fcicq:中英混合…

preg_match_all(“/([a-zA-Z]+)/i”, $tmpStr, $matches);

if( !empty($matches) ){ //fcicq:英语部分

foreach( $matches[0] as $matche ){

$returnVal[] = $matche;

}

}

//过滤ASCII字符

$tmpStr = preg_replace(“/([x00-x7f]+)/i”, ”, $tmpStr); //fcicq:你看,剩下的不就全是中文了?

$strLen = $objEnc->StrLength($tmpStr)-1;

for( $i = 0 ; $i < $strLen ; $i++ ){

$returnVal[] = $objEnc->SubString($tmpStr,$i,2); //fcicq:注意这里的substr,不是手册上的.
//fcicq:你仔细看,所有的词都是分成两个.
//比如”数据库的应用”,会被分成数据 据库 库的 的应 应用…
//全文搜索: 全文 文搜 搜索
//这分词自然是不怎么样的
//但是,搜索的时候同样这么做.
//比如搜索数据库,就相当于搜索了数据 据库.
//这是一种相当传统的全文搜索分词方法.

}

}

}

return $returnVal;

}//end function DV_ChineseWordSegment

//fcicq:这就是传说中的substr.偶相信许多人写出来的php代码都比这个好.
function &SubString(&$str,$start,$length=null){

if( !is_numeric($start) ){

return false;

}

$strLen = strlen($str);

if( $strLen < = 0 ){

return false;

}

if( $start < 0 || $length < 0 ){

$mbStrLen = $this->StrLength($str);

} else{

$mbStrLen = $strLen;

}

if( !is_numeric($length) ){

$length = $mbStrLen;

} elseif( $length < 0 ){

$length = $mbStrLen + $length - 1;

}

if( $start < 0 ){

$start = $mbStrLen + $start;

}

$returnVal = '';

$mbStart = 0;

$mbCount = 0;

for( $i = 0 ; $i < $strLen ; $i++ ){

if( $mbCount >= $length ){

break;

}

$currOrd = ord($str{$i});

if( $mbStart >= $start ){

$returnVal .= $str{$i};

if( $currOrd > 0×7f ){

$returnVal .= $str{$i+1}.$str{$i+2};

$i += 2;

}

$mbCount++;

} elseif( $currOrd > 0×7f ){

$i += 2;

}

$mbStart++;

}

return $returnVal;

}//end function SubString

//插入全文搜索分词表.一共两个,一个 topic_ft,一个bbs_ft

$arrTopicIndex =& DV_ChineseWordSegment($topic);

if( !empty($arrTopicIndex) && is_array($arrTopicIndex) ){

$topicindex = $db->escape_string(implode(‘ ‘,$arrTopicIndex));

if( $topicindex !== ” ){

$db->query(“UPD ATE {$dv}topic_ft SET topicindex=’{$topicindex}’ WHERE topicid=’{$RootID}’”);

} else{

$db->query(“DEL ETE FROM {$dv}topic_ft WHERE topicid=’{$RootID}’”);

}

}
}

明白了吧?这就是所谓的mysql全文搜索分词
mysql不会分词,而php会.就这么简单.
这虽然是一种比较过时的方法,但被dv这么一炒作就成了香饽饽.
很好理解的.

之后,mysql把这些全文搜索分词的结果
implode(‘ ‘,$arrTopicIndex)
再分词(呵呵,数据,据库…),把这些词生硬的记住了.

下面回到mysql上来,下面是php+mysql实现的全文搜索查询.

$arrFTKeyWord =& DV_ChineseWordSegment($keyword);

//$ftKeyWords = implode(‘ ‘,$arrFTKeyWord);

$ftKeyWords = ”.implode(‘ ‘,$arrFTKeyWord);

//fcicq:中间省略了很多….

$stmt = “SELECT {$SQL_CACHE} /*SQL_CALC_FOUND_ROWS*/ ft.topicid FROM {$dv}topic_ft AS ft WHERE MATCH(ft.topicindex) AGAINST(‘{$ftKeyWords}’ IN BOOLEAN MODE) “.($boardid>0?” AND ft.boardid=’{$boardid}’”:”).” AND ft.posttable=’{$stable}’”;
//in boolean mode,能够保证每一条都查到.

$TopicIDList = ‘0′;

if( $query = $db->query($stmt,array(‘absolutePage’=>$page,’pageSize’=>$pagesize,’debug’=>QUERY_DEBUG)) ){

//$Record_Count = $db->scalar(“SELECT FOUND_ROWS()”);

if( $Record_Count < = 0 ){ //没有就输出错误.

head(1,0,0,$arrNavMenu);

showmsg($lang['str_42'].$lang['str_43']);

exit;

}

while( $tmpResult =& $db->fetch_row($query) ){ //fcicq:注意注意….这里就是保存刚才的id了.这里可以优化一下

$TopicIDList .= “,{$tmpResult[0]}”;

}

}

$PCount = ceil( (float)$Record_Count / (float)$pagesize );

//fcicq:上面用php进行分页预处理,不用管它.

$__dbResults =& $db->getResultSet(“SELECT {$SQL_CACHE} t.boardid,t.topicid AS rootid,t.title AS topic,t.expression,t.postusername AS username,t.postuserid,t.dateandtime,t.isbest,t.locktopic,t.child,t.hits,t.hidename FROM {$dv}topic AS t WHERE t.topicid IN({$TopicIDList}) ORDER BY t.topicid DESC”);

//fcicq:这里就直接按主题的先后顺序(ORDER BY t.topicid DESC)进行了输出.

讲到这里大家都应该明白了吧,这就是最简单的php,mysql全文搜索分词方式.

肯定有更好的办法,具体如何做,还是要你自己去想.
(第一版:2006.9.17 修改:2007.5)

友情提示: 请注意文章的时效性与准确性, 作者不对文章的有效性负责.

Tags: mysql, php
Permalink Bookmark on del.icio.us
Last Modified: August 13, 2007 at 10:55 pm
« 收录的倒挂:算法问题? | Main | 左偏树:Leftist Tree »

2 Comments

   1.
      fcicq said,

      September 3, 2006 @ 09:30

      $tmpTopicTitle = preg_replace(‘#^[.*?]#i’,”,$TopicInfo['title']);

      $arrTopicTitle =& DV_ChineseWordSegment($tmpTopicTitle); //fcicq:把文章标题分词

      //echo implode(‘ ‘,$arrTopicTitle);

      if (is_array($arrTopicTitle) AND !empty($arrTopicTitle)) {

      //$topicIDList = ‘0′;

      $topicIDList = ”;

      $limitNumber = 5;

      //*

      $keyWordCount = 3;

      $stmt = ”;

      $count = count($arrTopicTitle);

      if( $count > 1 ){ //fcicq:注意注意…如果分出的词大于1的话.

      $stmt = ”;

      if( $count < = $keyWordCount ){

      for( $i = 0 ; $i < $count ; $i++ ){ //fcicq:每一句写一个sql,然后用union select连接,这就是所谓的相关性

      if( $stmt !== '' ){

      $stmt .= "
      UNION
      ";

      }

      $stmt .= "
      (SELECT {$SQL_CACHE} SQL_SMALL_RESULT ft.topicid FROM {$dv}topic_ft AS ft WHERE MATCH(ft.topicindex) AGAINST('{$arrTopicTitle[$i]}') AND (ft.boardid<>444 AND ft.locktopic=0) AND ft.posttable=’{$TotalUseTable}’ AND ft.topicid<>‘{$TopicInfo['topicid']}’ LIMIT {$limitNumber})
      “;

      }

      } else{

      $arrRand = array();

      for( $i = 0 ; $i < $keyWordCount ; $i++ ){

      //$indexRand = rand(0,$count);

      $indexRand = array_rand($arrTopicTitle);

      if( isset($arrRand[$arrTopicTitle[$indexRand].'']) ){

      //$i--;

      continue;

      }

      $arrRand[$arrTopicTitle[$indexRand].''] = true;

      if( $stmt !== '' ){

      $stmt .= ' UNION ';

      }

      $stmt .= "
      (SELECT {$SQL_CACHE} SQL_SMALL_RESULT ft.topicid FROM {$dv}topic_ft AS ft WHERE MATCH(ft.topicindex) AGAINST('{$arrTopicTitle[$indexRand]}') AND (ft.boardid<>444 AND ft.locktopic=0) AND ft.posttable=’{$TotalUseTable}’ AND ft.topicid<>‘{$TopicInfo['topicid']}’ LIMIT {$limitNumber})
      “;

      }

      }

      $stmt .= “ORDER BY RAND()”; //fcicq:最后不忘了随机排序.

      } elseif( $count === 1 ){

      $stmt = “SELECT {$SQL_CACHE} SQL_SMALL_RESULT ft.topicid FROM {$dv}topic_ft AS ft WHERE MATCH(ft.topicindex) AGAINST(‘{$arrTopicTitle[0]}’) AND (ft.boardid<>444 AND ft.locktopic=0) AND ft.topicid<>‘{$TopicInfo['topicid']}’”;

      }

      if( $query = $db->query($stmt,array(‘pageSize’=>$limitNumber)) ){ //fcicq:取topicid.如果多余的话就取这个数(limitnumber)

      $comma = ”;

      while( $tmpResult =& $db->fetch_row($query) ){

      $topicIDList .= “{$comma}{$tmpResult[0]}”;

      $comma = ‘,’;

      }

      }

      if (!empty($topicIDList)) { //fcicq:最后进行一次标准查询.

      $stmt = “SELECT {$SQL_CACHE} SQL_SMALL_RESULT dt.topicid,dt.title,dt.boardid,dt.pollid,dt.locktopic,dt.child,dt.postusername,dt.postuserid,dt.dateandtime,dt.hits,dt.expression,dt.votetotal,dt.lastpost,dt.lastposttime,dt.istop,dt.isvote,dt.isbest,dt.posttable,dt.smsuserlist,dt.issmstopic,dt.lastsmstime,dt.topicmode,dt.mode,dt.getmoney,dt.usetools,dt.getmoneytype,dt.hidename FROM {$dv}topic AS dt WHERE dt.topicid IN({$topicIDList}) ORDER BY dt.topicid DESC”;

      $arrRelatedTopic =& $db->getResultSet($stmt,array(‘pageSize’=>$limitNumber));

      }

      }
分享到:
评论

相关推荐

    Php mysql进销存系统

    搜索采用全文检索技术,不但提高搜索速度还减少了服务器消耗,可同时检索商品标题、标签、简介; 图表化的统计功能,销售信息更清晰; 美化商品,分类信息,店铺显示页面,更加漂亮和美观; 增加部分广告位,...

    mysql网络数据库指南(中文版) part1

    MySQL 是完全网络化的跨平台关系型数据库系统,同时是具有客户机/服务器体系结构的分布式数据库管理系统。它具有功能强、使用简便、管理方便、运行速度快、安全可靠性强等优点,用户可利用许多语言编写访问MySQL ...

    21行业网 v7.4 PHP MYSQL.rar

    仿百度搜索引擎,仿谷歌搜索引擎软件蜘蛛组件包括三大功能模块:链接采集、网页分析、无效网页扫描;自动识别GB2312、BIG5、UTF-8、Unicode等网页编码;文件类型证察防止非文本类型文件采集;蜘蛛可以采集ASP、PHP、...

    php网络开发完全手册

    15.4 使用PHP获取MySQL数据库的信息 255 15.4.1 获取数据库的信息 255 15.4.2 获取表的信息 256 15.4.3 获取列的数目 256 15.4.4 获取列的名称 257 15.4.5 获取列的数据类型 257 15.4.6 获取列的长度 257 15.4.7 ...

    MYSQL网络数据库PDF学习资源

    MySQL 是完全网络化的跨平台关系型数据库系统,同时是具有客户机/服务器体系结构的分布式数据库管理系统。 它具有功能强、使用简便、管理方便、运行速度快、安全可靠性强等优点,用户可利用许多语言编写访问MySQL ...

    美加PHP新闻聚合系统 v4.0 长尾词SEO版.rar

    自动抽取新闻:无需分析来源的网页编写特点,支持自动分析来源网页,自动抽取新闻正文。 自动翻译:全自动将外文翻译成中文,从而实现与原文不同,具有原创性。 自动后台更新:全自动后台刷新信息源,不影响访问...

    21行业网 v6.1 开源版_仿百度搜索引擎(带蜘蛛程序).rar

    仿百度搜索引擎,仿谷歌搜索引擎软件蜘蛛组件包括三大功能模块:链接采集、网页分析、无效网页扫描; 自动识别GB2312、BIG5、UTF-8、Unicode等网页编码; 文件类型证察防止非文本类型文件采集; 蜘蛛可以采集ASP...

    仿百度搜索引擎软件

    仿百度搜索引擎软件蜘蛛组件包括三大功能模块:链接采集、网页分析、无效网页扫描; 自动识别GB2312、BIG5、UTF-8、Unicode等网页编码; 文件类型证察防止非文本类型文件采集; 蜘蛛可以采集ASP、PHP、JSP等动态...

    用phplib做的一个文章发布系统案例

    判断 magic_quotes_gpc 的状态对变量做相应的处理。 修正部分主机无法登陆后台Bug。 允许程序在 register_globals = off 的环境下工作。 改善了自动安装脚本。 简练了 Mysql 数据库操作类文件。 改写了 js.php 文件...

    布谷直播源码完全开源.rar

    布谷直播系统源码 布谷一对一视频直播源码 布谷直播源码完全开源 品牌:thinkphp 语言:PHP 数据库:Mysql 移动端:Wap+App+(微信)小程序+自适应 完全开源(含全部源文件) 【2019布谷直播系统源码】 布谷直播...

    数据分页程序完全解决方案(含普通分页/分段分页/原始分页/since_id分页)

    4) 传统的分页, 分段式分页(每页内分为多段)归根结底是对数据集做一次切割, 映射到mysql的sql语法上, 就是根据输入求得limit子句, 适用场景为数据集变化频率低 5) since_id类分页, 其本质是假定已有数据无变化, 将...

    美加新闻聚合系统3.0

    自动抽取新闻:无需分析来源的网页编写特点,支持自动分析来源网页,自动抽取新闻正文。 自动翻译:全自动将外文翻译成中文,从而实现与原文不同,具有原创性。 自动后台更新:全自动后台刷新信息源,不影响访问...

    美加新闻聚合系统(长尾词SEO版) v4.0.zip

    自动抽取新闻:无需分析来源的网页编写特点,支持自动分析来源网页,自动抽取新闻正文。 自动翻译:全自动将外文翻译成中文,从而实现与原文不同,具有原创性。 自动后台更新:全自动后台刷新信息源,不影响访问...

    美加新闻聚合系统源码(经典兼容版) v3.6.rar

     自动抽取新闻:无需分析来源的网页编写特点,支持自动分析来源网页,自动抽取新闻正文。  自动翻译:全自动将外文翻译成中文,从而实现与原文不同,具有原创性。  自动后台更新:全自动后台刷新信息源,不影响...

    笨笨CMS内容管理系统.rar

    BBCMS采用PHP5 MYSQL做为技术基础进行开发,系统具有极强的可扩展性,并且完全开放源代码; BBCMS具有灵活的产品架构、严密的安全性、无限的伸缩性,能够高效构建起各种信息资讯类网站、企业内部知识网站、企业信息/...

    中国站长报总第四期

    关注 全方位网站流量分析 精华 IIS 错误代码大汇总 精华 IIS服务器完全配置使IIS实现ASP,CGI,PERL和PHP+MYSQL(图) 精华 让3721也无奈的弹出窗口(代码) 精华 让网页跳转的几种方法(代码) ...

    笨笨CMS内容管理系统 v1.0

    BBCMS采用PHP5+MYSQL做为技术基础进行开发,系统具有极强的可扩展性,并且完全开放源代码;BBCMS具有灵活的产品架构、严密的安全性、无限的伸缩性,能够高效构建起各种信息资讯类网站、企业内部知识网站、企业信息/...

    【YouDianCMS v9.1】 开源五合一建站系统+友点企业网站管理系统+数据自动同步

    1、完全开源:系统采用开源技术PHP+MYSQL开发,安全、成本低、性价比高、方便安装(全面支持PHP的最新版本)、功能不受限制、使用灵活;全面开放系统前端+后台的源代码,解除了开发者和用户的后顾之忧,完全支持二次...

    【YouDianCMS v9.1】 开源五合一建站系统+友点企业网站管理系统+数据自动同步.zip

    1、完全开源:系统采用开源技术PHP+MYSQL开发,安全、成本低、性价比高、方便安装(全面支持PHP的最新版本)、功能不受限制、使用灵活;全面开放系统前端+后台的源代码,解除了开发者和用户的后顾之忧,完全支持二次...

Global site tag (gtag.js) - Google Analytics