springboot整合Elasticsearch实现增删改查

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

springboot整合Elasticsearch实现增删改查

1 创建springboot项目

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

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

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

2 添加springboot-elasticsearch依赖

    <!--添加springboot-elasticsearch依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>

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就达到目的了!

3.2 调整springboot版本

      将springboot版本调整为:2.3.0.RELEASE

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

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

4 编写代码

4.1 配置application.yml

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

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<Label> labels;

  @Data
  @Builder
  @AllArgsConstructor
  @NoArgsConstructor
  public static class Label implements Serializable {

    /**
     * 标签id
     */
    @Field(type = FieldType.Long)
    private Long id;

    /**
     * 标签编码
     */
    @Field(type = FieldType.Keyword)
    private String labelCode;

    /**
     * 标签名称
     */
    @Field(type = FieldType.Keyword)
    private String labelName;

    /**
     * 标签名称 注意:该字段不会被写入es中!
     */
    @Transient
    private String labelDesc;
  }
}

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<User, Long> {

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

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息
   */
  Page<User> 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<User> users);

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

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

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

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

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

  /**
   * 分页搜索查询:分页查询名称或手机号相同的信息,并按age升序排序
   */
  Page<User> 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<User> 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<User> listByName(String name) {
    return esUserRepository.findByName(name);
  }

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

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

  /***********************RestHighLevelClient高级查询***********************/
  @Override
  public Page<User> 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<FunctionScoreQueryBuilder.FilterFunctionBuilder> 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<User> searchHits = elasticsearchRestTemplate.search(query, User.class);
    if (searchHits.getTotalHits() <= 0) {
      return new PageImpl<>(null, pageable, 0);
    }
    List<User> 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<User> 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<User> listByName(String name) {
    return userService.listByName(name);
  }

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

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

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

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

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

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

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

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
你可以按照以下步骤使用 Spring BootElasticsearch 实现增删改查的功能: 1. 添加依赖:在你的 Spring Boot 项目的 pom.xml 文件中,添加 Elasticsearch 相关的依赖。例如: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 2. 配置 Elasticsearch:在你的 application.properties 或 application.yml 文件中,配置 Elasticsearch 的连接信息。例如: ```yaml spring.data.elasticsearch.cluster-nodes=localhost:9200 ``` 3. 创建实体类:创建一个代表你要操作的数据的实体类,并使用注解来映射到 Elasticsearch 中的索引和类型。例如: ```java import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @Document(indexName = "your_index_name", type = "your_type_name") public class YourEntity { @Id private String id; private String name; // 其他属性和方法 } ``` 4. 创建数据访问接口:创建一个继承自 ElasticsearchRepository 的数据访问接口,该接口提供了一些基本的 CRUD 方法。例如: ```java import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface YourEntityRepository extends ElasticsearchRepository<YourEntity, String> { // 可以根据需要添加自定义的查询方法 } ``` 5. 编写业务逻辑:在你的服务类中使用 YourEntityRepository 来进行相关的数据操作。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class YourService { @Autowired private YourEntityRepository repository; public YourEntity save(YourEntity entity) { return repository.save(entity); } public void delete(String id) { repository.deleteById(id); } public Iterable<YourEntity> findAll() { return repository.findAll(); } // 可以根据需要添加其他的查询方法和业务逻辑 } ``` 这样,你就可以通过调用 YourService 中的方法来实现Elasticsearch增删改查操作了。希望对你有帮助!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT_Most

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值