Spring data elasticsearch使用方法详解

 更新时间:2020年01月29日 11:32:25   作者:bofeng  
这篇文章主要介绍了Spring data elasticsearch使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了Spring data elasticsearch使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一、准备

1.添加依赖

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

2.application.yml

spring:
 application:
  name: search-service
 data:
  elasticsearch:
   cluster-name: elasticsearch
   cluster-nodes: 192.168.25.129:9300

3.实体类

@Data
@Document(indexName = "goods", type = "_doc", shards = 1, replicas = 0)
public class Goods {
  @Idprivate Long id;
  @Field(type = FieldType.text, analyzer = "ik_max_word")
  private String all;
  @Field(type = FieldType.keyword, index = false)
  private String subTitle;private Long brandId;private Long cid1;private Long cid2;private Long cid3;private Date createTime;private List<Long> price;
  @Field(type = FieldType.keyword, index = false)
  private String skus;private Map<String, Object> specs;
}

@Document 作用在类,标记实体类为文档对象,一般有两个属性

  • indexName:对应索引库名称
  • type:对应在索引库中的类型
  • shards:分片数量,默认5
  • replicas:副本数量,默认1
  • @Id 作用在成员变量,标记一个字段作为id主键
  • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
  • type:字段类型,取值是枚举:FieldType
  • index:是否索引,布尔类型,默认是true
  • store:是否存储,布尔类型,默认是false
  • analyzer:分词器名称

二.、索引操作

首先注入ElasticsearchTemplate

@Resource
private ElasticsearchTemplate elasticsearchTemplate;

● 创建索引

elasticsearchTemplate.createIndex(Goods.class);

● 配置映射

elasticsearchTemplate.putMapping(Goods.class);

● 删除索引

//根据类
elasticsearchTemplate.deleteIndex(Goods.class);
//根据索引名
elasticsearchTemplate.deleteIndex("goods");

三、文档操作

1.定义接口。也是SpringData风格

public interface ItemRepository extends ElasticsearchRepository<Item,Long> {
}

2.注入

@Autowired
private ItemRepository itemRepository;

● 新增文档

Item item = new Item(1L, "小米手机7", " 手机",
             "小米", 3499.00, "http://image.leyou.com/13123.jpg");
itemRepository.save(item);

● 批量新增

  List<Item> list = new ArrayList<>();
  list.add(new Item(2L, "坚果手机R1", " 手机", "锤子", 3699.00, "http://image.leyou.com/123.jpg"));
  list.add(new Item(3L, "华为META10", " 手机", "华为", 4499.00, "http://image.leyou.com/3.jpg"));
  // 接收对象集合,实现批量新增
  itemRepository.saveAll(list);

四、 基本搜索

● 基本查询。

例:

  // 查询全部,并安装价格降序排序
  Iterable<Item> items = this.itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
  items.forEach(item-> System.out.println(item));

● 自定义查询

Keyword Sample Elasticsearch Query String
And findByNameAndPrice {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Or findByNameOrPrice {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Is findByName {"bool" : {"must" : {"field" : {"name" : "?"}}}}
Not findByNameNot {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
Between findByPriceBetween {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqual findByPriceLessThan {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqual findByPriceGreaterThan {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Before findByPriceBefore {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
After findByPriceAfter {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Like findByNameLike {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWith findByNameStartingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWith findByNameEndingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/Containing findByNameContaining {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
In findByNameIn(Collection<String>names) {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotIn findByNameNotIn(Collection<String>names) {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
Near findByStoreNear Not Supported Yet !
True findByAvailableTrue {"bool" : {"must" : {"field" : {"available" : true}}}}
False findByAvailableFalse {"bool" : {"must" : {"field" : {"available" : false}}}}
OrderBy findByAvailableTrueOrderByNameDesc {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

例:

public interface ItemRepository extends ElasticsearchRepository<Item,Long> {

  /**
   * 根据价格区间查询
   * @param price1
   * @param price2
   * @return
   */
  List<Item> findByPriceBetween(double price1, double price2);
}

五、高级查询

● 词条查询

    MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("all", "小米");
    // 执行查询
    Iterable<Goods> goods = this.goodsRepository.search(queryBuilder);

● 自定义查询

// 构建查询条件
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 添加基本的分词查询
    queryBuilder.withQuery(QueryBuilders.matchQuery("all", "小米"));
    // 执行搜索,获取结果
    Page<Goods> goods = this.goodsRepository.search(queryBuilder.build());
    // 打印总条数
    System.out.println(goods.getTotalElements());
    // 打印总页数
    System.out.println(goods.getTotalPages());

● 分页查询

// 构建查询条件
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 添加基本的分词查询
    queryBuilder.withQuery(QueryBuilders.termQuery("all", "手机"));

    // 初始化分页参数
    int page = 0;
    int size = 3;
    // 设置分页参数
    queryBuilder.withPageable(PageRequest.of(page, size));

    // 执行搜索,获取结果
    Page<Goods> goods = this.goodsRepository.search(queryBuilder.build());
    // 打印总条数
    System.out.println(goods.getTotalElements());
    // 打印总页数
    System.out.println(goods.getTotalPages());
    // 每页大小
    System.out.println(goods.getSize());
    // 当前页
    System.out.println(goods.getNumber());

● 排序

// 构建查询条件
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 添加基本的分词查询
    queryBuilder.withQuery(QueryBuilders.termQuery("all", "手机"));

    // 排序
    queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));

    // 执行搜索,获取结果
    Page<Goods> goods = this.goodsRepository.search(queryBuilder.build());
    // 打印总条数
    System.out.println(goods.getTotalElements());

● 聚合为桶

NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 不查询任何结果
    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brandId"));
    // 2、查询,需要把结果强转为AggregatedPage类型
    AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build());
    // 3、解析
    // 3.1、从结果中取出名为brands的那个聚合,
    // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    LongTerms agg = (LongTerms) aggPage.getAggregation("brands");
    // 3.2、获取桶
    List<LongTerms.Bucket> buckets = agg.getBuckets();
    // 3.3、遍历
    for (LongTerms.Bucket bucket : buckets) {
      // 3.4、获取桶中的key,即品牌名称
      System.out.println(bucket.getKeyAsString());
      // 3.5、获取桶中的文档数量
      System.out.println(bucket.getDocCount());
    }

● 嵌套聚合,求平均值

NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    // 不查询任何结果
    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
    // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
    queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brandId")
            .subAggregation(AggregationBuilders.avg("priceAvg").field("price"))); // 在品牌聚合桶内进行嵌套聚合,求平均值
    // 2、查询,需要把结果强转为AggregatedPage类型
    AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build());
    // 3、解析
    // 3.1、从结果中取出名为brands的那个聚合,
    // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
    LongTerms agg = (LongTerms) aggPage.getAggregation("brands");
    // 3.2、获取桶
    List<LongTerms.Bucket> buckets = agg.getBuckets();
    // 3.3、遍历
    for (LongTerms.Bucket bucket : buckets) {
      // 3.4、获取桶中的key,即品牌名称 3.5、获取桶中的文档数量
      System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "台");

      // 3.6.获取子聚合结果:
      InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
      System.out.println("平均售价:" + avg.getValue());
    }

附:配置搜索结果不显示为null字段:

spring:
 jackson:
  default-property-inclusion: non_null # 配置json处理时忽略空值

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java线程同步的四种方式详解

    Java线程同步的四种方式详解

    这篇文章主要介绍了Java线程同步的四种方式详解,需要的朋友可以参考下
    2023-02-02
  • java源码阅读之java.lang.Object

    java源码阅读之java.lang.Object

    这篇文章主要介绍了java源码阅读之java.lang.Object,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 使用springboot打包后的文件读取方式

    使用springboot打包后的文件读取方式

    这篇文章主要介绍了使用springboot打包后的文件读取方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java volatile的适用场景实例详解

    Java volatile的适用场景实例详解

    在本文里我们给大家整理了一篇关于Java volatile的适用场景实例内容和知识点,需要的朋友们可以学习下。
    2019-08-08
  • JVM 运行时数据区与JMM 内存模型

    JVM 运行时数据区与JMM 内存模型

    这篇文章主要介绍了JVM 运行时数据区与JMM 内存模型,文章围绕主题展开详细的内容介绍,具有一定的参考价值。需要的朋友可以参考一下
    2022-07-07
  • idea配置检查XML中SQL语法及书写sql语句智能提示的方法

    idea配置检查XML中SQL语法及书写sql语句智能提示的方法

    idea连接了数据库,也可以执行SQL查到数据,但是无法识别sql语句中的表导致没有提示,下面这篇文章主要给大家介绍了关于idea配置检查XML中SQL语法及书写sql语句智能提示的相关资料,需要的朋友可以参考下
    2023-03-03
  • Spring Boot + Thymeleaf + Activiti 快速开发平台项目 附源码

    Spring Boot + Thymeleaf + Activiti 快速开发平台项目 附源码

    这篇文章主要介绍了Spring Boot + Thymeleaf + Activiti 快速开发平台项目附源码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 浅谈ThreadLocal为什么会内存泄漏

    浅谈ThreadLocal为什么会内存泄漏

    这篇文章主要介绍了浅谈ThreadLocal为什么会内存泄漏,每个Thread内部维护着一个ThreadLocalMap,它是一个Map,这个映射表的Key是一个弱引用,其实就是ThreadLocal本身,Value是真正存的线程变量Object,需要的朋友可以参考下
    2023-12-12
  • Java8并行流中自定义线程池操作示例

    Java8并行流中自定义线程池操作示例

    这篇文章主要介绍了Java8并行流中自定义线程池操作,结合实例形式分析了并行流的相关概念、定义及自定义线程池的相关操作技巧,需要的朋友可以参考下
    2019-05-05
  • java实现学生成绩录入系统

    java实现学生成绩录入系统

    这篇文章主要为大家详细介绍了java实现学生成绩录入系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01

最新评论