PHP和MYSQL构建中文全文搜索引擎

SJY发表于:2018年05月10日 21:33 • 阅读:

全文搜索用的最多的是Sphinx,为了支持中文,还有很多扩展版本,最典型的就是 coreseek。先不说其配置的麻烦程度,最重要的是穷站长买不起服务器。本文主要讲述使用PHP和MYSQL来直接实现中文的全文搜索。

首先想到的是MYSQL自带的全文索引,但人家只是为了英文而开发的,是以空格来切词的。所以我就直接建立一张fulltext表,每次更新文章时,把标题和内容进行分词存储到这张表里,这样就实现了中文的全文索引。关于中文切词可参考我之前写的文章,PHP中文分词的几种方式总结

但实际效果并不是很理想,仅仅是把包含分词的文章搜索出来了,权重处理并不是太好,理想的排序应该是标题包含比内容包含排在前面,完全匹配比分词匹配排在前面。我在官方文档里看到一老外也有这个提议,下面是他给出的方法。引用来源 https://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html

Boolean searching has two deficiencies: 1) results are not sorted by relevance and; 2) no method by which to weigh certain columns. There is a way around both of these problems. For example, if I have a table of articles and want to weigh the title more heavily than the text, I can do the following:

SELECT *, ( (1.3 * (MATCH(title) AGAINST ('+term +term2' IN BOOLEAN MODE))) + (0.6 * (MATCH(text) AGAINST ('+term +term2' IN BOOLEAN MODE))) ) AS relevance FROM [table_name] WHERE ( MATCH(title,text) AGAINST ('+term +term2' IN BOOLEAN MODE) ) HAVING relevance > 0 ORDER BY relevance DESC;

Here we artificially manipulate the relevancy score to give title more weight by multiplying by the constant 1.3. In the above query, it doesn't seem to matter whether I have 3 fulltext indexes or just one comprising the title and text columns. From my testing, the results appear to be the same.

MYSQL全文索引我个人是不太喜欢,想要用此方法者可看下这篇基础:http://www.sjyhome.com/php/mysql-fulltext-index.html

我的思路是先从MYSQL读取数据,然后通过PHP进行权重分配。下面是3种读取mysql数据的方法,测试数据2000条左右。

REGEXP平均时长0.6秒,正则匹配,代码短,效率差

SELECT a.`id`,`title`,`content` FROM `posts`a INNER JOIN `posts_data`b ON a.`id`=b.`id` AND CONCAT(`title`,`content`) REGEXP '三国|武将|吕布|方天画戟'

读取全部数据,平均时长0.4秒,而且随着数据量变大会越来越慢,不可取。目前2000条数据,速度要比上面的正则快的多。

SELECT a.`id`,`title`,`content` FROM `posts`a INNER JOIN `posts_data`b ON a.`id`=b.`id`

LIKE平均时长0.15秒,代码比REGEXP多了很多,但效率大幅度提高

SELECT a.`id`,`title`,`content` FROM `posts`a INNER JOIN `posts_data`b ON a.`id`=b.`id` WHERE CONCAT(`title`,`content`) LIKE '%三国%' OR CONCAT(`title`,`content`) LIKE '%武将%' OR CONCAT(`title`,`content`) LIKE '%吕布%' OR CONCAT(`title`,`content`) LIKE '%方天画戟%'

很明显,我肯定取最后一种方案。通过PHP中文分词,然后在表里查询包含这些分词的数据,最后用PHP对这些数据进行权重分配,具体PHP怎么做,根据自己的需求来,这里仅提供一个思路。本文结束!

欢迎转载,但请保留原文地址 http://www.sjyhome.com/php/php-mysql-chinese-full-text-search-engine.html

标签: 搜索引擎

回复(0)