Elasticsearch

Elasticsearch 简介

  • 一个分布式的、Restful 风格的搜索引擎
  • 支持对各种类型的数据的检索
  • 搜索速度快,可以提供实时的搜索服务
  • 便于水平扩展,每秒可以处理 PB 级海量数据

Elasticsearch 术语

  • 索引、类型、文档、字段
  • 集群、节点、分片、副本

索引可以理解为一个数据库

类型为一张表

文档为一条数据,通常为 JSON 结果

字段为表中的列

在 ES6 以后,逐渐废弃上面的类型,ES7(本文使用)彻底废除,由索引逐渐代替其功能

Elasticsearch 和 SpringBoot 是有版本对应的,点击查看

下载Elasticsearch,在使用 ES 之前,还需要装一个ik 分词器,下载好之后,将其解压至 ES 的 plugins 文件夹中的 ik 文件夹(无则创建)

在使用 ES 之前,我们最好简单更改一下其配置,在 config 目录下,找到 elasticsearch.yml,进行如下更改

# 集群的名字 随意
cluster.name: nowcoder
# ES数据存储路径
path.data: /home/gas/桌面/elasticsearch-7.12.0/data
# 日志
path.logs: /home/gas/桌面/elasticsearch-7.12.0/logs

然后执行 bin 目录下的 elasticsearch 文件即可

SpringBoot 使用 Elasticsearch

1. Maven 引入

<!-- elasticsearch -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2. yml 配置

spring:
  elasticsearch:
    rest:
      username: nowcoder #   填写上面自己配置的
      uris: 127.0.0.1:9200 #   es的ip:port

3. 配置 ES 实体类

直接用现有的实体类就好,并不冲突

//indexName:索引的名称
//shards:分片
//replicas:副本
//type:7.x不用写
@Document(indexName = "discusspost", shards = 6, replicas = 3)
public class DiscussPost {

    //声明ID
    @Id
    private int id;

    //声明类型
    @Field(type = FieldType.Integer)
    private int userId;

    //后面两个是使用的分词器的名字,没什么必要无须更改,前面是存储数据时使用的解析器(存储时尽可能拆分出更多的词语进行存储),后面是搜索时使用的解析器(搜索时无须过分分词)
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String title;

    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
    private String content;

    //name:字段在es中的名称
    @Field(name = "type",type = FieldType.Integer)
    private int type;
    @Field(type = FieldType.Integer)
    private int status;
    @Field(name = "createTime",type = FieldType.Date)
    private Date createTime;
    @Field(type = FieldType.Integer)
    private int commentCount;
    @Field(name = "score",positiveScoreImpact = false,type = FieldType.Double)
    private double score;
}

4. 创建一个操作 ES 的类

@Repository                                                         //<处理的对象,对象的主键类型>
public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost,Integer> {
    //高亮
    @Highlight(
            fields = {
                    @HighlightField(name = "title"),
                    @HighlightField(name = "content")
            },parameters = @HighlightParameters(
                    preTags = "<em>",
                    postTags = "</em>"
    ))
    //Pageable包含了排序功能,如果你只需要排序,则替换成Sort sort即可,注意:Pageable和Sort不能同时存在
    List<SearchHit<DiscussPost>> findDiscussPostByTitleLikeOrContentLike(String title,String content,Pageable pageable);
    //注意,方法的名称findDiscussPostByTitleLikeOrContentLike可不是乱写的,是用含义的,底层会根据方法名称去构建搜索语句
    //当然,也可以用@Query注解自定义搜索语句,下面是官方文档的声明
    //https://docs.spring.io/spring-data/elasticsearch/docs/4.1.8/reference/html/#elasticsearch.query-methods
}

5. 实际操作演示

@Autowired
private DiscussPostRepository discussPostRepository;

//保存数据,这里是从数据库中读取了一条DiscussPost类型的数据存入es中
discussPostRepository.save(discussPostMapper.selectDiscussPostById(230));
//批量存储
discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(101, 0, 100,0));
//更新数据
DiscussPost discussPost = discussPostMapper.selectDiscussPostById(231);
discussPost.setContent("我是新人,使劲灌水");
discussPostRepository.save(discussPost);
//根据ID删除
discussPostRepository.deleteById(231);
//删除所有
discussPostRepository.deleteAll();

//搜索
public void Select(){
    Sort sort = Sort.by("score").descending()
        .and(Sort.by("type").descending())
        .and(Sort.by("createTime").descending());

    List<SearchHit<DiscussPost>> post = discussPostRepository
        														//分页数据第1页,10条数据,排序
        .findDiscussPostByTitleLikeOrContentLike("压力数据", "压力",PageRequest.of(1,10,sort));

    post.forEach(res-> {
        System.out.println("查询结果:" + res);
    });
}

参考:

官方文档:https://docs.spring.io/spring-data/elasticsearch/docs/4.1.8/reference/html/#repositories

文章:https://zhuanlan.zhihu.com/p/321248369