天天看点

PHP+MYSQL实现全文检索及全文检索工具

使用分词类库,分词类库请参见:http://www.xunsearch.com/scws/

如何使用php实现全文检索功能?

很多人可能马上可以想出几种方案,比如:文件检索法、采用sql的like语句等方法,但这些方法效率都相当的低。

这里介绍一种比较高效的php全文检索实现方法,这就是采用mysql的fulltext字段类型。但是mysql的fulltext字段对中文的支持不是很好,本文也一并介绍如何通过php+mysql实现中文全文检索功能。

首先需要用到一个php中文分词扩展模块——scws,关于这个模块的安装和使用大家可以到www.ftphp.com/scws去查找相关内容(如有问题请留言)。

然后再看看mysql的fulltext字段类型的相关信息:

mysql3.23.23之后的版本开始支持全文索引和搜索。全文索引在 mysql 中是一个 fulltext 类型索引。

fulltext 索引用于 myisam 表,可以在 create table 时或之后使用 alter table 或 create index 在 char、varchar 或 text 列上创建。对于大的数据库,将数据装载到一个没有 fulltext 索引的表中,然后再使用 alter table (或 create index) 创建索引,这将是非常快的。将数据装载到一个已经有 fulltext 索引的表中,将是非常慢的。

mysql全文搜索通过 match() 函数完成。

下面举一简单例子:

1、新建数据表:

create table fulltext_sample(copy text,fulltext(copy)) type=myisam;

这里的copy就是一个fulltext类型的字段,如果建表的时候没有添加全文检索字段,也可以通过alert来添加,如:

alter table fulltext_sample add fulltext(copy)

2、插入数据:

insert into fulltext_sample values

(‘it appears good from here‘),

(‘the here and the past‘),

(‘why are we hear‘),

(‘an all-out alert‘),

(‘all you need is love‘),

(‘a good alert‘);

3、数据检索:

select * from fulltext_sample where match(copy) against(‘love‘);

上面就是mysql的全文检索功能,注意:在全文索引上进行搜索是不区分大小写的。

下面再看如何实现中文全文检索。

fulltext字段是以词语为单位,词语之间需要用空格隔开,而汉语的句子中各个词语之间并不会用空格隔开,因此我们需要对中文进行分词,这也就是为什么上面需要强词用到中文分词扩展模块。

但是尽管对中文进行分词,mysql还是不能通过match来实现中文的全文检索,这需要通过一定的方法来进行转换,一个比较简单实用的方法是采用下面这个函数(当然还有更好的),它将中文进行了urlencode转换。

function q_encode($str)

{

$data = array_filter(explode(" ",$str));

$data = array_flip(array_flip($data));

foreach ($data as $ss) {

  if (strlen($ss)>1 )

   $data_code .= str_replace("%","",urlencode($ss)) . " ";

}

$data_code = trim($data_code);

return $data_code;

将转换过后的内容保存至事先定义好的fulltext字段。同样,在查询的时候也需要将查询的关键词进行同样方法的转换。

php+mysql实现utf8全文搜索的方法

本文讲解一下如何在海量的数据中能够快速的进行全文检索呢?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中文全文检索方法.

全文检索工具:http://www.xunsearch.com