Hoody's Blog
博客文章通过3种方式添加全文模糊搜索

背景介绍

最近在给博客做SEO,顺便也学学怎么与搜索引擎打交道
发现自己站内没有一个像样的搜索功能
于是全文搜索便是第一步

给博客文章添加全文搜索,摸索着尝试了3种方案
可以根据具体项目选择 数据库:Mysql

1.SQL Like 查询 初级方案

使用

作为最简单的方式,直接使用like条件在ttitlecontent中查询

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.创建在需要搜索的字段 titlecontent创建全文索引(使用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

参考 Spring Data Elasticsearch

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进行查看

ElasticSearch Head on Chrome

ElasticSearch Head on Chrome.jpg

优势

1.通过JPA 操作接近简单和MySql一样
2.能够处理海量数据

劣势

1.需要额外管理一个elasticsearch库 2.不适用于存取频繁场景

添加新评论,支持Markdown格式