文档章节

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

h
 hackdl
发布于 2015/06/08 09:59
字数 1470
阅读 48
收藏 2
这次给大家渗透些比较高级些的.关于搜索的东西.
首先,大家先去下载一份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全文搜索分词方式.

本文转载自:http://hackerdl.blog.51cto.com/867412/285237

h
粉丝 0
博文 46
码字总数 0
作品 0
东城
私信 提问
robbe+base64+Mysql简易有效的php全文索引实现

确实有很多方法来给php提供全文索引功能。 例如: 1。solr或者lucene,(需要安装对应的php客户端扩展)。 2。sphinx 3。基于任何一个数据库(key/value的最好)的模拟实现。 4。Mysql的全文索...

狮子的魂
2013/03/01
0
2
用Kibana和logstash快速搭建实时日志查询、收集与分析系统

Logstash是一个完全开源的工具,他可以对你的日志进行收集、分析,并将其存储供以后使用(如,搜索),您可以使用它。说到搜索,logstash带有一个web界面,搜索和展示所有日志。 kibana 也是...

amwuqd
2014/08/29
0
0
MySQL索引的分类(根据数据结构)

MySQL索引的分类(根据数据结构) 索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。 数据库查...

秋风醉了
2014/08/30
0
0
伍哥原创之豆荚商城商品搜索架构介绍

豆荚商城(www.dou55.com)商品搜索架构介绍 1,需求分析 伍哥所在的豆荚商城是一个家电行业的B2C网上零售平台。作为这样一个平台,自然少不了一个强大而且快速的商品搜索功能啦。这个搜索的...

alex.wu
2012/08/06
0
0
基于mysql全文索引的深入理解

前言:本文简单讲述全文索引的应用实例,MYSQL演示版本5.5.24。 Q:全文索引适用于什么场合? A:全文索引是目前实现大数据搜索的关键技术。 至于更详细的介绍请自行百度,本文不再阐述。 ----...

pureboys
2014/12/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java的战争

本文来自微信公众号: 金捷幡(ID:jin-jiefan) ,作者:金捷幡,封面:拉里·埃里森(东方IC) 2019年5月,彻底撕破脸的特朗普掀起对华为的战争,谷歌被迫吊销了华为的Android授权。开源软...

Java领航员
36分钟前
1
0
超详细的LM3414MRX/NOPB规格参数介绍就在这里

超详细的LM3414MRX/NOPB规格参数介绍就在这里 描述 LM3414和LM3414MRX/NOPB是具有1-A 60 W(1)共阳极功能的恒流降压LED驱动器。它们适用于驱动单串3-W HBLED,效率高达96%。它们可接受4.5...

不能吃肉的仙女
43分钟前
1
0
Eclipse国内镜像源配置方法

Table of Contents 我们在国内从官网下载Eclipse以及插件非常慢,那么,有没有方法变快呢? 有,那就是使用国内的公开镜像源替换官方源。 1 下载Eclipse 首先,我们看一个链接地址: http:/...

求神
今天
5
0
java 请求服务

一.第一种基于java web http 请求服务,必须用tomcat 容器启动才能对外提供服务 在maven 工程中pox 文件导入jar <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>h......

zaolonglei
今天
5
0
HDFS工作机制——自开发分布式数据采集系统

需求描述: 在业务系统的服务器上,业务程序会不断生成业务日志(比如网站的页面访问日志) 业务日志是用log4j生成的,会不断地切出日志文件,需要定期(比如每小时)从业务服务器上的日志目...

须臾之余
今天
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部