springboot整合Elasticsearch实现增删改查

平凡也就两个字: 懒和惰;
成功也就两个字: 苦和勤;
优秀也就两个字: 你和我。
跟着我从0学习JAVA、spring全家桶和linux运维等知识,带你从懵懂少年走向人生巅峰,迎娶白富美!
关注微信公众号【 IT特靠谱 】,每天都会分享技术心得~

springboot整合Elasticsearch实现增删改查

1 创建springboot项目

      创建的项目名称为:elasticsearch-demo

springboot整合Elasticsearch实现增删改查_第1张图片

      选择需要依赖的基础jar包。

springboot整合Elasticsearch实现增删改查_第2张图片

      创建成功后,项目结构如下图所示:

springboot整合Elasticsearch实现增删改查_第3张图片

2 添加springboot-elasticsearch依赖

    
    
      org.springframework.boot
      spring-boot-starter-data-elasticsearch
    

springboot整合Elasticsearch实现增删改查_第4张图片

3 调整springboot版本

3.1 为什么要调整springboot版本?

      由于之前的文章中,我们安装的是7.6.2版本的elasticsearch。而创建的springboot项目是2.4.0版本的,其默认依赖的是7.9.3版本的elasticsearch相关包。

      如果项目用到的es相关包版本与安装的es服务版本不一致,在实际使用es进行CRUD的时候就会出现一些版本导致的未知问题。因此,我们需要调整项目依赖的es版本或者调整springboot版本!

      恰好!springboot的2.3.0.RELEASE版本,默认依赖的就是7.6.2版本的es相关依赖包。那么我们调整springboot版本为2.3.0.RELEASE就达到目的了!

springboot整合Elasticsearch实现增删改查_第5张图片

springboot整合Elasticsearch实现增删改查_第6张图片

3.2 调整springboot版本

      将springboot版本调整为:2.3.0.RELEASE

springboot整合Elasticsearch实现增删改查_第7张图片

      自动下载完依赖后,查看依赖的es相关包版本:

springboot整合Elasticsearch实现增删改查_第8张图片

springboot整合Elasticsearch实现增删改查_第9张图片

      到此,项目组依赖的es相关包版本与es服务版本相同了!都为:7.6.2版本

4 编写代码

4.1 配置application.yml

#指定es服务访问url
spring:
  elasticsearch:
    rest:
      uris: http://localhost:9200

springboot整合Elasticsearch实现增删改查_第10张图片

4.2 创建实体类

      创建实体类:User.java

package com.test.elasticsearchdemo.entity;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * 用户实体类
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "pms", type = "_doc") //es注解1。指定es索引名和类型。es8版本中会废弃掉type类型(实际上默认的type为"_doc")。
public class User implements Serializable {

  /**
   * 数据id Id注解:指明pms索引_doc类型中的文档的id为数据的id。如果insert到es中的数据的id值为空,那么es会自动生成一个唯一的uuid作为文档id
   */
  @Id
  private Long id;

  /**
   * 用户名 Text:其取代了string,当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型。 设置text类型以后,字段内容会被分词,在生成倒排索引以前,字符串会被分词器分成一个个词项。text类型的字段不用于排序,很少用于聚合(termsAggregation除外)。
   * ik_max_word:指示了该字段使用到的分词算法,为:最细粒度分词
   */
  @Field(analyzer = "ik_max_word", type = FieldType.Text)
  private String name;

  /**
   * 用户密码 注意:password字段添加@Transient注解,也就意味着该字段不会被写入es中!
   */
  @Transient
  private String password;

  /**
   * 用户手机号 Keyword:关键词。该类型字段只能通过"精确查找"方式索引到,不会对该字段分词后与查询条件匹配
   */
  @Field(type = FieldType.Keyword)
  private String mobile;

  /**
   * 用户年龄 Integer:整数类型
   */
  @Field(type = FieldType.Integer)
  private Integer age;

  /**
   * 用户生日 Date:日期类型
   */
  @Field(type = FieldType.Date)
  private Date birthday;

  /**
   * 删除标识 Boolean:bool类型
   */
  @Field(type = FieldType.Boolean)
  private Boolean deleteStatus;

  /**
   * 用户标签 Nested:嵌套类型
   */
  @Field(type = FieldType.Nested)
  private List

4.3 自定义ElasticsearchRepository

      创建自定义es仓库接口:EsUserRepository.java,继承ElasticsearchRepository.java接口。

      ElasticsearchRepository及其父接口封装了一些常用的CRUD方法。因此我们只需要继承该接口,就可以进行简单的增删改查操作了。当然如果希望实现更复杂的查询操作,就需要搭配RestHighLevelClient客户端来使用!

package com.test.elasticsearchdemo.repository;

import com.test.elasticsearchdemo.entity.User;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * ES用户repository
 */
public interface EsUserRepository extends ElasticsearchRepository {

  /**
   * 根据名称查询
   */
  List findByName(String name);

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息
   */
  Page findByNameOrMobile(String name, String mobile, Pageable page);
}

4.4 创建service接口类

      创建service接口类:UserService.java

package com.test.elasticsearchdemo.service;

import com.test.elasticsearchdemo.dto.request.PageByNameOrMobileRequest;
import com.test.elasticsearchdemo.entity.User;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

/**
 * 用户service接口类
 */
public interface UserService {

  /**
   * 保存一条数据
   */
  void insert(User user);

  /**
   * 批量保存数据
   */
  void insertBatch(List users);

  /**
   * 更新一条数据
   */
  void update(User user);

  /**
   * 删除一条数据
   * @param id 删除数据文档id(文档id与数据id相同)
   */
  void deleteById(Long id);

  /**
   * 根据名称查询
   */
  List listByName(String name);

  /**
   * 根据id查询唯一数据
   */
  User findById(Long id);

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息
   */
  Page findByNameOrMobile(PageByNameOrMobileRequest request);

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息,并按age升序排序
   */
  Page pageByConditions(PageByNameOrMobileRequest request);
}

4.5 创建service接口实现类

      创建service接口实现类:UserServiceImpl.java

package com.test.elasticsearchdemo.service.impl;

import com.test.elasticsearchdemo.dto.request.PageByNameOrMobileRequest;
import com.test.elasticsearchdemo.entity.User;
import com.test.elasticsearchdemo.repository.EsUserRepository;
import com.test.elasticsearchdemo.service.UserService;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * 用户接口实现类
 */
@Service
public class UserServiceImpl implements UserService {

  /**
   * 一般CRUD查询用这个!spring-data风格
   */
  @Autowired
  private EsUserRepository esUserRepository;

  /**
   * es复杂操作用这个!底层用的是RestHighLevelClient客户端
   */
  @Autowired
  private ElasticsearchRestTemplate elasticsearchRestTemplate;

  /***********************EsUserRepository新增、更新和删除***********************/
  /**
   * 新增一条数据
   */
  @Override
  public void insert(User user) {
    esUserRepository.save(user);
  }

  /**
   * 批量保存数据
   */
  @Override
  public void insertBatch(List users) {
    esUserRepository.saveAll(users);
  }

  /**
   * 更新一条数据 说明:如果es数据库中存在相同id的数据,那么就是更新数据!否则就是新增数据。
   */
  @Override
  public void update(User user) {
    esUserRepository.save(user);
  }

  /**
   * 删除一条数据
   *
   * @param id 删除数据文档id(文档id与数据id相同)
   */
  @Override
  public void deleteById(Long id) {
    esUserRepository.deleteById(id);
  }

  /***********************EsUserRepository普通查询***********************/
  /**
   * 根据名称查询
   */
  @Override
  public List listByName(String name) {
    return esUserRepository.findByName(name);
  }

  /**
   * 根据id查询唯一数据
   */
  @Override
  public User findById(Long id) {
    Optional optional = esUserRepository.findById(id);
    return optional.orElse(null);
  }

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息
   */
  @Override
  public Page findByNameOrMobile(PageByNameOrMobileRequest request) {
    Pageable pageable = PageRequest.of(request.getPage()-1, request.getSize());
    return esUserRepository.findByNameOrMobile(request.getName(), request.getMobile(), pageable);
  }

  /***********************RestHighLevelClient高级查询***********************/
  @Override
  public Page pageByConditions(PageByNameOrMobileRequest request) {
    //构建查询条件
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    //1.排序
    nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("age").order(SortOrder.ASC));
    //2.分页
    Pageable pageable = PageRequest.of(request.getPage() - 1, request.getSize());
    nativeSearchQueryBuilder.withPageable(pageable);
    //3.过滤
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.must(QueryBuilders.termQuery("deleteStatus", false));
    nativeSearchQueryBuilder.withFilter(boolQueryBuilder);
    //4.搜索条件
    if (StringUtils.isEmpty(request.getMobile()) && StringUtils.isEmpty(request.getName())) {
      nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
    } else {
      List filterFunctionBuilders = new ArrayList<>();
      if (!StringUtils.isEmpty(request.getMobile())) {
        filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("mobile", request.getMobile()),
            ScoreFunctionBuilders.weightFactorFunction(10)));
      }
      if (!StringUtils.isEmpty(request.getName())) {
        filterFunctionBuilders.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("name", request.getName()),
            ScoreFunctionBuilders.weightFactorFunction(7)));
      }
      FunctionScoreQueryBuilder.FilterFunctionBuilder[] builders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilders.size()];
      filterFunctionBuilders.toArray(builders);
      FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(builders)
          .scoreMode(FunctionScoreQuery.ScoreMode.SUM)
          .setMinScore(3);
      nativeSearchQueryBuilder.withQuery(functionScoreQueryBuilder);
    }
    NativeSearchQuery query = nativeSearchQueryBuilder.build();
    SearchHits searchHits = elasticsearchRestTemplate.search(query, User.class);
    if (searchHits.getTotalHits() <= 0) {
      return new PageImpl<>(null, pageable, 0);
    }
    List userList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
    return new PageImpl<>(userList, pageable, searchHits.getTotalHits());
  }
}

4.6 创建controller控制器类

      创建控制器类:UserController.java

package com.test.elasticsearchdemo.controller;

import com.test.elasticsearchdemo.dto.request.PageByNameOrMobileRequest;
import com.test.elasticsearchdemo.entity.User;
import com.test.elasticsearchdemo.service.UserService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 用户api接口控制器
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {

  @Autowired
  private UserService userService;

  /***********************EsUserRepository新增、更新和删除***********************/
  /**
   * 保存一条数据
   */
  @PostMapping("insert")
  public void insert(@RequestBody User user) {
    userService.insert(user);
  }

  /**
   * 批量保存数据
   */
  @PostMapping("insertBatch")
  public void insertBatch(@RequestBody List users) {
    userService.insertBatch(users);
  }

  /**
   * 更新一条数据
   */
  @PostMapping("update")
  public void update(@RequestBody User user) {
    userService.update(user);
  }

  /**
   * 删除一条数据
   */
  @GetMapping("deleteById")
  public void deleteById(Long id) {
    userService.deleteById(id);
  }

  /***********************EsUserRepository普通查询***********************/
  /**
   * 根据名称查询
   */
  @GetMapping("listByName")
  public List listByName(String name) {
    return userService.listByName(name);
  }

  /**
   * 根据id查询唯一数据
   */
  @GetMapping("findById")
  public User findById(Long id) {
    return userService.findById(id);
  }

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息
   */
  @PostMapping("findPageByNameOrMobile")
  public Page findPageByNameOrMobile(@RequestBody PageByNameOrMobileRequest request) {
    return userService.findByNameOrMobile(request);
  }

  /***********************highLevelClient高级查询***********************/
  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息,并按age升序排序
   */
  @PostMapping("pageByConditions")
  public Page pageByConditions(@RequestBody PageByNameOrMobileRequest request) {
    return userService.pageByConditions(request);
  }
}

      到此,springboot整合Elasticsearch,并实现了基于repository和restHighLevel两种方式实现了数据的CRUD。

    (1) 商务合作微信号:M9392W

    (2) 购物商城: 扫码即可进入博主开发的小程序购物商城,享超大优惠购物,支持一下博主吧~

springboot整合Elasticsearch实现增删改查_第11张图片

    (3) 博主微信公众号IT特靠谱,学习更多开发实战技巧!

你可能感兴趣的:(elasticsearch,springboot,elasticsearch,spring,boot)