前面在 ubuntu 完成安装 elasticsearch,现在我们SpringBoot将集成elasticsearch。

1、创建SpringBoot项目

我们这边直接引入NoSql中Spring Data Elasticsearch启动器。

创建项目完成后。

项目结构:

pom文件:(新增 lombok 简化pojo)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.1.6.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.yatces.elasticsearch</groupId>
  12. <artifactId>elasticsearch-demo</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>elasticsearch-demo</name>
  15. <description>Demo project for Spring Boot</description>
  16.  
  17. <properties>
  18. <java.version>1.8</java.version>
  19. </properties>
  20.  
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  25. </dependency>
  26.  
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-test</artifactId>
  30. <scope>test</scope>
  31. </dependency>
  32. <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
  33. <dependency>
  34. <groupId>org.projectlombok</groupId>
  35. <artifactId>lombok</artifactId>
  36. <version>1.16.20</version>
  37. <scope>provided</scope>
  38. </dependency>
  39.  
  40. </dependencies>
  41.  
  42. <build>
  43. <plugins>
  44. <plugin>
  45. <groupId>org.springframework.boot</groupId>
  46. <artifactId>spring-boot-maven-plugin</artifactId>
  47. </plugin>
  48. </plugins>
  49. </build>
  50.  
  51. </project>

2、添加 elasticsearch 配置

本人习惯 yml 文件,将 application.properties 重命名为 application.yml

  1. spring:
  2. data:
  3. elasticsearch:
  4. cluster-name: elasticsearch
  5. cluster-nodes: 192.168.78.130:

3、新增实体类

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. @Document(indexName = "product",type = "item",shards = 1,replicas = 0)
  5. public class Item {
  6.  
  7. @Id
  8. Long id;
  9. @Field(type = FieldType.Text,analyzer = "ik_max_word")
  10. String title; //标题
  11. @Field(type = FieldType.Keyword)
  12. String category;// 分类
  13. @Field(type = FieldType.Keyword)
  14. String brand; // 品牌
  15. @Field(type = FieldType.Double)
  16. Double price; // 价格
  17. @Field(index = false, type = FieldType.Keyword)
  18. String images; // 图片地址
  19. }

主要注解:

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

  indexName:对应索引库名称

  type:对应在索引库中的类型

  shards:分片数量,默认5

  replicas:副本数量,默认1

@Id 作用在成员变量,标记一个字段作为id主键

@Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:

  type:字段类型,取值是枚举:FieldType

  index:是否索引,布尔类型,默认是true

  store:是否存储,布尔类型,默认是false

  analyzer:分词器名称:ik_max_word

4、编写测试

4.1新建ItemTest

用于测试 elasticsearch 的使用,使用 ElasticsearchTemplate 操作索引。

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = ElasticsearchDemoApplication.class)
  3. public class ItemTest {
  4. @Autowired
  5. private ElasticsearchTemplate elasticsearchTemplate;
  6. }

4.2创建索引和映射

  1. @Test
  2. public void testCreate(){
  3. // 创建索引,会根据Item类的@Document注解信息来创建
  4. elasticsearchTemplate.createIndex(Item.class);
  5. // 配置映射,会根据Item类中的id、Field等字段来自动完成映射
  6. elasticsearchTemplate.putMapping(Item.class);
  7. }

在 Kibana通过 GET product/_mapping 查询结果

  1. {
  2. "product": {
  3. "mappings": {
  4. "item": {
  5. "properties": {
  6. "brand": {
  7. "type": "keyword"
  8. },
  9. "category": {
  10. "type": "keyword"
  11. },
  12. "images": {
  13. "type": "keyword",
  14. "index": false
  15. },
  16. "price": {
  17. "type": "double"
  18. },
  19. "title": {
  20. "type": "text",
  21. "analyzer": "ik_max_word"
  22. }
  23. }
  24. }
  25. }
  26. }
  27. }

4.3删除索引

  1.  
  1. @Test
    public void testDelete(){
    //elasticsearchTemplate.deleteIndex(Item.class);
    // indexName = "product"
    elasticsearchTemplate.deleteIndex("product");
    }

Kibana 再次查询,报404。

  1. {
  2. "error": {
  3. "root_cause": [
  4. {
  5. "type": "index_not_found_exception",
  6. "reason": "no such index",
  7. "resource.type": "index_or_alias",
  8. "resource.id": "product",
  9. "index_uuid": "_na_",
  10. "index": "product"
  11. }
  12. ],
  13. "type": "index_not_found_exception",
  14. "reason": "no such index",
  15. "resource.type": "index_or_alias",
  16. "resource.id": "product",
  17. "index_uuid": "_na_",
  18. "index": "product"
  19. },
  20. "status": 404
  21. }

4.4新建 ItemRepository

用于对 document 的操作测试

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

在 ItemTest 中注入 ItemRepository

  1. @Autowired
  2. private ItemRepository itemRepository;

4.5新增文档

修改和新增是同一个接口,区分的依据就是id,新增用POST 请求,修改用PUT请求。

  1. @Test
  2. public void testSaveDocument(){
  3. Item item = new Item(1L, "小米手机7", " 手机", "小米", 3499.00, "13123.jpg");
  4. itemRepository.save(item);
  5. }

Kibana 通过GET product/_search 查询

  1. {
  2. "took": 1,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total": 1,
  12. "max_score": 1,
  13. "hits": [
  14. {
  15. "_index": "product",
  16. "_type": "item",
  17. "_id": "1",
  18. "_score": 1,
  19. "_source": {
  20. "id": 1,
  21. "title": "小米手机7",
  22. "category": " 手机",
  23. "brand": "小米",
  24. "price": 3499,
  25. "images": "13123.jpg"
  26. }
  27. }
  28. ]
  29. }
  30. }

4.6批量新增

  1. @Test
  2. public void testSaveDocumentList() {
  3. List<Item> list = new ArrayList<>();
  4. list.add(new Item(1L, "小米手机7", "手机", "小米", 3299.00, "13123.jpg"));
  5. list.add(new Item(2L, "坚果手机R1", "手机", "锤子", 3699.00, "13123.jpg"));
  6. list.add(new Item(3L, "华为META10", "手机", "华为", 4499.00, "13123.jpg"));
  7. list.add(new Item(4L, "小米Mix2S", "手机", "小米", 4299.00, "13123.jpg"));
  8. list.add(new Item(5L, "荣耀V10", "手机", "华为", 2799.00, "13123.jpg"));
  9. // 接收对象集合,实现批量新增
  10. itemRepository.saveAll(list);
  11. }

Kibana 通过GET product/_search 再次查询,得到5个doc

4.7基本查询

在 ElasticsearchRepository 继承下来的查询方法

4.7.1根据Id查询

  1. @Test
  2. public void testFindById(){
  3. Optional<Item> optional = itemRepository.findById(1l);
  4. System.out.println(optional.get());
  5. }

结果

4.7.2查询所有

  1. @Test
  2. public void testFindAll(){
  3. // 查询所有,并根据 price 降序排序
  4. Iterable<Item> items = itemRepository.findAll(Sort.by(Sort.Direction.DESC,"price"));
  5. items.forEach(System.out::println);
  6. }

结果

4.8自定义方法

Spring Data 的提供一个强大功能,是根据方法名称自动实现功能,下述自定义规范:

在ItemRepository定义一个方法findByPriceBetween,不用写这个方法的实现例如:根据价格区间查询所有 item

/**
 * 根据价格区间查询
 * @param price1
 * @param price2
 * @return
 */

  1. List<Item> findByPriceBetween(double price1, double price2);

在 ItemTest 编写测试

  1. @Test
  2. public void testFindByPriceBetween(){
  3. List<Item> list = this.itemRepository.findByPriceBetween(4000.00, 5000.00);
  4. list.forEach(System.out::println);
  5. }

结果

4.9高级查询

4.9.1基本查询

Repository 的 search 方法,使用 QueryBuilders 构建查询条件

QueryBuilders 提供了大量的静态方法,用于生成各种不同类型的查询对象,例如:词条、模糊、通配符等QueryBuilder对象

  1. public void testQuery(){
  2. // 词条查询
  3. MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "小米");
  4. // 执行查询
  5. Iterable<Item> items = this.itemRepository.search(queryBuilder);
  6. items.forEach(System.out::println);
  7. }

结果

4.9.2自定义查询

  1. @Test
  2. public void testNativeQuery(){
  3. // 构建查询条件
  4. NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
  5. // 添加基本的分词查询
  6. queryBuilder.withQuery(QueryBuilders.matchQuery("title", "小米"));
  7. // 执行搜索,获取结果
  8. Page<Item> items = this.itemRepository.search(queryBuilder.build());
  9. // 打印总条数
  10. System.out.println(items.getTotalElements());
  11. // 打印总页数
  12. System.out.println(items.getTotalPages());
  13. items.forEach(System.out::println);
  14. }

结果

NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体。

Page<item>:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:

  totalElements:总条数

  totalPages:总页数

  Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据

4.9.3分页查询

利用NativeSearchQueryBuilder可以方便的实现分页

  1. @Test
  2. public void testNativePageQuery(){
  3. // 构建查询条件
  4. NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
  5. // 添加基本的分词查询
  6. queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
  7.  
  8. // 初始化分页参数
  9. int page = 0;
  10. int size = 3;
  11. // 设置分页参数
  12. queryBuilder.withPageable(PageRequest.of(page, size));
  13.  
  14. // 执行搜索,获取结果
  15. Page<Item> items = this.itemRepository.search(queryBuilder.build());
  16. // 打印总条数
  17. System.out.println("总条数:"+items.getTotalElements());
  18. // 打印总页数
  19. System.out.println("总页数:"+items.getTotalPages());
  20. // 每页大小
  21. System.out.println("每页大小:"+items.getSize());
  22. // 当前页
  23. System.out.println("当前页:"+items.getNumber());
  24. items.forEach(System.out::println);
  25. }

结果:分页是从第0页开始

4.9.4排序

排序也通用通过NativeSearchQueryBuilder完成

  1. @Test
  2. public void testSortQuery(){
  3. // 构建查询条件
  4. NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
  5. // 添加基本的分词查询
  6. queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
  7.  
  8. // 排序
  9. queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
  10.  
  11. // 执行搜索,获取结果
  12. Page<Item> items = this.itemRepository.search(queryBuilder.build());
  13. // 打印总条数
  14. System.out.println("总条数:"+items.getTotalElements());
  15. items.forEach(System.out::println);
  16. }

结果

4.10聚合

4.10.1普通聚合

按照品牌brand进行分组

  1. @Test
  2. public void testBrandAgg(){
  3. NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
  4. // 不查询任何结果
  5. queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
  6. // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
  7. queryBuilder.addAggregation(
  8. AggregationBuilders.terms("brands").field("brand"));
  9. // 2、查询,需要把结果强转为AggregatedPage类型
  10. AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());
  11. // 3、解析
  12. // 3.1、从结果中取出名为brands的那个聚合,
  13. // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
  14. StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
  15. // 3.2、获取桶
  16. List<StringTerms.Bucket> buckets = agg.getBuckets();
  17. // 3.3、遍历
  18. for (StringTerms.Bucket bucket : buckets) {
  19. // 3.4、获取桶中的key,即品牌名称 和 文档数量
  20. System.out.println(bucket.getKeyAsString() + ":" +bucket.getDocCount());
  21. }
  22. }

结果

AggregationBuilders.terms("brands").field("brand") 聚合的构建工厂类AggregationBuilders,所有聚合都由这个类来构建

aggPage.getAggregation("brands")返回的结果都是Aggregation类型对象,不过根据字段类型不同,又有不同的子类表示

4.10.2嵌套聚合

  1. @Test
  2. public void testSubAvgAgg(){
  3. NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
  4. // 不查询任何结果
  5. queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
  6. // 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
  7. queryBuilder.addAggregation(
  8. AggregationBuilders.terms("brands").field("brand")
  9. .subAggregation(AggregationBuilders.avg("avgPrice").field("price")) // 在品牌聚合桶内进行嵌套聚合,求平均值
  10. );
  11. // 2、查询,需要把结果强转为AggregatedPage类型
  12. AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());
  13. // 3、解析
  14. // 3.1、从结果中取出名为brands的那个聚合,
  15. // 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
  16. StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
  17. // 3.2、获取桶
  18. List<StringTerms.Bucket> buckets = agg.getBuckets();
  19. // 3.3、遍历
  20. buckets.forEach(bucket -> {
  21. // 3.4、获取桶中的key,即品牌名称 ; 获取桶中的文档数量 ;获取平均值结果:
  22. InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("avgPrice");
  23. System.out.println(bucket.getKeyAsString() + "共" + bucket.getDocCount() +",平均售价:"+ avg.getValue() );
  24. });
  25. }

结果

SpringBoot 集成 Elasticsearch的更多相关文章

  1. springboot集成elasticsearch

    在基础阶段学习ES一般是首先是 安装ES后借助 Kibana 来进行CURD 了解ES的使用: 在进阶阶段可以需要学习ES的底层原理,如何通过Version来实现乐观锁保证ES不出问题等核心原理: 第 ...

  2. springboot 集成elasticsearch

    In this article, we will discuss about “How to create a Spring Boot + Spring Data + Elasticsearch Ex ...

  3. ElasticSearch(八):springboot集成ElasticSearch集群并使用

    1. 集群的搭建 见:ElasticSearch(七) 2. springboot配置集群 2.1 创建springboot项目,使用idea创建,不过多介绍(创建项目时候建议不要勾选elastics ...

  4. springBoot集成Elasticsearch抛出Factory method 'restHighLevelClient' threw exception; nested exception is java.lang.NoSuchFieldError: IGNORE_DEPRECATIONS

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restHighLeve ...

  5. ElasticSearch(十):springboot集成ElasticSearch集群完成数据的增,删,改

    前言 之前介绍了使用devTools进行索引库数据的crud,这里使用的是java程序,使用中间件activeMQ进行数据库和索引库数据的同步.主要是用来完成对数据库的修改来完成对索引库的同步. 正文 ...

  6. Springboot 集成 ElasticSearch 踩坑

    这里只涉及到基础使用 导包 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  7. SpringBoot 集成Elasticsearch进行简单增删改查

    一.引入的pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  8. springboot集成elasticsearch遇到的问题

    public interface EsBlogRepository extends ElasticsearchRepository<EsBlog,String>{ Page<EsBl ...

  9. springboot集成elk 一: springboot + Elasticsearch

    1.ELK介绍 1> Elasticsearch是实时全文搜索和分析引擎, 提供搜集.分析.存储数据三大功能: 是一套开放REST和JAVA API等结构提供高效搜索功能,可扩展的分布式系统. ...

随机推荐

  1. leetcode 签到 面试题40. 最小的k个数

    题目 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...

  2. ASP.NET Core AutoWrapper 自定义响应输出

    前言 AutoWrapper是一个简单可自定义全局异常处理程序和ASP.NET Core API响应的包装.他使用ASP.NET Core middleware拦截传入的HTTP请求,并将最后的结果使 ...

  3. C# NAudio录音和播放音频文件及实时绘制音频波形图(从音频流数据获取,而非设备获取)

    下午写了一篇关于NAudio的录音.播放和波形图的博客,不太满意,感觉写的太乱,又总结了下 NAudio是个相对成熟.开源的C#音频开发工具,它包含录音.播放录音.格式转换.混音调整等功能.本次介绍主 ...

  4. Kullback-Leibler(KL)散度介绍

    在这篇文章中,我们将探讨一种比较两个概率分布的方法,称为Kullback-Leibler散度(通常简称为KL散度).通常在概率和统计中,我们会用更简单的近似分布来代替观察到的数据或复杂的分布.KL散度 ...

  5. API开放平台接口设计-------基于OAuth2.0协议方式

    1,简介OAuth http://www.ruanyifeng.com/blog/2019/04/oauth_design.html OAuth 是什么? http://www.ruanyifeng. ...

  6. 线程间交换数据的Exchanger

    作者:Steven1997 链接:https://www.jianshu.com/p/9b59829fb191 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. Exc ...

  7. ​结合异步模型,再次总结Netty多线程编码最佳实践

    更多技术分享可关注我 前言 本文重点总结Netty多线程的一些编码最佳实践和注意事项,并且顺便对Netty的线程调度模型,和异步模型做了一个汇总.原文:​​结合异步模型,再次总结Netty多线程编码最 ...

  8. C/C++知识总结 二 C/C++基础知识

    C/C++基础知识 C/C++基本格式说明 C/C++基本常识说明 C/C++基本格式说明 C语言基本格式 #include<stdio.h> //预处理文件 int main() //自 ...

  9. 从JDK源码学习Hashmap

    这篇文章记录一下hashmap的学习过程,文章并没有涉及hashmap整个源码,只学习一些重要部分,如有表述错误还请在评论区指出~ 1.基本概念 Hashmap采用key算hash映射到具体的valu ...

  10. 曹工说Redis源码(2)-- redis server 启动过程解析及简单c语言基础知识补充

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...