网络编程
位置:首页>> 网络编程>> 数据库>> 通过MySQL内置全文检索实现中文的相关检索

通过MySQL内置全文检索实现中文的相关检索

 来源:Asp之家 发布时间:2010-06-11 13:20:00 

标签:MySQL,全文检索,中文,检索,分词

在MySQL4中,是已经开始支持全文检索(索引)的了。但是只是对英文支持全文检索。

由于英文在书写上的特殊性,使得分词算法相对中文来说,简单得多。一般来说,我们可以通过单词与单词之间的空格,以及标点符号来完成这个分词过程。

但是就中文来说,就没有那么简单。MySQL无法对中文做出正确的分词,假设有如下英文句子:


"Hello world! Hello PHP!"


通过上面提及的方法,可以很简单的把这个句子分词为:


1 Hello

2 world

3 PHP

我们再来看看中文的句子:


"你好世界,你好PHP!"


按照英文的算法,分词如下:


1 你好世界

2 你好PHP

显然是不能满足我们的需要的。


所以,首先我们要做的是,把中文的句子转变为MySQL眼中的英文,以便使得它能以英文分词算法去对句子进行正确的分词处理。

先将上面中文句子进行标点过滤处理,得到以下句子:


你好世界 你好PHP

接着再使用中文分词中较简单实现的二元分词算法对句子进行二元分词,得到以下句子:


你好 好世 世界 你好 PHP

因为把标点符号替换为空格,以及PHP本身为英文字母的关系,可以不用进行二元切分,所以得到上面句子。

这个时候,我们来看看处理过后的句子,会发现,就其书写格式上来说,已经符合英文的书写格式,既以空格,标点来对单词形成自然间隔。只是上面句子没有标点,只有空格而已。

到此,我们已经成功的将中文“翻译”为MySQL能理解的“英文”书写格式。


但是,问题还没解决,首先,MySQL中,ft_min_word_len(分词词汇最小长度)这个参数的默认值为4,也就是4个字母以上长度的单词,才会被考虑,小于4个的,将会被忽略。

如果不改变这个长度,按照上面的分词结果,我们将无法通过 你好,世界,PHP等检索到相关的结果,因为分出来的词太短了,不在MySQL的选择范围内。

我们可以通过修改ft_min_word_len的值,将其设置为2来解决上面问题,但是这样做的话,在检索列表中的原本就为英文的短小词汇,如:PHP,MP3,也会被划入检索范围内,这样做的结果是,出现很多无意义的相关结果。


请看以下列表:


[MP3] the look

[MP3] because of you


因为他们都同有MP3在标题中,所以会出现上述提到的问题。


回到ft_min_word_len值的问题,我们之所以要修改他,是为了能让MySQL找到我们的二元分词,但是短小的英文又被“无辜”的卷入,我们目前要解决的问题就是,如何使得MySQL能检索到二个字的中文词汇,又能忽略掉原本的英数?第一个反应是把中文MD5,这样以上分词就将转化为以下结果:


你好 好世 世界 你好 PHP => b94ae3c6d892b29cf48d9bea819b27b9 f5625345be46432fb0fd51340fcf6679 9067de5206278a93823f9c5dc2c737fd b94ae3c6d892b29cf48d9bea819b27b9 PHP

这样做,首先是使得中文分词的长度超越了默认的2个字,同时消除了中文的歧义性。(MySQL4对中文的处理有问题),搜索“车轮”时候,不再会出现类似“发动机”结果的问题。(车轮的例子只是为了方便理解而做出的假设)


通过上面的做法,已经解决了分词最小长度的问题,顺利的把中文词汇长度升级,从而达到把中文词汇划入检索范围,把较短的英数划出检索范围。

休息一下,然后发现这个MD5后的字符串是否太长了点……比较占用空间,要不,于是想到区位码,4位数的区位码能表示一个GB汉字,一个词有二个汉字组成,转换为区位码后是8个数字。不但能确定惟一性,也就MD5而已减少了长度。下面是转换后的:


你好 好世 世界 你好 PHP => b94ae3c6d892b29cf48d9bea819b27b9 f5625345be46432fb0fd51340fcf6679 9067de5206278a93823f9c5dc2c737fd b94ae3c6d892b29cf48d9bea819b27b9 PHP => 36672635 26354232 42322971 36672635 PHP

呵呵,是不是比MD5的小了很多呢?最后我们把相同的词汇留一个,多余的删除。得到

36672635 26354232 42322971 PHP

于是就完成了 "你好世界,你好PHP!" 到 "36672635 26354232 42322971 PHP" 的转换。

通过上面方法结合MySQL全文检索语句,我们可以通过给出一个标题例如:"迈克尔·杰克逊 -《危险之旅之布加勒斯特站》"找出类似以下的相关标题

迈克尔杰克逊 -《迈克尔杰克逊危险布加勒斯特演唱会》

Michael Jackson -《迈克尔杰克逊 罗马尼亚 危险演唱会》

迈克尔杰克Michael Jackson -《危险之旅》

迈克尔杰克逊 -《迈克尔杰克逊 美国50annive演唱会危险片段》

迈克尔杰克逊 -《迈克尔杰克逊 终极收藏 原版DVD危险演唱会》

迈克尔杰克逊 杰克逊五兄弟 -《The Jackson Motown 25 演唱会》

迈克尔杰克逊 -《迈克尔杰克逊BAD曰本Yokohama演唱会》

迈克尔杰克逊 -《迈克尔杰克逊曰本大阪演唱会》

迈克尔杰克逊 -《迈克尔杰克逊之胜利-达拉丝演唱会》

迈克尔杰克逊 -《迈克尔杰克逊之胜利演唱会 比丽珍 片段》

迈克尔杰克逊 -《迈克尔杰克逊德国危险演唱会之 billie jean片段》

迈克尔杰克逊 -《Michael Jackson -30周年演唱会》

Michael Jackson -《迈克尔杰克逊 马尼拉 历史演唱会》

迈克尔杰克逊 -《1993年美国橄榄球中场休息精彩表演》

表结构 article

title varchar 200 -------- 用于存放标题 (显示用)

ft text ---- fulltext 用于存放标题分词结果 (检索用)

首先我们在把标题保存到数据库时候,就已经对标题进行分词转区位码,保存到ft字段中,用于相关性的检索。

然后把给出的标题"迈克尔·杰克逊 -《危险之旅之布加勒斯特站》"转为"34853143 31432291 22910104 01042960 29603143 31434923 46034753 47535414 54143435 34355414 54141828 18282851 28513253 32534325 43254456 44565330",最后进行全文检索查询:

SELECT title, MATCH( ft ) AGAINST( '34853143 31432291 22910104 01042960 29603143 31434923 46034753 47535414 54143435 34355414 54141828 18282851 28513253 32534325 43254456 44565330' IN BOOLEAN MODE ) AS score

FROM article

WHERE MATCH( ft ) AGAINST( '34853143 31432291 22910104 01042960 29603143 31434923 46034753 47535414 54143435 34355414 54141828 18282851 28513253 32534325 43254456 44565330' IN BOOLEAN MODE )

ORDER BY score DESC

LIMIT 0, 5

从SQL Query上来看,进行了两次全文检索,其实不然,MySQL会将其视为一次,所以不比担心。

同时使用了AS score,这个score是相似度,分值越高,自然越与给出的标题相近。

二点建议:

1.在实际使用中,挑选score大于1的作为检索结果。

2.检索结果会将本身标题也算入其中,根据score排序,为第一条,别忘记过滤哦 ^_^。

站在用户的立场来说,我们给用户提供了更多的相关内容,站在搜索引擎立场上来说,给关键字提供了更多的相关链接,形成了良好的站内互联结构,提高了搜索引擎对网页的评价。

如果各位碰到错误的不合理的地方,恳请指正,共同进步。谢谢!

0
投稿

猜你喜欢

  • 什么是事件代理(Event Delegation)?如果不太了解的朋友,可详细阅读:《Event delegation in JavaScr
  • 内容: ************* 1安装MYSQL后更改了ROOT的密码后用 net startmysql 启动时我就遇到了这样的问题.使
  • 每个人都可以编写CSS代码,甚至你现在已经让它为你的项目工作了。但是CSS还可以更好吗?开始用这5个Tips改进你的CSS吧!一、关于CSS
  • 由于数据文件平时在数据库运行的时候处于使用状态,故当数据库处于打开状态时,管理员是无法重命名数据文件名字的。那么一定要更改这个数据文件的名字
  • 阅读上一篇:W3C优质网页小贴士(三)明智地选择 URI没有什么比走到你最喜欢的商店门口,却发现店门紧闭,而且没有看见店面搬迁告示这种事情还
  • 1) 用正式表达式 regexp "[u0391-uFFE5]"2) 用length和char_lengthdrop t
  • MySQL从5.1开始支持event功能,类似oracle的job功能。有了这个功能之后我们就可以让MySQL自动的执行数据汇总等功能,不用
  • 生成静态页的方法有很多种,我比较喜欢用xmlhttp的方法生成,因为我不用考虑很多东西,我只要把动态的asp页面编写好就行了。<% s
  • 首先介绍下简朝阳.现就职于阿里巴巴(中国)网络技术有限公司DBA Team运维部, 简朝阳是本次MYSQL技术征文大赛第三名得主(获奖文章:
  • 1. 排名函数与PARTITION BY --所有数据 SELECT * FROM dbo.student AS a INNER JOIN
  • 检测是否注册成功<% Set Jpeg =Server.CreateObject("Persi
  • 第一种情况:有RAID,还需要做数据库备份吗?回答:需要。有了RAID,万一部份磁盘损坏,可以修复数据库,有的情况下数据库甚至可以继续使用。
  • 经常写一些联合查询,联合一多了,代码就成倍的增加,时间一长,连我自己也看不懂到底是什么意思了。做Oracle 的时候,就看到有个 WITH,
  • 相对于 Ajax,服务端 XMLHTTP 就是在服务端使用 XMLHttpRequest 对象了。虽然说,在服务端使用异步请求是比较不方便的
  • 先看几个数据。。一大堆文字滴,不管人家是不是故意的,字数还是这样:news.163.cn:14px,39个中文字符 news.sina.co
  • 即使MyISAM表格式非常可靠(SQL语句对表做的所有改变在语句返回之前被写下),如果下列任何事件发生,你依然可以获得损坏的表:&m
  • 为最终用户提供的功能主要由一个HTML文件和两个ASP文件提供,它们负责接受用户的订阅申请以及退出邮件列表申请。 用户的个人信息在图1所示的
  • 话说土匪老湿在他的大作 《交互设计之回归篇》 里曝光了上次有意思小组竞赛我们小组分享的话题 “瞬间的快感”,但这一极具噱
  • 昨天群里介绍了一个专门帮你PS图片的网站。吐司网。网站在图片的预览处理上有点意思。当鼠标经过图片,显示为处理过的图片。这样大家能很清晰的对比
  • 在翻译这篇文章时我想起一件事情,去年有个朋友在网上非常兴致勃勃的和我说:“我弄了一个很酷的网站,去玩玩吧!真的不错哦!”,然后他把网址发给我
手机版 网络编程 asp之家 www.aspxhome.com