堕落不振功业废,勤耕不辍日月新

Mysql全文索引无插件非分词实现方案

MySQL hailen 790℃

开篇,容我先说点废话


关于Mysql的中文全文索引的实现方式有很多,其中大多数都是用第三方Mysql插件来实现,而这些插件一般对环境都会或多或少的有点要求,而且插件本身也存在若干的问题,所以一般不是特别的需要,我是不会用这种方法的。

 

Mysql本身从4.0开始就已经支持FULLTEXT了,不过并不支持中文(或者说支持的非常不好),这种状况一直持续到现在。其主要原因就是中文分词实在太麻烦了。我们知道,英文中每个单词除了少数特殊字符和标点几乎都是以空格分隔的,为一段英文内容分词很简单,只要找到其中含有哪些分隔符就行了。而中文……太博大精深了,字与字之间没有类似于空格的分隔符,而且组成词组的规律也不同,很多时候一句话中同样的几个字可以分出不同的词,分词算法对这些歧义的识别能力也没有那么完美,就算是国内在这方面比较领先的海量分词也无法做到100%的准确。

 

 

 

正题,介绍一种无插件非分词的方法


我们知道Mysql是支持英文的全文索引的,而且它的分词方式就是上面提到的一些分隔符,比如空格,要让它支持中文其实很简单,就是把中文转换成英文或者数字,并且用空格分隔开来,当然,对于这些信息我们需要单独建个字段或者是表来存储。

对于如何将汉字转换成英文与数字,方法还是很多的,比如unicode,我用的就是这一种,函数如下:

 

/**
 * 将字符串转为Unicode编码
 *
 * @author XingDongHai (http://www.xingdonghai.cn)
 * @version 0.10
 * @param string $str 要转换的字符串
 * @param string $encoding 源字符串的编码
 * return string
 */

function str2Unicode($str, $encoding = 'GBK') {
    $str = iconv($encoding, 'UCS-2', $str);
    $arr = str_split($str, 2);
    $unicode = '';
    foreach ($arr as $tmp) {
        $dec = hexdec(bin2hex($tmp));
        $unicode .= $dec . ' ';
    }
    return $unicode;
}

 

 

一个例子:

表结构

 

CREATE TABLE IF NOT EXISTS `data` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `content` text,
  `searchindex` text,
  PRIMARY KEY (`id`),
  FULLTEXT `searchindex` (`searchindex`)
) TYPE=MyISAM DEFAULT CHARSET=utf8;

 

表中的searchindex字段就是unicode信息存储字段,它是又content内容转换而来的。

 

#老的搜索SQL类似:
SELECT id FROM `data` WHERE content LIKE '%关键词%';

#新的SQL:
SELECT id FROM `data` WHERE MATCH (`content`) AGAINST ('关键词' IN BOOLEAN MODE);

 

 

 

注意,应用范围


一般情况下是不需要这种方法的,比如你的记录数量很少的时候(一万以下),直接LIKE效率还是可以接受的。再就是此方法的弊端,会占用更多的数据空间,并且所占的大小还比较可观,因为用到全文索引的场景普遍数据量比较大,转换成unicode后的字符数也很多。

转载请注明:我是IT » Mysql全文索引无插件非分词实现方案

喜欢 (0)or分享 (0)