ElasticsearchRestTemplate 和ElasticsearchRepository 的使用

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: ElasticsearchRestTemplate 和ElasticsearchRepository 的使用

操作ElasticSearch的数据,有两种方式一种是 ElasticsearchRepository 接口,另一种是ElasticsearchTemplate接口。SpringData对ES的封装ElasticsearchRestTemplate类,可直接使用,此类在ElasticsearchRestTemplate基础上进行性一定程度的封装,使用起来更方便灵活,拓展性更强。ElasticsearchRepository可以被继承操作ES,是SpringBoot对ES的高度封装,操作最为方便,但牺牲了灵活性。

Spring boot 和Elasticsearch版本关系:

一、使用ElasticsearchRestTemplate类

1.引用Maven类库

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

2. 配置文件application.yml

spring:
  elasticsearch:
    rest:
      uris: http://192.168.10.202:9200
      connection-timeout: 1s
      read-timeout: 1m
      username: elastic
      password: elastic

注意,如果es资源没有开启x-pack安全插件的话,可以不加username和password(因为默认是没有的)。

3.创建实体类(用于JSON文档对象的转换)

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
 * @author Sinbad
 * @description: 测试ES对象<br />
 * @date 2022/8/26 17:12
 */
@Document(indexName = "mysql-test")
@Data
public class TestEsEntity {
    @Id  
    Long id;
    @Field(type = FieldType.Text, name = "addr")
    String addr;
    @Field(type = FieldType.Text, name = "name")
    String name;
    @Field(type = FieldType.Date, name = "birthday", pattern = "yyyy-MM-dd")
    LocalDate birthday;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",locale = "zh_CN")
    @Field(type = FieldType.Date, name = "create_time", pattern = "yyyy-MM-dd HH:mm:ss",format =DateFormat.custom )
    LocalDateTime createTime;
}

@Document注解:表示对应一个索引名相关的文档

@Data注解:lombok的,为类提供读写属性, 此外还提供了 equals()、hashCode()、toString() 方法

@Id 注解:表示文档的ID字段

@Field注解:文档字段的注解,对于日期含时间的字段,要写patten和format,不然会无法更新文档对象

@JsonFormat注解:将文档转换成JSON返回给前端时用到

注意日期类型字段不要用java.util.Date类型,要用java.time.LocalDate或java.time.LocalDateTime类型。

测试实例:

import com.hkyctech.commons.base.entity.JsonResult;
import com.hkyctech.tu.core.vo.TestEsEntity ;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Slf4j
@Service
public class ElasticSearchServiceImpl {
    @Resource
    ElasticsearchRestTemplate elasticsearchTemplate; //直接注入就可以用了
    /***
     * @description 查询全部数据
     */
    public Object testSearchAll(){
        Query query=elasticsearchTemplate.matchAllQuery();
        return elasticsearchTemplate.search(query, TestEsEntity .class);
    }
    /***
    * @description  精确查询地址字段
    * @param keyword 搜索关键字
    */
    public Object testSearchAddr(String keyword) {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                //查询条件
                .withQuery(QueryBuilders.queryStringQuery(keyword).defaultField("addr"))
                //分页
                .withPageable(PageRequest.of(0, 10))
                //高亮字段显示
                .withHighlightFields(new HighlightBuilder.Field(keyword))
                .build();
        return elasticsearchTemplate.search(nativeSearchQuery, TestEsEntity .class);
    }
    /***
    * @description 组合查询,查询关键词不分词,关系and
    */
    public Object testComboSearchAnd(){
        BoolQueryBuilder esQuery=QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("addr", "深圳"))
                .must(QueryBuilders.termQuery("addr", "广东"));
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                //查询条件
                .withQuery(esQuery)
                //分页
                .withPageable(PageRequest.of(0, 10))
                .build();
        return elasticsearchTemplate.search(nativeSearchQuery, TestEsEntity .class);
    }
    /***
     * @description 组合查询,查询关键词不分词,关系or
     */
    public Object testComboSearchOr(){
        BoolQueryBuilder esQuery=QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("addr", "深圳"))
                .should(QueryBuilders.termQuery("addr", "广东"));
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                //查询条件
                .withQuery(esQuery)
                //分页
                .withPageable(PageRequest.of(0, 10))
                .build();
        return elasticsearchTemplate.search(nativeSearchQuery, TestEsEntity .class);
    }
    /***
    * @description  索引或更新文档
    * @param vo 文档对象
    */
    public JsonResult testPutDocument(TestEsEntity  vo){
        try {
            Object data = elasticsearchTemplate.save(vo);
            return JsonResult.getSuccessResult(data,"更新成功");
        }catch (Exception e){
            // 看http请求响应日志其实操作成功了,但是会报解析出错,可能是spring的bug,这里拦截一下
            String message=e.getMessage();
            if(message.indexOf("response=HTTP/1.1 200 OK")>0 || message.indexOf("response=HTTP/1.1 201 Created")>0){
                return JsonResult.getSuccessResult("更新成功");
            }
            return JsonResult.getFailResult(e.getStackTrace(),e.getMessage());
        }
    }
    /***
    * @description  删除文档
    * @param id 文档ID
    */
    public JsonResult deleteDocument(String id){
        try {
            elasticsearchTemplate.delete(id, TestEsEntity .class);
            return JsonResult.getSuccessResult("删除成功");
        }catch (Exception e){
            String message=e.getMessage();
            // 看http请求响应日志其实操作成功了,但是会报解析出错,可能是spring的bug,这里拦截一下
            if(message.indexOf("response=HTTP/1.1 200 OK")>0 ){
                return JsonResult.getSuccessResult("删除成功");
            }
            return JsonResult.getFailResult(e.getStackTrace(),e.getMessage());
        }
    }
}

二、使用ElasticsearchRepository 类

1.引用Maven类库

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

2. 配置文件application.yml

spring:
  elasticsearch:
    rest:
      uris: http://192.168.10.202:9200
      connection-timeout: 1s
      read-timeout: 1m
      username: elastic
      password: elastic

3. ElasticsearchRepository接口的源码

package org.springframework.data.elasticsearch.repository;
import java.io.Serializable;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.repository.NoRepositoryBean;
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {
  <S extends T> S index(S entity);
  Iterable<T> search(QueryBuilder query);
  Page<T> search(QueryBuilder query, Pageable pageable);
  Page<T> search(SearchQuery searchQuery);
  Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);
  void refresh();
  Class<T> getEntityClass();
}

4.CrudRepository 源码

package org.springframework.data.repository;
import java.util.Optional;
/**
 * Interface for generic CRUD operations on a repository for a specific type.
 *
 * @author Oliver Gierke
 * @author Eberhard Wolff
 */
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
  /**
   * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
   * entity instance completely.
   *
   * @param entity must not be {@literal null}.
   * @return the saved entity will never be {@literal null}.
   */
  <S extends T> S save(S entity);
  /**
   * Saves all given entities.
   *
   * @param entities must not be {@literal null}.
   * @return the saved entities will never be {@literal null}.
   * @throws IllegalArgumentException in case the given entity is {@literal null}.
   */
  <S extends T> Iterable<S> saveAll(Iterable<S> entities);
  /**
   * Retrieves an entity by its id.
   *
   * @param id must not be {@literal null}.
   * @return the entity with the given id or {@literal Optional#empty()} if none found
   * @throws IllegalArgumentException if {@code id} is {@literal null}.
   */
  Optional<T> findById(ID id);
  /**
   * Returns whether an entity with the given id exists.
   *
   * @param id must not be {@literal null}.
   * @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
   * @throws IllegalArgumentException if {@code id} is {@literal null}.
   */
  boolean existsById(ID id);
  /**
   * Returns all instances of the type.
   *
   * @return all entities
   */
  Iterable<T> findAll();
  /**
   * Returns all instances of the type with the given IDs.
   *
   * @param ids
   * @return
   */
  Iterable<T> findAllById(Iterable<ID> ids);
  /**
   * Returns the number of entities available.
   *
   * @return the number of entities
   */
  long count();
  /**
   * Deletes the entity with the given id.
   *
   * @param id must not be {@literal null}.
   * @throws IllegalArgumentException in case the given {@code id} is {@literal null}
   */
  void deleteById(ID id);
  /**
   * Deletes a given entity.
   *
   * @param entity
   * @throws IllegalArgumentException in case the given entity is {@literal null}.
   */
  void delete(T entity);
  /**
   * Deletes the given entities.
   *
   * @param entities
   * @throws IllegalArgumentException in case the given {@link Iterable} is {@literal null}.
   */
  void deleteAll(Iterable<? extends T> entities);
  /**
   * Deletes all entities managed by the repository.
   */
  void deleteAll();
}

5.查询查找策略

5.1存储库方法可以定义为具有以下返回类型,用于返回多个元素:

  • List<T>
  • Stream<T>
  • SearchHits<T>
  • List<SearchHit<T>>
  • Stream<SearchHit<T>>
  • SearchPage<T>

5.2 使用@Query注解

使用@query注释对方法声明query。

interface BookRepository extends ElasticsearchRepository<Book, String> {
    @Query("{\"match\": {\"name\": {\"query\": \"?0\"}}}")
    Page<Book> findByName(String name,Pageable pageable);
}

设置为注释参数的字符串必须是有效的 Elasticsearch JSON 查询。 它将作为查询元素的值发送到Easticsearch;例如,如果使用参数 John 调用函数,它将生成以下查询正文:

{
  "query": {
    "match": {
      "name": {
        "query": "John"
      }
    }
  }
}

对@Query采用集合参数的方法进行注释

@Query("{\"ids\": {\"values\": ?0 }}")
List<SampleEntity> getByIds(Collection<String> ids);

将进行ID查询以返回所有匹配的文档。因此,调用List为[“id1”、“id2”、“id3”]的方法将生成查询主体

{
  "query": {
    "ids": {
      "values": ["id1", "id2", "id3"]
    }
  }
}

6.开发实例:

public interface LogRepository extends ElasticsearchRepository<Log, String> {
    /**
     * 定义一个方法查询:根据title查询es
     *
     * 原因:  ElasticsearchRepository会分析方法名,参数对应es中的field(这就是灵活之处)
     * @param title
     */
    List<Log> findBySummary(String summary);
    List<Log> findByTitle(String title);
  /**
     * 定义一个方法查询: 根据title,content查询es
     */
    List<Log> findByTitleAndContent(String title, String content);
}
@PostMapping("save")
    public void save(@Validated @RequestBody Log req){
        Log dto = new Log();
        dto.setTitle(req.getTitle());
        dto.setSummary(req.getSummary());
        dto.setContent(req.getContent());
        dto.setCreateTime(new Date());
        dto.setId(req.getId());      
        LogRepository.save(dto);
        return ;
        } 
    @PostMapping("testTitle")
    public void testSearchTitle(@Validated @RequestBody Log req){
        List<Log> searchResult = logRepository.findByTitle(req.getMobileType());
        Iterator<Log> iterator = searchResult.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("sa");
        return;
    }

官网:Spring Data Elasticsearch - Reference Documentation


📢文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群💪💪💪

📢创作不易,如果觉得文章不错,可以点赞👍收藏📁评论📒

📢你的支持和鼓励是我创作的动力❗❗❗

大家好,欢迎来到Doker品牌,我们专注3C产品。欢迎点赞和评论,您的鼓励是我们持续更新的动力!需要完整资料欢迎加微信进入技术群聊,请前往官网:

Doker 多克

官方旗舰店

Doker多克官方旗舰店

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
存储 JSON 网络协议
ElasticsearchRestTemplate客户端使用
ElasticsearchRestTemplate客户端使用
|
9月前
|
搜索推荐 Java 索引
Spring Boot中的ElasticsearchRepository
Spring Boot中的ElasticsearchRepository
|
存储 Java 索引
Elastic实战:彻底解决spring-data-elasticsearch日期、时间类型数据读取报错问题
在使用spring-data-elasticsearch读取es中时间类型的数据时出现了日期转换报错,不少初学者会在这里困惑很久,所以今天我们专门来解读该问题的几种解决方案。
1661 0
Elastic实战:彻底解决spring-data-elasticsearch日期、时间类型数据读取报错问题
|
算法 Java 机器人
手把手教你提交Jar包到Maven公共仓库
在上一篇文章中,我介绍了自己的SpringBoot Starter项目,可以让我们使用注解的方式轻松地获取操作日志,并推送到指定数据源。 之前,我的项目开源在Github上,大家想要用我的项目,还得把Github仓库配置到Maven的Setting.xml里,一点也不方便。 本文,就整理一下我把项目上传到公共Maven仓库的过程,当做一篇教程文章。
2133 0
|
IDE Java 程序员
IDEA创建maven项目过慢,一直卡在resolving dependencies...的解决办法
作为一个从事 Java 开发的程序员,每天离不开ide的帮助。一开始学习java的时候基本都是使用eclipse进行开发, 后来接触了idea,发现是真的香,比eclipse好用太多了,能够大大提升开发的效率。
3387 0
IDEA创建maven项目过慢,一直卡在resolving dependencies...的解决办法
|
1月前
|
存储 Java Maven
SpringBoot整合Jest和Elasticsearch实践
SpringBoot整合Jest和Elasticsearch实践
129 1
完美解决Non-terminating decimal expansion; no exact representable decimal result.异常
完美解决Non-terminating decimal expansion; no exact representable decimal result.异常
18433 0
完美解决Non-terminating decimal expansion; no exact representable decimal result.异常
|
1月前
|
Java API Maven
springboot 、spring-data-elasticsearch、elasticserach的版本对应关系
springboot 、spring-data-elasticsearch、elasticserach的版本对应关系
502 0
|
安全 Java 网络架构
解决SpringBoot ElasticSearch6.x升级7.x产生的问题
解决SpringBoot ElasticSearch6.x升级7.x产生的问题
654 0
|
存储 设计模式 负载均衡
Spring Cloud openFeign学习【3.0.2版本】
Feign是一个声明性web服务客户端。它使编写web服务客户机更加容易,要使用Feign,需要创建一个接口并对其进行注释。它具有可插入注释支持,包括Feign注释和JAX-RS注释。
394 0