Home  >  Article  >  Backend Development  >  基于MySQL数据库的UTF8中文网站全文检索的实现_PHP

基于MySQL数据库的UTF8中文网站全文检索的实现_PHP

WBOY
WBOYOriginal
2016-06-01 12:25:09898browse

现在的互联网上,很多网站都提供了全文搜索功能,浏览者可以通过输入关键字或者是短语来搜索特定的资料。在PHP+MySQL构架的网站中,通常的做法是通过SELECT查询的Like语句来进行搜索,这一办法存在搜索不够精确、以及效率非常低下的缺点。比如对一个有十几万条记录数据表的TEXT字段进行LIKE操作,可能会花费上近10秒钟左右,这对网站的浏览者来说是一个非常糟糕的使用体验。如何在海量的数据中能够快速的进行全文检索呢?MySQL提供了一个全文索引功能,也就是把字段设置上FULLTEXT索引属性,然后通过SELECT的MATCH AGAINST语句进行查找。

我们开发的一个纯英文站点TouchUs - The Global Yellow Pages & Business Directory(www.touchus.org)就是利用MySQL的这一功能,实现了对十多万条数据的平均全文检索时间小于0.5秒。但是在开发TouchUs的中文网站——城市黄页网时(www.city39.cn),碰到了新的问题。原来英文排版时词和词之间是通过空格区分的,FULLText可以完全支持,但是对中文或者是东亚文字就没有这么简单了,因为中文的词和词之间并没有明显的分隔,所以MySQL不支持中文字符的全文检索。

如何让MySQL也能支持中文的全文检索呢?偶然间产生了一个思路,那就是能不能在中文分词后,通过对中文进行编码转化成英文字符,这样就在中英文间建立一个特定的联系,然后再进行全文检索,这样不就实现了中文的全文索引了吗?经过试验,答案是肯定的。下面是在城市黄页网中实现的具体过程:

1. 建立一个单独的索引表,比如对应members表,我们建立一个members_index表。

用户信息表(members)                    用户信息全文索引表(members_index)
User_id                                              user_id
User_name                                       index_intro
User_introduction                                    
 在members_index表的index_intro中加入fulltext索引。

2. 对用户信息表(members)的User_introduction字段内容进行中文分词处理

中文分词的处理过程,可以参考简易中文分词系统http://www.ftphp.com/scws/,在城市黄页网中,我们采用了scws的PHP扩展模块方式来实现中文分词。scws的php扩展模块安装非常简单,只需简单编译配置后即可使用。在具体的php代码中,我们写了如下的函数来实现分词后将分词结果用空格进行连接。

//中文分词函数
function str_fc($str) {
 $so = scws_new();
 $so->set_charset('utf8');
 // 这里没有调用 set_dict 和 set_rule 系统会自动试调用 ini 中指定路径下的词典和规则文件
 $so->send_text($str);
 while ($tmp = $so->get_result())
 {
  foreach (  $tmp as $ss ){
   $s = trim($ss[word]);
   if ( $s )
    $mystr .= trim($ss[word]) . " ";
    //echo urlencode(trim($ss[word])) . " ";
  }
 }
 return $mystr;
}
该函数返回就是用空格连接的分词结果。

3. 对分词结果进行编码,可以采用多种编码方式,比如base64编码、urlencode编码、汉字转拼音等,对gb2312甚至可以采用区位码编码方式。考虑到存储空间以及便利性,我们采用了PHP的urlencode编码方式。需要注意的是,在编码前,我们可以去掉重复的分词来节约存储空间,编码后要去掉编码结果中的%符号,因为urlencode采用RFC 1738进行编码,会产生很多%,而%在MySQL是通配符。下面是编码过程用到的PHP代码

$data = str_fc($data);  //中文分词
 $data = array_filter(explode(" ",$data)); //删除数组空项
 $data = array_flip(array_flip($data));  //删除重复项
 
 //对分词结果进行urlcode编码
 foreach (  $data as $ss ) {
  if (strlen($ss)>1 )
  $data_code .= str_replace("%","",urlencode($ss)) . " ";
 }
这里的$data_code就是编码后的结果。把编码结果根据user_id存入用户信息全文索
引表(members_index)

4. 在进行搜索处理时,首先对用户输入的关键字进行同样的分词编码处理,然后通过MySQL的SELECT的MATCH  AGAINST语句进行全文快速检索,根据检索结的user_id即可调用用户信息表(members)中的原始数据进行显示,而没有必要进行一次解码重组。

以上MySQL UTF8中文全文检索方法,目前在我们的2个中文网站——城市黄页网(www.city39.cn)和企业供求信息网(www.myglobalmarket.cn)中运行良好,平均检索时间均小于0.5秒。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn