在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
基于 Mysql 实现一个搜索引擎前言: 其实 Mysql 很早就支持全文索引了,只不过一直只支持英文的检索,从5.7.6 版本开始,Mysql 就内置了 ngram 全文解析器,用来支持中文、日文、韩文分词。 Mysql 全文索引采用的是倒排索引的原理,在倒排索引中关键词是主键,每个关键词都对应着一系列文件,这些文件中都出现了这个关键词。这样当用户搜索某个关键词时,排序程序在倒排索引中定位到这个关键词,就可以马上找出所有包含这个关键词的文件。
一、ngram 全文解析器ngram 就是一段文字里面连续的 n 个字的序列。ngram 全文解析器能够对文本进行分词,每个单词是连续的 n 个字的序列。例如,用 ngram 全文解析器对“你好靓仔”进行分词: n=1: '你', '好', '靓', '仔' n=2: '你好', '好靓', '靓仔' n=3: '你好靓', '好靓仔' n=4: '你好靓仔' MySQL 中使用全局变量 可以通过以下命令查看 Mysql 默认的 show variables like 'ngram_token_size' 有两种方式可以设置全局变量 (1)启动 mysqld 命令时指定: mysqld --ngram_token_size=2 (2)修改 Mysql 配置文件 my.ini,末尾增加一行参数: ngram_token_size=2 二、创建全文索引1、建表时创建全文索引CREATE TABLE `article` ( `id` bigint NOT NULL, `url` varchar(1024) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `title` varchar(256) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', `source` varchar(32) COLLATE utf8mb4_general_ci DEFAULT '', `keywords` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL, `publish_time` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`), FULLTEXT KEY `title_index` (`title`) WITH PARSER `ngram` ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 2、通过 alter table 方式ALTER TABLE article ADD FULLTEXT INDEX title_index(title) WITH PARSER ngram; 3、通过 create index 方式CREATE FULLTEXT INDEX title_index ON article (title) WITH PARSER ngram; 三、检索方式1、自然语言检索(NATURAL LANGUAGE MODE)自然语言模式是 MySQL 默认的全文检索模式。自然语言模式不能使用操作符,不能指定关键词必须出现或者必须不能出现等复杂查询。 示例: select * from article where MATCH(title) AGAINST ('北京旅游' IN NATURAL LANGUAGE MODE); // 不指定模式,默认使用自然语言模式 select * from article where MATCH(title) AGAINST ('北京旅游'); 可以看出,该模式下根据“北京旅游”搜索,可以搜索出包含“北京”的或者包含“旅游”的内容,因为它是根据自然语言分成了两个关键词。 上面示例中返回的结果会自动按照匹配度排序,匹配度高的在前面,匹配度是一个非负浮点数。 示例: // 查看匹配度 select * , MATCH(title) AGAINST ('北京旅游') as score from article where MATCH(title) AGAINST ('北京旅游' IN NATURAL LANGUAGE MODE); 2、布尔检索(BOOLEAN MODE)布尔检索模式可以使用操作符,可以支持指定关键词必须出现或者必须不能出现或者关键词的权重高还是低等复杂查询。 示例: // 无操作符 // 包含“约会”或“攻略” select * from article where MATCH(title) AGAINST ('约会 攻略' IN BOOLEAN MODE); // 使用操作符 // 必须包含“约会”,可包含“攻略” select * from article where MATCH(title) AGAINST ('+约会 攻略' IN BOOLEAN MODE); 更多操作符示例: '约会 攻略' 无操作符,表示或,要么包含“约会”,要么包含“攻略” '+约会 +攻略' 必须同时包含两个词 '+约会 攻略' 必须包含“约会”,但是如果也包含“攻略”的话,匹配度更高。 '+约会 -攻略' 必须包含“约会”,同时不能包含“攻略”。 '+约会 ~攻略' 必须包含“约会”,但是如果也包含“攻略”的话,匹配度要比不包含“攻略”的记录低。 '+约会 +(>攻略 <技巧)' 查询必须包含“约会”和“攻略”或者“约会”和“技巧”的记录,但是“约会 攻略”的匹配度要比“约会 技巧”高。 '约会*' 查询包含以“约会”开头的记录。 '"约会攻略"' 使用双引号把要搜素的词括起来,效果类似于like '%约会攻略%', 例如“约会攻略初级篇”会被匹配到,而“约会的攻略”就不会被匹配。 四、与 Like 对比全文索引和 like 查询对比,有以下优点:
而且全文检索的性能也是优于 like 查询的 以下是以 50w 左右数据进行的测试: // like 查询 select * from article where title like '%北京%'; // 全文索引查询 select * from article where MATCH(title) AGAINST ('北京' IN BOOLEAN MODE); 可以看出 like 查询是 1.536s,全文索引查询是 0.094s,快了16倍左右。 全文索引能快速搜索,但是也存在维护索引的开销。字段长度越大,创建的全文索引也越大,会影响DML语句的吞吐量。数据量不大的情况下可以采用全文索引来做搜索,简单方便,但是数据量大的话还是建议用专门的搜索引擎 ElasticSearch 来做这件事。 以上就是基于 Mysql 实现一个简易版搜索引擎的详细内容,更多关于 Mysql 实现搜索引擎的资料请关注极客世界其它相关文章!希望大家以后多多支持极客世界! |
请发表评论