MySQL全文检索中文搜索

4 篇文章 0 订阅
3 篇文章 0 订阅

全文检索概述:

        全文搜索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。对于Google、百度都是比较典型的全文搜索引擎系统。
        百度百科:全文检索是将存储于数据库中整本书、整篇文章中的任意内容信息查找出来的检索。它可以根据需要获得全文中有关章、节、段、句、词等信息,也可以进行各种统计和分析。例如,它可以回答“《红楼梦》一书中“林黛玉”一共出现多少次?”的问题。


检索基本过程:

全文检索大体分两个过程,索引创建(Indexing)和搜索索引(Search)。
• 索引创建:将需要被搜索的数据提取信息,创建索引的过程。
• 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。

全文检索的索引创建过程一般有以下几步:

1:准备待索引的原数据

2:将原数据传给分词组件。
分词组件会做以下几件事情:
1. 将文档分成一个一个单独的单词。
2. 去除标点符号。
3. 去除停词(Stop word)。

经过分词(Tokenizer)后得到的结果称为词元(Token)。

3:将得到的词元(Token)传给语言处理组件(Linguistic Processor)。

对于英语,语言处理组件一般做以下几点:
1. 变为小写(Lowercase)。
2. 将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming。
3. 将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization。

语言处理组件的结果称为词(Term)。

4:将得到的词(Term)传给索引组件(Indexer)。

索引组件(Indexer)主要做以下几件事情:
1. 利用得到的词(Term)创建一个字典。

2. 对字典按字母顺序进行排序。

3. 合并相同的词(Term)成为文档倒排(Posting List)链表。


简单的中文分词算法:

简单的中文分词算法知识,一般采用N元分词法对中文词句进行拆分。基本过程是,对于中文文档,首先过滤标点符号,将其替换成空格,然后对空格之间的每一段词句依次拆分,每个词元为N个字,然后合并相同的词元,并对词元进行排序。

一元分词法:

例句:

上有天堂,下有苏杭!

根据上面的过程,首先我们将标点符号替换为空格,则句子转化为:

上有天堂 下有苏杭

然后对于一元分词,一个字就是一个词元,句子拆分为:

上 有 天 堂 下 有 苏 杭

最后合并相同的词元,得到结果如下:

上 有 天 堂 下 苏 杭


二元分词法:

同样的对于上面的句子,第一步是相同的,对于二元分词,两个字作为一个词元,依次拆分为:

上有 有天 天堂 下有 有苏 苏杭

最后合并相同词元,得到分词结果:

上有 有天 天堂 下有 有苏 苏杭

 

搜索结果排序:
按照匹配相似度排序,相似度最高的排在最前面,以此降序排列。


Mysql全文检索过程介绍:

Mysql从4.0版本开始支持全文检索,但是只是对英文支持全文索引。对于中文全文检索,首先我们需要将中文转变为mysql眼中的英文,然后它才能以英文分词算法去对句子进行正确的分词处理,以便建立起全文索引。

例如对于上面的结果:

上有 有天 天堂 下有 有苏 苏杭
这样的分词结果已经符合mysql眼中的“英文”书写格式,但是mysql中的ft_min_word_len这个参数的默认值为4,也就是4个字母以上长度的单词,才会被考虑,小于4个的,将会被忽略。我们需要修改这个长度,这样才能搜索到像天堂、苏杭等这样的短词语,比如将其设置成2,但是这样做有一个缺点,它也会检索到一些像PHP,HP等过于短小的英文词语,从而出现很多无意义的搜索结果。

还有另外一种方法来避开这个问题,那就是把中文转变为另外一种语言,比如MD5,分词结果转变为:

上有 有天 天堂 下有 有苏 苏杭 => 4ab801a555e6ff20e33cdd4e585c474e 8c59fda62e9e91995c40561ae6da83ad e69ee86290f7dd5d96c93546dfa5f83e 
985462310c8c259f4dfddda070a5181d 7937ff7349ba8c433c3eb088c853c6f6 16c6a7b45e0b49bbb9be1a820316715b 
这样做,使得中文大于了默认的2个字符,同时避免了中文词语的歧义性。

MD5之后的索引确实可以解决上面的问题,但是MD5的字符串太长了,占用空间太大,解决这个问题,我们可以用区位码来表示中文词元,一个四位的十进制数可以表示一个汉字,那么上面的分词结果可以转变为:

上有 有天 天堂 下有 有苏 苏杭 => 41475148 51484476 44764435 47345148 51484353 43532628

这样表示汉字词元,既使每个词元长度大于ft_min_word_len的默认长度2,同时又缩短了长度,不至于占用很大的存储空间,我们可以将分词结果存储于索引表中以备查询之用。

具体例子:

表结构:article

title        varchar 200 -------- 用于存放标题 (显示用)
search   text              -------- 用于存放标题分词结果 (检索用)

为字段search建立fulltext 索引

首先我们在将标题保存到数据库的时候,就已经将标题分词并转为区位码,保存到search字段中,以用于全文索引。

我们搜索标题:“苏杭  人间的天堂

经过分词转区位码操作,结果为:

苏杭  人间的天堂 => 43532628 40432868 28682136 21364476 44764435
然后进行全文检索查询:

SELECT title, MATCH(search) AGAINST('43532628 40432868 28682136 21364476 44764435' IN BOOLEAN MODE) 
AS score FROM la_search 
WHERE MATCH(search) AGAINST('43532628 40432868 28682136 21364476 44764435' IN BOOLEAN MODE) 
ORDER BY score DESC
LIMIT 0,5
这里将score作为相似度,按照相似度进行降序排列,相似度最高的显示在最前面。

最后在实际使用中,我们需要提取score大于1的数据,并且结果会将标题也计入结果集中,需要将其过滤输出。


中文二元分词方法及区位码转换代码:http://blog.csdn.net/luochuan/article/details/7298300


参考资料:

区位码百度百科:http://baike.baidu.com/view/685605.htm

区位码查询:http://quwei.911cha.com/

Mysql全文检索介绍:http://www.21andy.com/blog/20080123/779.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值