>데이터 베이스 >MySQL 튜토리얼 >中文模糊搜索_MySQL

中文模糊搜索_MySQL

WBOY
WBOY원래의
2016-05-30 17:10:021408검색

什么是模糊搜索?为什么要使用模糊搜索?相信大家都知道这些,我就不讲了。今天只讲怎么使用模糊搜索。

 

一 LIKE。大名鼎鼎的like字句,使用方便,兼容性好,易维护,但效率奇低。大家都会用,不多介绍。

 

二 MYSQL 原生支持的全文索引(FULLTEXT index)。

 

实现方式:首先给目标字段添加索引,索引的类型是FULLTEXT,然后查询的时候,在sql语句的where条件后面使用against()去指定关键字就好了。

 

而网上很多文章对这个理解却有很多误区,认为FULLTEXT不支持中文,或者Linux下全文索引不支持中文,然后说要把中文转为拼音就好了。事实上不是这样的,重点是在于分词,因为中文没有自然分词,不像英文每个单词都有空格隔开,而转为拼音之后,每个字对应的拼音之间也像单词一样空格隔开,所以才有了“FULLTEXT不支持中文,要把中文转为拼音”这一说法。

 

其实,转拼音也行、按照分词规则把一个个词组用空格隔开也好、甚至简单粗暴的每个字空格隔开都可以,然后把这些用空格隔开的文本存入都数据库的一个特定字段里面,也就是数据库里面要一份信息要存两个字段,一段原始文本/一段分词之后的文本。注意,FULLTEXT 索引要设置在分词之后的那个字段上面。

 

优点:与使用like字句相比,更加高效,且MYSQL 原生支持。

 

缺点:要额外维护一个字段,而且需要自行分词。使用复杂,有多复杂?请见下文(FULLTEXT全文索引的几个关键点)

 

三 使用第三方组件,(Coreseek)sphinx、迅搜……

 

实现方式:把数据中需要搜索的字段连同Id,一起导入到这些第三方组件中去,搜索的时候,调用这些第三方组件提供的api去搜索,得到返回的Id,再根据Id去数据库查询。

 

优点:比上面两种方案都要高效,且不需要自行分词。

 

缺点:需要额外维护这个第三方组件,并且每次更新数据库都要同时更新它。

 

而我选择了方案三,至于维护与同步,都交给了定时任务去做了。

 

-- FULLTEXT全文索引的几个关键点

 

1. 表的存储引擎需要是MyISAM,听说MYSQL5.6也支持全文索引了;

 

2. 字段类型:char、varchar和text;

 

3. MySQL全文索引查询关键词最小长度限制;

 

=> ft_min_word_len,默认是4,建议改为1,不然against()对应的关键字就只能是4个以上的字符,查不了单个字符,也查不了单个汉字.

 

=> my.ini配置文件中添加

[mysqld]

ft_min_word_len = 1

 

=> 设置 ft_min_word_len 之后,要重启MySQL服务,然后执行 SHOW VARIABLES 查看 ft_min_word_len设置成功没有;

 

=> 重新设置配置后,已经设置的索引需要重新设置生成索引,不然有可能报错,

我在update某些记录的时候就报错了: Incorrect key file for table './webm/temp.MYI';try to repair it. 

 

后来, 我执行了 mysql> repair table 表名; 就好了;

 

5. match(索引名),match()的参数是索引名,不是字段名;

 

=> MATCH(title, content)里的参数必须和FULLTEXT(title, content)里的参数一模一样。

 

6. match(singername,songname),可以同时在多个索引名里面查找关键字;

 

7. 如果一个关键词在50%的数据出现,那么这个词会被当做无效词,可以使用against('关键字'IN BOOLEAN MODE)绕过无效设定;

 

8. 如果搜索多个词,请用空格或者逗号隔开,如下

 

=> SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a x');

 

=> SELECT * FROM `temp` WHERE MATCH(`char`) AGAINST ('a,x');

 

=> AGAINST('关键字1 关键字2'),使用逗号或空格隔开多个关键字,使用的是or规则.

 

9. 每次更新表都会重构索引,索引使用了全文索引会拖慢insert和update;

 

10. 搜索语法规则;

 

=> + 一定要有(不含有该关键词的数据条均被忽略)。

 

=> - 不可以有(排除指定关键词,含有该关键词的均被忽略)。

 

=> " " 用双引号将一段句子包起来表示要完全相符,不可拆字。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.