背景介绍
最近在给博客做SEO,顺便也学学怎么与搜索引擎打交道
发现自己站内没有一个像样的搜索功能
于是全文搜索便是第一步
给博客文章添加全文搜索,摸索着尝试了3种方案
可以根据具体项目选择
数据库:Mysql
1.SQL Like 查询 初级方案
使用
作为最简单的方式,直接使用like条件在ttitle
和content
中查询
select *
from blog
where `title` like '%key_word%' or `content` like '%key_word%'
优势
1.简单 2.简单 3.简单
劣势
1.效率低下,查询走全表,数据量过大时无法获得正常体验 2.关键词必须完全匹配,用户使用无法找到准确关键词
2.Mysql 全文索引
介绍
使用mysql的Full text
全文索引,配合ngram
全文解析器进行模糊搜索
全文索引
目前搜索引擎使用的一种关键技术。
它能够利用分词技术
等多种算法智能分析出文本文字中关键字词的频率及重要性,
然后按照一定的算法规则智能地筛选出我们想要的搜索结果。 mysql 5.6版本之后InnoDB存储引擎开始支持全文索引
MySQL允许在char、varchar、text类型上建立全文索引
ngram Parser
对中文友好的分词器,可将词语进行分词处理
Mysql 通过分词结果进行全文索引基础
比如词语"博客网站",将会被拆解为
n=1: '博', '客', '网', '站'
n=2: '博客', '客网', '网站'
n=3: '博客网', '客网站'
n=4: '博客网站'
使用
1.创建表 `blog
DROP TABLE IF EXISTS `blog`;
CREATE TABLE `blog` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`content` text,
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8;
2.创建在需要搜索的字段 title
和 content
创建全文索引(使用ngram parser
)
ALTER TABLE `blog` ADD FULLTEXT INDEX index_name(`title`,`content`) WITH PARSER ngram;
或
CREATE FULLTEXT INDEX index_name ON `blog` (`title`,`content`) WITH PARSER ngram;
#也可以添加配置分词的数量,默认值1
[mysqld]
ngram_token_size=2
3.进行全文检索
select * from `table_name` where MATCH(col1,col2,…) AGAINST (expr[search_modifier])
eg. select * from `blog` where MATCH(`title`,`content`) AGAINST ('博客搜索' IN NATURAL LANGUAGE MODE)
MATCH(col1,col2,…) AGAINST (expr[search_modifier])。
其中MATCH中的内容为已建立FULLTEXT索引并要从中查找数据的列,
AGAINST中的expr为要查找的文本内容,search_modifier为可选搜索类型。
search_modifier
的可选值
search_modifier:
{
IN NATURAL LANGUAGE MODE
| IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
| IN BOOLEAN MODE
| WITH QUERY EXPANSION
}
更多信息请查看 Mysql Full-Text Search Functions
优势
1.精准度很高,能达到LIKE '%...%
的效果,并且能对词语进行分词,进行自然语言查询
2.查询速度比LIKE '%...%
搜索快3~50倍(大约)
劣势
1.索引文件会占用更多空间 2.仍然无法支撑海量数据
Elasticsearch 引擎 ^高级^
使用 with Springboot
1.添加Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.配置application.yml
sprin:
data:
elasticsearch:
cluster-name: esName #es库名称
cluster-nodes: localhost:9300 #es服务器地址:端口
repositories:
enabled: true #启用es Repositories
3.创建实体类
Blog.java
//indexName 相当于表名,
@Document(indexName = "blog", type = "_blog")
public class Blog {
//ID是必须的注解
@Id
private Long id;
private String title;
private String content;
//省略 setter getter
4.创建Repository接口
BlogRepository.java
public interface BlogRepository extends ElasticsearchRepository<BlogModel, String> {}
5.对Blog 进行CRUD
BlogController.java
@RestController
@RequestMapping("/blog")
public class BlogController {
@Autowired
private BlogRepository blogRepository;
/** 增加 */
@PostMapping("/add")
public String add(@RequestBody BlogModel blogModel) {
blogRepository.save(blogModel);
return "success";
}
/** 通过关键词查询,返回结果为全文模糊查询 */
@GetMapping("/search/{keyWord}")
public String getById(@PathVariable String keyWord) {
if (id == null){
return "error";
}
List<Blog> blogs = blogRepository.findAllByContent(keyWord);
return blogs.toString();
}
// 删除,修改同JPA Mysql 操作
}
6.使用Chrome插件对Elasticsearch进行查看
优势
1.通过JPA 操作接近简单和MySql一样
2.能够处理海量数据
劣势
1.需要额外管理一个elasticsearch库 2.不适用于存取频繁场景