概述
全文索引与普通的索引不是一回事,在查找上方面其效率是普通模糊(like)查询的 N 倍,是 MySQL 专门提供用作搜索引擎的。
Mysql 5.6 之前版本,只有 MyISAM 支持全文索引,5.6 之后,Innodb 和 MyISAM 均支持全文索引,另外,只有字段的数据类型为 char、varchar、text 才可以建全文索引。
5.6 之后 MySQL 自带 ngram 解析器,可以解析中日韩三国文字,如果不使用 ngram 解析器,则 MySQL 默认使用空格与符号作为分隔符(对于英文自然够用了,但对于中日韩文字就不好用了,所以才需要 ngram 解析器)
创建索引
有两种方式:
一种是带有 ngram 解析器,会自动分词
ALTER TABLE news ADD FULLTEXT idx_full_text (`content`) WITH PARSER ngram;
另外一种是不带有 ngram 解析器的,以符号和空格分词
ALTER TABLE news ADD FULLTEXT idx_full_text (`content`);
查询
全文索引有专用的查询语法:match (字段) against (关键字),例如
select * from answer where match(content) against("测试表")
为了更好的搜索效果,通常会配置最小搜索长度。
全文索引的相关参数都无法进行动态修改,必须通过修改 MySQL 的配置文件来完成。
// MyISAM 全文索引的的分词
ft_min_word_len = 4; 默认值
ft_max_word_len = 84; 默认值
// InnoDB 全文索引的的分词
innodb_ft_min_token_size = 3; 默认值
innodb_ft_max_token_size = 84; 默认值
// ngram解析器令牌长度----即against()中字符串切分的最小字符长度,搜索语句的内容如果不是""起来,会被分词
ngram_token_size = 2~10 ; 默认值
通常修改最小搜索长度的值为 2,在 my.ini
,的 [mysqld]
的下面追加以下内容:
[mysqld]
innodb_ft_min_token_size = 2
ft_min_word_len = 2
ngram_token_size = 2
查看变量值
show variables like "%ft%"
三种全文搜索模式
自然语言模式
IN NATURAL LANGUAGE MODE,默认情况下为该模式,例:
-- 如果最小搜索长度ngram_token_size为1的话,则查找包含张,或三,或张三的记录;与布尔搜索模式中的‘+张三’结果相同
SELECT * FROM user WHERE MATCH(userName) AGAINST (‘张三’ );
布尔搜索模式
有以下几个操作符:
- 【+】----------必须包含此字符串
- 【-】----------必须不包含此字符串
- 【""】--------双引号内作为整体不能拆词
- 【>】--------提高该词的相关性,查询的结果靠前
- 【<】--------降低该词的相关性,查询的结果靠后
- 【
*
】---------通配符,只能接在词后面
例如,查询有"美女"的又有"动人"的记录:
SELECT * FROM user WHERE MATCH(userName) AGAINST ('+"美女" & +"动人"' IN BOOLEAN MODE);
查询扩展搜索
较少使用,没有细了解
多字段索引
对 title 和 body 字段建立索引
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER ngram;
然后 selec 语句如下使用即可:
SELECT
id,
title,
body,
MATCH (title,body) AGAINST ('标题' IN NATURAL LANGUAGE MODE) AS score
FROM
articles
where
MATCH (title,body) AGAINST ('标题' IN NATURAL LANGUAGE MODE)
ORDER BY score DESC;
不过上面这种方式,两个字段的权重是一样,有时候希望不同字段的权重不一样,例如希望你 title 字段权重大一点,这个只需要分别对字段建立索引,然后改下排序方式即可满足,例如:
SELECT
id,
title,
body,
MATCH (title) AGAINST ('标题' IN NATURAL LANGUAGE MODE) AS score_title,
MATCH (body) AGAINST ('标题' IN NATURAL LANGUAGE MODE) AS score_body
FROM
articles
where
(MATCH (title) AGAINST ('标题' IN NATURAL LANGUAGE MODE) OR MATCH (body) AGAINST ('标题' IN NATURAL LANGUAGE MODE))
-- 主要是改排序方式
ORDER BY score_title DESC,score_body DESC;
评论 (0)