当前位置:   article > 正文

SpringBoot 集成ES 实现增删改查(附源码) 建议收藏!

springboot集成es8实现增删改查
点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐]

一、ElasticSearch 简介

1、简介

ElasticSearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多员工能力的全文搜索引擎,基于 RESTful web 接口。Elasticsearch 是用 Java 语言开发的,并作为 Apache 许可条款下的开放源码发布,是一种流行的企业级搜索引擎。

ElasticSearch 用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

2、特性

  • 分布式的文档存储引擎

  • 分布式的搜索引擎和分析引擎

  • 分布式,支持PB级数据

3、使用场景

  • 搜索领域:如百度、谷歌,全文检索等。

  • 门户网站:访问统计、文章点赞、留言评论等。

  • 广告推广:记录员工行为数据、消费趋势、员工群体进行定制推广等。

  • 信息采集:记录应用的埋点数据、访问日志数据等,方便大数据进行分析。

二、ElasticSearch 基础概念

1、ElaticSearch 和 DB 的关系

在 Elasticsearch 中,文档归属于一种类型 type,而这些类型存在于索引 index 中,我们可以列一些简单的不同点,来类比传统关系型数据库:

  • Relational DB -> Databases -> Tables -> Rows -> Columns

  • Elasticsearch -> Indices -> Types -> Documents -> Fields

Elasticsearch 集群可以包含多个索引 indices,每一个索引可以包含多个类型 types,每一个类型包含多个文档 documents,然后每个文档包含多个字段 Fields。而在 DB 中可以有多个数据库 Databases,每个库中可以有多张表 Tables,没个表中又包含多行Rows,每行包含多列Columns。

2、索引

索引基本概念(indices):

索引是含义相同属性的文档集合,是 ElasticSearch 的一个逻辑存储,可以理解为关系型数据库中的数据库,ElasticSearch 可以把索引数据存放到一台服务器上,也可以 sharding 后存到多台服务器上,每个索引有一个或多个分片,每个分片可以有多个副本。

索引类型(index_type):

索引可以定义一个或多个类型,文档必须属于一个类型。在 ElasticSearch 中,一个索引对象可以存储多个不同用途的对象,通过索引类型可以区分单个索引中的不同对象,可以理解为关系型数据库中的表。每个索引类型可以有不同的结构,但是不同的索引类型不能为相同的属性设置不同的类型。

3、文档

文档(document):

文档是可以被索引的基本数据单位。存储在 ElasticSearch 中的主要实体叫文档 document,可以理解为关系型数据库中表的一行记录。每个文档由多个字段构成,ElasticSearch 是一个非结构化的数据库,每个文档可以有不同的字段,并且有一个唯一的标识符。

4、映射

映射(mapping):

ElasticSearch 的 Mapping 非常类似于静态语言中的数据类型:声明一个变量为 int 类型的变量,以后这个变量都只能存储 int 类型的数据。同样的,一个 number 类型的 mapping 字段只能存储 number 类型的数据。

同语言的数据类型相比,Mapping 还有一些其他的含义,Mapping 不仅告诉 ElasticSearch 一个 Field 中是什么类型的值, 它还告诉 ElasticSearch 如何索引数据以及数据是否能被搜索到。

ElaticSearch 默认是动态创建索引和索引类型的 Mapping 的。这就相当于无需定义 Solr 中的 Schema,无需指定各个字段的索引规则就可以索引文件,很方便。但有时方便就代表着不灵活。比如,ElasticSearch 默认一个字段是要做分词的,但我们有时要搜索匹配整个字段却不行。如有统计工作要记录每个城市出现的次数。对于 name 字段,若记录 new york 文本,ElasticSearch 可能会把它拆分成 new 和 york 这两个词,分别计算这个两个单词的次数,而不是我们期望的 new york。

三、SpringBoot 项目引入 ElasticSearch 依赖

下面介绍下 SpringBoot 如何通过 elasticsearch-rest-high-level-client 工具操作 ElasticSearch,这里需要说一下,为什么没有使用 Spring 家族封装的 spring-data-elasticsearch。

主要原因是灵活性和更新速度,Spring 将 ElasticSearch 过度封装,让开发者很难跟 ES 的 DSL 查询语句进行关联。再者就是更新速度,ES 的更新速度是非常快,但是 spring-data-elasticsearch 更新速度比较缓慢。

由于上面两点,所以选择了官方推出的 Java 客户端 elasticsearch-rest-high-level-client,它的代码写法跟 DSL 语句很相似,懂 ES 查询的使用其上手很快。

示例项目地址:https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-elasticsearch-example

1、Maven 引入相关依赖

  • lombok:lombok 工具依赖。

  • fastjson:用于将 JSON 转换对象的依赖。

  • spring-boot-starter-web: SpringBoot 的 Web 依赖。

  • elasticsearch:ElasticSearch:依赖,需要和 ES 版本保持一致。

  • elasticsearch-rest-high-level-client:用于操作 ES 的 Java 客户端。

  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 https://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.2.4.RELEASE</version>
  9.         <relativePath/> <!-- lookup parent from repository -->
  10.     </parent>
  11.     <groupId>club.mydlq</groupId>
  12.     <artifactId>springboot-elasticsearch-example</artifactId>
  13.     <version>0.0.1-SNAPSHOT</version>
  14.     <name>springboot-elasticsearch-example</name>
  15.     <description>Demo project for Spring Boot ElasticSearch</description>
  16.     <properties>
  17.         <java.version>1.8</java.version>
  18.     </properties>
  19.     <dependencies>
  20.         <!--web-->
  21.         <dependency>
  22.             <groupId>org.springframework.boot</groupId>
  23.             <artifactId>spring-boot-starter-web</artifactId>
  24.         </dependency>
  25.         <!--lombok-->
  26.         <dependency>
  27.             <groupId>org.projectlombok</groupId>
  28.             <artifactId>lombok</artifactId>
  29.             <optional>true</optional>
  30.         </dependency>
  31.         <!--fastjson-->
  32.         <dependency>
  33.             <groupId>com.alibaba</groupId>
  34.             <artifactId>fastjson</artifactId>
  35.             <version>1.2.61</version>
  36.         </dependency>
  37.         <!--elasticsearch-->
  38.         <dependency>
  39.             <groupId>org.elasticsearch.client</groupId>
  40.             <artifactId>elasticsearch-rest-high-level-client</artifactId>
  41.             <version>6.5.4</version>
  42.         </dependency>
  43.         <dependency>
  44.             <groupId>org.elasticsearch</groupId>
  45.             <artifactId>elasticsearch</artifactId>
  46.             <version>6.5.4</version>
  47.         </dependency>
  48.     </dependencies>
  49.     <build>
  50.         <plugins>
  51.             <plugin>
  52.                 <groupId>org.springframework.boot</groupId>
  53.                 <artifactId>spring-boot-maven-plugin</artifactId>
  54.             </plugin>
  55.         </plugins>
  56.     </build>
  57. </project>

2、ElasticSearch 连接配置

(1)、application.yml 配置文件

为了方便更改连接 ES 的连接配置,所以我们将配置信息放置于 application.yaml 中:

  1. #base
  2. server:
  3.   port: 8080
  4. #spring
  5. spring:
  6.   application:
  7.     name: springboot-elasticsearch-example
  8. #elasticsearch
  9. elasticsearch:
  10.   schema: http
  11.   address: 127.0.0.1:9200
  12.   connectTimeout: 5000
  13.   socketTimeout: 5000
  14.   connectionRequestTimeout: 5000
  15.   maxConnectNum: 100
  16.   maxConnectPerRoute: 100

(2)、java 连接配置类

这里需要写一个 Java 配置类读取 application 中的配置信息:

  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.client.RestClient;
  3. import org.elasticsearch.client.RestClientBuilder;
  4. import org.elasticsearch.client.RestHighLevelClient;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /**
  11.  * ElasticSearch 配置
  12.  */
  13. @Configuration
  14. public class ElasticSearchConfig {
  15.     /** 协议 */
  16.     @Value("${elasticsearch.schema:http}")
  17.     private String schema;
  18.     /** 集群地址,如果有多个用“,”隔开 */
  19.     @Value("${elasticsearch.address}")
  20.     private String address;
  21.     /** 连接超时时间 */
  22.     @Value("${elasticsearch.connectTimeout:5000}")
  23.     private int connectTimeout;
  24.     /** Socket 连接超时时间 */
  25.     @Value("${elasticsearch.socketTimeout:10000}")
  26.     private int socketTimeout;
  27.     /** 获取连接的超时时间 */
  28.     @Value("${elasticsearch.connectionRequestTimeout:5000}")
  29.     private int connectionRequestTimeout;
  30.     /** 最大连接数 */
  31.     @Value("${elasticsearch.maxConnectNum:100}")
  32.     private int maxConnectNum;
  33.     /** 最大路由连接数 */
  34.     @Value("${elasticsearch.maxConnectPerRoute:100}")
  35.     private int maxConnectPerRoute;
  36.     @Bean
  37.     public RestHighLevelClient restHighLevelClient() {
  38.         // 拆分地址
  39.         List<HttpHost> hostLists = new ArrayList<>();
  40.         String[] hostList = address.split(",");
  41.         for (String addr : hostList) {
  42.             String host = addr.split(":")[0];
  43.             String port = addr.split(":")[1];
  44.             hostLists.add(new HttpHost(host, Integer.parseInt(port), schema));
  45.         }
  46.         // 转换成 HttpHost 数组
  47.         HttpHost[] httpHost = hostLists.toArray(new HttpHost[]{});
  48.         // 构建连接对象
  49.         RestClientBuilder builder = RestClient.builder(httpHost);
  50.         // 异步连接延时配置
  51.         builder.setRequestConfigCallback(requestConfigBuilder -> {
  52.             requestConfigBuilder.setConnectTimeout(connectTimeout);
  53.             requestConfigBuilder.setSocketTimeout(socketTimeout);
  54.             requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
  55.             return requestConfigBuilder;
  56.         });
  57.         // 异步连接数配置
  58.         builder.setHttpClientConfigCallback(httpClientBuilder -> {
  59.             httpClientBuilder.setMaxConnTotal(maxConnectNum);
  60.             httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
  61.             return httpClientBuilder;
  62.         });
  63.         return new RestHighLevelClient(builder);
  64.     }
  65. }

四、索引操作示例

这里示例会指出通过 Kibana 的 Restful 工具操作与对应的 Java 代码操作的两个示例。扩展:某小公司RESTful、共用接口、前后端分离、接口约定的实践

1、Restful 操作示例

创建索引

创建名为 mydlq-user 的索引与对应 Mapping。

  1. PUT /mydlq-user
  2. {
  3.   "mappings": {
  4.     "doc": {
  5.       "dynamic"true,
  6.       "properties": {
  7.         "name": {
  8.           "type""text",
  9.           "fields": {
  10.             "keyword": {
  11.               "type""keyword"
  12.             }
  13.           }
  14.         },
  15.         "address": {
  16.           "type""text",
  17.           "fields": {
  18.             "keyword": {
  19.               "type""keyword"
  20.             }
  21.           }
  22.         },
  23.         "remark": {
  24.           "type""text",
  25.           "fields": {
  26.             "keyword": {
  27.               "type""keyword"
  28.             }
  29.           }
  30.         },
  31.         "age": {
  32.           "type""integer"
  33.         },
  34.         "salary": {
  35.           "type""float"
  36.         },
  37.         "birthDate": {
  38.           "type""date",
  39.           "format""yyyy-MM-dd"
  40.         },
  41.         "createTime": {
  42.           "type""date"
  43.         }
  44.       }
  45.     }
  46.   }
  47. }

删除索引

删除 mydlq-user 索引。

DELETE /mydlq-user

2、Java 代码示例

  1. import lombok.extern.slf4j.Slf4j;
  2. import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
  3. import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
  4. import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
  5. import org.elasticsearch.action.support.master.AcknowledgedResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.common.settings.Settings;
  9. import org.elasticsearch.common.xcontent.XContentBuilder;
  10. import org.elasticsearch.common.xcontent.XContentFactory;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.stereotype.Service;
  13. import java.io.IOException;
  14. @Slf4j
  15. @Service
  16. public class IndexService2 {
  17.     @Autowired
  18.     private RestHighLevelClient restHighLevelClient;
  19.     /**
  20.      * 创建索引
  21.      */
  22.     public void createIndex() {
  23.         try {
  24.             // 创建 Mapping
  25.             XContentBuilder mapping = XContentFactory.jsonBuilder()
  26.                 .startObject()
  27.                     .field("dynamic"true)
  28.                     .startObject("properties")
  29.                         .startObject("name")
  30.                             .field("type","text")
  31.                             .startObject("fields")
  32.                                 .startObject("keyword")
  33.                                     .field("type","keyword")
  34.                                 .endObject()
  35.                             .endObject()
  36.                         .endObject()
  37.                         .startObject("address")
  38.                             .field("type","text")
  39.                             .startObject("fields")
  40.                                 .startObject("keyword")
  41.                                     .field("type","keyword")
  42.                                 .endObject()
  43.                             .endObject()
  44.                         .endObject()
  45.                         .startObject("remark")
  46.                             .field("type","text")
  47.                             .startObject("fields")
  48.                                 .startObject("keyword")
  49.                                     .field("type","keyword")
  50.                                 .endObject()
  51.                             .endObject()
  52.                         .endObject()
  53.                         .startObject("age")
  54.                             .field("type","integer")
  55.                         .endObject()
  56.                         .startObject("salary")
  57.                             .field("type","float")
  58.                         .endObject()
  59.                         .startObject("birthDate")
  60.                             .field("type","date")
  61.                             .field("format""yyyy-MM-dd")
  62.                         .endObject()
  63.                         .startObject("createTime")
  64.                             .field("type","date")
  65.                         .endObject()
  66.                     .endObject()
  67.                 .endObject();
  68.             // 创建索引配置信息,配置
  69.             Settings settings = Settings.builder()
  70.                     .put("index.number_of_shards"1)
  71.                     .put("index.number_of_replicas"0)
  72.                     .build();
  73.             // 新建创建索引请求对象,然后设置索引类型(ES 7.0 将不存在索引类型)和 mapping 与 index 配置
  74.             CreateIndexRequest request = new CreateIndexRequest("mydlq-user", settings);
  75.             request.mapping("doc", mapping);
  76.             // RestHighLevelClient 执行创建索引
  77.             CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
  78.             // 判断是否创建成功
  79.             boolean isCreated = createIndexResponse.isAcknowledged();
  80.             log.info("是否创建成功:{}", isCreated);
  81.         } catch (IOException e) {
  82.             log.error("", e);
  83.         }
  84.     }
  85.     /**
  86.      * 删除索引
  87.      */
  88.     public void deleteIndex() {
  89.         try {
  90.             // 新建删除索引请求对象
  91.             DeleteIndexRequest request = new DeleteIndexRequest("mydlq-user");
  92.             // 执行删除索引
  93.             AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
  94.             // 判断是否删除成功
  95.             boolean siDeleted = acknowledgedResponse.isAcknowledged();
  96.             log.info("是否删除成功:{}", siDeleted);
  97.         } catch (IOException e) {
  98.             log.error("", e);
  99.         }
  100.     }
  101. }

五、文档操作示例

1、Restful 操作示例

增加文档信息

在索引 mydlq-user 中增加一条文档信息。

  1. POST /mydlq-user/doc
  2. {
  3.     "address""北京市",
  4.     "age"29,
  5.     "birthDate""1990-01-10",
  6.     "createTime"1579530727699,
  7.     "name""张三",
  8.     "remark""来自北京市的张先生",
  9.     "salary"100
  10. }

获取文档信息

获取 mydlq-user 的索引 id=1 的文档信息。

GET /mydlq-user/doc/1

更新文档信息

更新之前创建的 id=1 的文档信息。

  1. PUT /mydlq-user/doc/1
  2. {
  3.     "address""北京市海淀区",
  4.     "age"29,
  5.     "birthDate""1990-01-10",
  6.     "createTime"1579530727699,
  7.     "name""张三",
  8.     "remark""来自北京市的张先生",
  9.     "salary"100
  10. }

删除文档信息

删除之前创建的 id=1 的文档信息。

DELETE /mydlq-user/doc/1

2、Java 代码示例

  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.delete.DeleteRequest;
  5. import org.elasticsearch.action.delete.DeleteResponse;
  6. import org.elasticsearch.action.get.GetRequest;
  7. import org.elasticsearch.action.get.GetResponse;
  8. import org.elasticsearch.action.index.IndexRequest;
  9. import org.elasticsearch.action.index.IndexResponse;
  10. import org.elasticsearch.action.update.UpdateRequest;
  11. import org.elasticsearch.action.update.UpdateResponse;
  12. import org.elasticsearch.client.RequestOptions;
  13. import org.elasticsearch.client.RestHighLevelClient;
  14. import org.elasticsearch.common.xcontent.XContentType;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import java.io.IOException;
  18. import java.util.Date;
  19. @Slf4j
  20. @Service
  21. public class IndexService {
  22.     @Autowired
  23.     private RestHighLevelClient restHighLevelClient;
  24.     /**
  25.      * 增加文档信息
  26.      */
  27.     public void addDocument() {
  28.         try {
  29.             // 创建索引请求对象
  30.             IndexRequest indexRequest = new IndexRequest("mydlq-user""doc""1");
  31.             // 创建员工信息
  32.             UserInfo userInfo = new UserInfo();
  33.             userInfo.setName("张三");
  34.             userInfo.setAge(29);
  35.             userInfo.setSalary(100.00f);
  36.             userInfo.setAddress("北京市");
  37.             userInfo.setRemark("来自北京市的张先生");
  38.             userInfo.setCreateTime(new Date());
  39.             userInfo.setBirthDate("1990-01-10");
  40.             // 将对象转换为 byte 数组
  41.             byte[] json = JSON.toJSONBytes(userInfo);
  42.             // 设置文档内容
  43.             indexRequest.source(json, XContentType.JSON);
  44.             // 执行增加文档
  45.             IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
  46.             log.info("创建状态:{}", response.status());
  47.         } catch (Exception e) {
  48.             log.error("", e);
  49.         }
  50.     }
  51.     /**
  52.      * 获取文档信息
  53.      */
  54.     public void getDocument() {
  55.         try {
  56.             // 获取请求对象
  57.             GetRequest getRequest = new GetRequest("mydlq-user""doc""1");
  58.             // 获取文档信息
  59.             GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
  60.             // 将 JSON 转换成对象
  61.             if (getResponse.isExists()) {
  62.                 UserInfo userInfo = JSON.parseObject(getResponse.getSourceAsBytes(), UserInfo.class);
  63.                 log.info("员工信息:{}", userInfo);
  64.             }
  65.         } catch (IOException e) {
  66.             log.error("", e);
  67.         }
  68.     }
  69.     /**
  70.      * 更新文档信息
  71.      */
  72.     public void updateDocument() {
  73.         try {
  74.             // 创建索引请求对象
  75.             UpdateRequest updateRequest = new UpdateRequest("mydlq-user""doc""1");
  76.             // 设置员工更新信息
  77.             UserInfo userInfo = new UserInfo();
  78.             userInfo.setSalary(200.00f);
  79.             userInfo.setAddress("北京市海淀区");
  80.             // 将对象转换为 byte 数组
  81.             byte[] json = JSON.toJSONBytes(userInfo);
  82.             // 设置更新文档内容
  83.             updateRequest.doc(json, XContentType.JSON);
  84.             // 执行更新文档
  85.             UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
  86.             log.info("创建状态:{}", response.status());
  87.         } catch (Exception e) {
  88.             log.error("", e);
  89.         }
  90.     }
  91.     /**
  92.      * 删除文档信息
  93.      */
  94.     public void deleteDocument() {
  95.         try {
  96.             // 创建删除请求对象
  97.             DeleteRequest deleteRequest = new DeleteRequest("mydlq-user""doc""1");
  98.             // 执行删除文档
  99.             DeleteResponse response = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
  100.             log.info("删除状态:{}", response.status());
  101.         } catch (IOException e) {
  102.             log.error("", e);
  103.         }
  104.     }
  105. }

六、插入初始化数据

执行查询示例前,先往索引中插入一批数据:

1、单条插入

POST mydlq-user/_doc

{"name":"零零","address":"北京市丰台区","remark":"低层员工","age":29,"salary":3000,"birthDate":"1990-11-11","createTime":"2019-11-11T08:18:00.000Z"}

2、批量插入

POST _bulk

  1. {"index":{"_index":"mydlq-user","_type":"doc"}}
  2. {"name":"刘一","address":"北京市丰台区","remark":"低层员工","age":30,"salary":3000,"birthDate":"1989-11-11","createTime":"2019-03-15T08:18:00.000Z"}
  3. {"index":{"_index":"mydlq-user","_type":"doc"}}
  4. {"name":"陈二","address":"北京市昌平区","remark":"中层员工","age":27,"salary":7900,"birthDate":"1992-01-25","createTime":"2019-11-08T11:15:00.000Z"}
  5. {"index":{"_index":"mydlq-user","_type":"doc"}}
  6. {"name":"张三","address":"北京市房山区","remark":"中层员工","age":28,"salary":8800,"birthDate":"1991-10-05","createTime":"2019-07-22T13:22:00.000Z"}
  7. {"index":{"_index":"mydlq-user","_type":"doc"}}
  8. {"name":"李四","address":"北京市大兴区","remark":"高层员工","age":26,"salary":9000,"birthDate":"1993-08-18","createTime":"2019-10-17T15:00:00.000Z"}
  9. {"index":{"_index":"mydlq-user","_type":"doc"}}
  10. {"name":"王五","address":"北京市密云区","remark":"低层员工","age":31,"salary":4800,"birthDate":"1988-07-20","createTime":"2019-05-29T09:00:00.000Z"}
  11. {"index":{"_index":"mydlq-user","_type":"doc"}}
  12. {"name":"赵六","address":"北京市通州区","remark":"中层员工","age":32,"salary":6500,"birthDate":"1987-06-02","createTime":"2019-12-10T18:00:00.000Z"}
  13. {"index":{"_index":"mydlq-user","_type":"doc"}}
  14. {"name":"孙七","address":"北京市朝阳区","remark":"中层员工","age":33,"salary":7000,"birthDate":"1986-04-15","createTime":"2019-06-06T13:00:00.000Z"}
  15. {"index":{"_index":"mydlq-user","_type":"doc"}}
  16. {"name":"周八","address":"北京市西城区","remark":"低层员工","age":32,"salary":5000,"birthDate":"1987-09-26","createTime":"2019-01-26T14:00:00.000Z"}
  17. {"index":{"_index":"mydlq-user","_type":"doc"}}
  18. {"name":"吴九","address":"北京市海淀区","remark":"高层员工","age":30,"salary":11000,"birthDate":"1989-11-25","createTime":"2019-09-07T13:34:00.000Z"}
  19. {"index":{"_index":"mydlq-user","_type":"doc"}}
  20. {"name":"郑十","address":"北京市东城区","remark":"低层员工","age":29,"salary":5000,"birthDate":"1990-12-25","createTime":"2019-03-06T12:08:00.000Z"}
  21. {"index":{"_index":"mydlq-user","_type":"doc"}}
  22. {"name":"萧十一","address":"北京市平谷区","remark":"低层员工","age":29,"salary":3300,"birthDate":"1990-11-11","createTime":"2019-03-10T08:17:00.000Z"}
  23. {"index":{"_index":"mydlq-user","_type":"doc"}}
  24. {"name":"曹十二","address":"北京市怀柔区","remark":"中层员工","age":27,"salary":6800,"birthDate":"1992-01-25","createTime":"2019-12-03T11:09:00.000Z"}
  25. {"index":{"_index":"mydlq-user","_type":"doc"}}
  26. {"name":"吴十三","address":"北京市延庆区","remark":"中层员工","age":25,"salary":7000,"birthDate":"1994-10-05","createTime":"2019-07-27T14:22:00.000Z"}
  27. {"index":{"_index":"mydlq-user","_type":"doc"}}
  28. {"name":"冯十四","address":"北京市密云区","remark":"低层员工","age":25,"salary":3000,"birthDate":"1994-08-18","createTime":"2019-04-22T15:00:00.000Z"}
  29. {"index":{"_index":"mydlq-user","_type":"doc"}}
  30. {"name":"蒋十五","address":"北京市通州区","remark":"低层员工","age":31,"salary":2800,"birthDate":"1988-07-20","createTime":"2019-06-13T10:00:00.000Z"}
  31. {"index":{"_index":"mydlq-user","_type":"doc"}}
  32. {"name":"苗十六","address":"北京市门头沟区","remark":"高层员工","age":32,"salary":11500,"birthDate":"1987-06-02","createTime":"2019-11-11T18:00:00.000Z"}
  33. {"index":{"_index":"mydlq-user","_type":"doc"}}
  34. {"name":"鲁十七","address":"北京市石景山区","remark":"高员工","age":33,"salary":9500,"birthDate":"1986-04-15","createTime":"2019-06-06T14:00:00.000Z"}
  35. {"index":{"_index":"mydlq-user","_type":"doc"}}
  36. {"name":"沈十八","address":"北京市朝阳区","remark":"中层员工","age":31,"salary":8300,"birthDate":"1988-09-26","createTime":"2019-09-25T14:00:00.000Z"}
  37. {"index":{"_index":"mydlq-user","_type":"doc"}}
  38. {"name":"吕十九","address":"北京市西城区","remark":"低层员工","age":31,"salary":4500,"birthDate":"1988-11-25","createTime":"2019-09-22T13:34:00.000Z"}
  39. {"index":{"_index":"mydlq-user","_type":"doc"}}
  40. {"name":"丁二十","address":"北京市东城区","remark":"低层员工","age":33,"salary":2100,"birthDate":"1986-12-25","createTime":"2019-03-07T12:08:00.000Z"}

3、查询数据

插入完成后再查询数据,查看之前插入的数据是否存在:

GET mydlq-user/_search

执行后得到下面记录:

  1. {
  2.   "took"2,
  3.   "timed_out"false,
  4.   "_shards": {
  5.     "total"1,
  6.     "successful"1,
  7.     "skipped"0,
  8.     "failed"0
  9.   },
  10.   "hits": {
  11.     "total"20,
  12.     "max_score"1,
  13.     "hits": [
  14.       {
  15.         "_index""mydlq-user",
  16.         "_type""_doc",
  17.         "_id""BeN0BW8B7BNodGwRFTRj",
  18.         "_score"1,
  19.         "_source": {
  20.           "name""刘一",
  21.           "address""北京市丰台区",
  22.           "remark""低层员工",
  23.           "age"30,
  24.           "salary"3000,
  25.           "birthDate""1989-11-11",
  26.           "createTime""2019-03-15T08:18:00.000Z"
  27.         }
  28.       },
  29.       {
  30.         "_index""mydlq-user",
  31.         "_type""_doc",
  32.         "_id""BuN0BW8B7BNodGwRFTRj",
  33.         "_score"1,
  34.         "_source": {
  35.           "name""陈二",
  36.           "address""北京市昌平区",
  37.           "remark""中层员工",
  38.           "age"27,
  39.           "salary"7900,
  40.           "birthDate""1992-01-25",
  41.           "createTime""2019-11-08T11:15:00.000Z"
  42.         }
  43.       },
  44.       {
  45.         "_index""mydlq-user",
  46.         "_type""_doc",
  47.         "_id""B-N0BW8B7BNodGwRFTRj",
  48.         "_score"1,
  49.         "_source": {
  50.           "name""张三",
  51.           "address""北京市房山区",
  52.           "remark""中层员工",
  53.           "age"28,
  54.           "salary"8800,
  55.           "birthDate""1991-10-05",
  56.           "createTime""2019-07-22T13:22:00.000Z"
  57.         }
  58.       },
  59.       {
  60.         "_index""mydlq-user",
  61.         "_type""_doc",
  62.         "_id""CON0BW8B7BNodGwRFTRj",
  63.         "_score"1,
  64.         "_source": {
  65.           "name""李四",
  66.           "address""北京市大兴区",
  67.           "remark""高层员工",
  68.           "age"26,
  69.           "salary"9000,
  70.           "birthDate""1993-08-18",
  71.           "createTime""2019-10-17T15:00:00.000Z"
  72.         }
  73.       },
  74.       {
  75.         "_index""mydlq-user",
  76.         "_type""_doc",
  77.         "_id""CeN0BW8B7BNodGwRFTRj",
  78.         "_score"1,
  79.         "_source": {
  80.           "name""王五",
  81.           "address""北京市密云区",
  82.           "remark""低层员工",
  83.           "age"31,
  84.           "salary"4800,
  85.           "birthDate""1988-07-20",
  86.           "createTime""2019-05-29T09:00:00.000Z"
  87.         }
  88.       },
  89.       {
  90.         "_index""mydlq-user",
  91.         "_type""_doc",
  92.         "_id""CuN0BW8B7BNodGwRFTRj",
  93.         "_score"1,
  94.         "_source": {
  95.           "name""赵六",
  96.           "address""北京市通州区",
  97.           "remark""中层员工",
  98.           "age"32,
  99.           "salary"6500,
  100.           "birthDate""1987-06-02",
  101.           "createTime""2019-12-10T18:00:00.000Z"
  102.         }
  103.       },
  104.       {
  105.         "_index""mydlq-user",
  106.         "_type""_doc",
  107.         "_id""C-N0BW8B7BNodGwRFTRj",
  108.         "_score"1,
  109.         "_source": {
  110.           "name""孙七",
  111.           "address""北京市朝阳区",
  112.           "remark""中层员工",
  113.           "age"33,
  114.           "salary"7000,
  115.           "birthDate""1986-04-15",
  116.           "createTime""2019-06-06T13:00:00.000Z"
  117.         }
  118.       },
  119.       {
  120.         "_index""mydlq-user",
  121.         "_type""_doc",
  122.         "_id""DON0BW8B7BNodGwRFTRj",
  123.         "_score"1,
  124.         "_source": {
  125.           "name""周八",
  126.           "address""北京市西城区",
  127.           "remark""低层员工",
  128.           "age"32,
  129.           "salary"5000,
  130.           "birthDate""1987-09-26",
  131.           "createTime""2019-01-26T14:00:00.000Z"
  132.         }
  133.       },
  134.       {
  135.         "_index""mydlq-user",
  136.         "_type""_doc",
  137.         "_id""DeN0BW8B7BNodGwRFTRj",
  138.         "_score"1,
  139.         "_source": {
  140.           "name""吴九",
  141.           "address""北京市海淀区",
  142.           "remark""高层员工",
  143.           "age"30,
  144.           "salary"11000,
  145.           "birthDate""1989-11-25",
  146.           "createTime""2019-09-07T13:34:00.000Z"
  147.         }
  148.       },
  149.       {
  150.         "_index""mydlq-user",
  151.         "_type""_doc",
  152.         "_id""DuN0BW8B7BNodGwRFTRj",
  153.         "_score"1,
  154.         "_source": {
  155.           "name""郑十",
  156.           "address""北京市东城区",
  157.           "remark""低层员工",
  158.           "age"29,
  159.           "salary"5000,
  160.           "birthDate""1990-12-25",
  161.           "createTime""2019-03-06T12:08:00.000Z"
  162.         }
  163.       }
  164.     ]
  165.   }
  166. }

七、查询操作示例

1、精确查询(term)

(1)、Restful 操作示例

精确查询

精确查询,查询地址为 北京市通州区 的人员信息:

查询条件不会进行分词,但是查询内容可能会分词,导致查询不到。之前在创建索引时设置 Mapping 中 address 字段存在 keyword 字段是专门用于不分词查询的子字段。

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "term": {
  5.       "address.keyword": {
  6.         "value""北京市通州区"
  7.       }
  8.     }
  9.   }
  10. }

精确查询-多内容查询

精确查询,查询地址为 北京市丰台区、北京市昌平区 或 北京市大兴区 的人员信息:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "terms": {
  5.       "address.keyword": [
  6.         "北京市丰台区",
  7.         "北京市昌平区",
  8.         "北京市大兴区"
  9.       ]
  10.     }
  11.   }
  12. }
(2)、Java 代码示例
  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.search.SearchRequest;
  5. import org.elasticsearch.action.search.SearchResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.index.query.QueryBuilders;
  9. import org.elasticsearch.rest.RestStatus;
  10. import org.elasticsearch.search.SearchHit;
  11. import org.elasticsearch.search.SearchHits;
  12. import org.elasticsearch.search.builder.SearchSourceBuilder;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Service;
  15. import java.io.IOException;
  16. @Slf4j
  17. @Service
  18. public class TermQueryService {
  19.     @Autowired
  20.     private RestHighLevelClient restHighLevelClient;
  21.     /**
  22.      * 精确查询(查询条件不会进行分词,但是查询内容可能会分词,导致查询不到)
  23.      */
  24.     public void termQuery() {
  25.         try {
  26.             // 构建查询条件(注意:termQuery 支持多种格式查询,如 boolean、int、double、string 等,这里使用的是 string 的查询)
  27.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  28.             searchSourceBuilder.query(QueryBuilders.termQuery("address.keyword""北京市通州区"));
  29.             // 创建查询请求对象,将查询对象配置到其中
  30.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  31.             searchRequest.source(searchSourceBuilder);
  32.             // 执行查询,然后处理响应结果
  33.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  34.             // 根据状态和数据条数验证是否返回了数据
  35.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  36.                 SearchHits hits = searchResponse.getHits();
  37.                 for (SearchHit hit : hits) {
  38.                     // 将 JSON 转换成对象
  39.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  40.                     // 输出查询信息
  41.                     log.info(userInfo.toString());
  42.                 }
  43.             }
  44.         } catch (IOException e) {
  45.             log.error("", e);
  46.         }
  47.     }
  48.     /**
  49.      * 多个内容在一个字段中进行查询
  50.      */
  51.     public void termsQuery() {
  52.         try {
  53.             // 构建查询条件(注意:termsQuery 支持多种格式查询,如 boolean、int、double、string 等,这里使用的是 string 的查询)
  54.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  55.             searchSourceBuilder.query(QueryBuilders.termsQuery("address.keyword""北京市丰台区""北京市昌平区""北京市大兴区"));
  56.             // 创建查询请求对象,将查询对象配置到其中
  57.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  58.             searchRequest.source(searchSourceBuilder);
  59.             // 执行查询,然后处理响应结果
  60.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  61.             // 根据状态和数据条数验证是否返回了数据
  62.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  63.                 SearchHits hits = searchResponse.getHits();
  64.                 for (SearchHit hit : hits) {
  65.                     // 将 JSON 转换成对象
  66.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  67.                     // 输出查询信息
  68.                     log.info(userInfo.toString());
  69.                 }
  70.             }
  71.         } catch (IOException e) {
  72.             log.error("", e);
  73.         }
  74.     }
  75. }

2、匹配查询(match)

(1)、Restful 操作示例

匹配查询全部数据与分页

匹配查询符合条件的所有数据,并且设置以 salary 字段升序排序,并设置分页:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "match_all": {}
  5.   },
  6.   "from"0,
  7.   "size"10,
  8.   "sort": [
  9.     {
  10.       "salary": {
  11.         "order""asc"
  12.       }
  13.     }
  14.   ]
  15. }

匹配查询数据

匹配查询地址为 通州区 的数据:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "match": {
  5.       "address""通州区"
  6.     }
  7.   }
  8. }

词语匹配查询

词语匹配进行查询,匹配 address 中为 北京市通州区 的员工信息:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "match_phrase": {
  5.       "address""北京市通州区"
  6.     }
  7.   }
  8. }

内容多字段查询

查询在字段 address、remark 中存在 北京 内容的员工信息:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "multi_match": {
  5.       "query""北京",
  6.       "fields": ["address","remark"]
  7.     }
  8.   }
  9. }
(2)、Java 代码示例
  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.search.SearchRequest;
  5. import org.elasticsearch.action.search.SearchResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.index.query.MatchAllQueryBuilder;
  9. import org.elasticsearch.index.query.QueryBuilders;
  10. import org.elasticsearch.rest.RestStatus;
  11. import org.elasticsearch.search.SearchHit;
  12. import org.elasticsearch.search.SearchHits;
  13. import org.elasticsearch.search.builder.SearchSourceBuilder;
  14. import org.elasticsearch.search.sort.SortOrder;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import java.io.IOException;
  18. @Slf4j
  19. @Service
  20. public class MatchQueryService {
  21.     @Autowired
  22.     private RestHighLevelClient restHighLevelClient;
  23.     /**
  24.      * 匹配查询符合条件的所有数据,并设置分页
  25.      */
  26.     public Object matchAllQuery() {
  27.         try {
  28.             // 构建查询条件
  29.             MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
  30.             // 创建查询源构造器
  31.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  32.             searchSourceBuilder.query(matchAllQueryBuilder);
  33.             // 设置分页
  34.             searchSourceBuilder.from(0);
  35.             searchSourceBuilder.size(3);
  36.             // 设置排序
  37.             searchSourceBuilder.sort("salary", SortOrder.ASC);
  38.             // 创建查询请求对象,将查询对象配置到其中
  39.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  40.             searchRequest.source(searchSourceBuilder);
  41.             // 执行查询,然后处理响应结果
  42.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  43.             // 根据状态和数据条数验证是否返回了数据
  44.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  45.                 SearchHits hits = searchResponse.getHits();
  46.                 for (SearchHit hit : hits) {
  47.                     // 将 JSON 转换成对象
  48.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  49.                     // 输出查询信息
  50.                     log.info(userInfo.toString());
  51.                 }
  52.             }
  53.         } catch (IOException e) {
  54.             log.error("", e);
  55.         }
  56.     }
  57.     /**
  58.      * 匹配查询数据
  59.      */
  60.     public Object matchQuery() {
  61.         try {
  62.             // 构建查询条件
  63.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  64.             searchSourceBuilder.query(QueryBuilders.matchQuery("address""*通州区"));
  65.             // 创建查询请求对象,将查询对象配置到其中
  66.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  67.             searchRequest.source(searchSourceBuilder);
  68.             // 执行查询,然后处理响应结果
  69.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  70.             // 根据状态和数据条数验证是否返回了数据
  71.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  72.                 SearchHits hits = searchResponse.getHits();
  73.                 for (SearchHit hit : hits) {
  74.                     // 将 JSON 转换成对象
  75.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  76.                     // 输出查询信息
  77.                     log.info(userInfo.toString());
  78.                 }
  79.             }
  80.         } catch (IOException e) {
  81.             log.error("", e);
  82.         }
  83.     }
  84.     /**
  85.      * 词语匹配查询
  86.      */
  87.     public Object matchPhraseQuery() {
  88.         try {
  89.             // 构建查询条件
  90.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  91.             searchSourceBuilder.query(QueryBuilders.matchPhraseQuery("address""北京市通州区"));
  92.             // 创建查询请求对象,将查询对象配置到其中
  93.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  94.             searchRequest.source(searchSourceBuilder);
  95.             // 执行查询,然后处理响应结果
  96.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  97.             // 根据状态和数据条数验证是否返回了数据
  98.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  99.                 SearchHits hits = searchResponse.getHits();
  100.                 for (SearchHit hit : hits) {
  101.                     // 将 JSON 转换成对象
  102.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  103.                     // 输出查询信息
  104.                     log.info(userInfo.toString());
  105.                 }
  106.             }
  107.         } catch (IOException e) {
  108.             log.error("", e);
  109.         }
  110.     }
  111.     /**
  112.      * 内容在多字段中进行查询
  113.      */
  114.     public Object matchMultiQuery() {
  115.         try {
  116.             // 构建查询条件
  117.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  118.             searchSourceBuilder.query(QueryBuilders.multiMatchQuery("北京市""address""remark"));
  119.             // 创建查询请求对象,将查询对象配置到其中
  120.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  121.             searchRequest.source(searchSourceBuilder);
  122.             // 执行查询,然后处理响应结果
  123.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  124.             // 根据状态和数据条数验证是否返回了数据
  125.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  126.                 SearchHits hits = searchResponse.getHits();
  127.                 for (SearchHit hit : hits) {
  128.                     // 将 JSON 转换成对象
  129.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  130.                     // 输出查询信息
  131.                     log.info(userInfo.toString());
  132.                 }
  133.             }
  134.         } catch (IOException e) {
  135.             log.error("", e);
  136.         }
  137.     }
  138. }

3、模糊查询(fuzzy)

(1)、Restful 操作示例

模糊查询所有以 三 结尾的姓名

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "fuzzy": {
  5.       "name""三"
  6.     }
  7.   }
  8. }
(2)、Java 代码示例
  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.search.SearchRequest;
  5. import org.elasticsearch.action.search.SearchResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.common.unit.Fuzziness;
  9. import org.elasticsearch.index.query.QueryBuilders;
  10. import org.elasticsearch.rest.RestStatus;
  11. import org.elasticsearch.search.SearchHit;
  12. import org.elasticsearch.search.SearchHits;
  13. import org.elasticsearch.search.builder.SearchSourceBuilder;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.stereotype.Service;
  16. import java.io.IOException;
  17. @Slf4j
  18. @Service
  19. public class FuzzyQueryService {
  20.     @Autowired
  21.     private RestHighLevelClient restHighLevelClient;
  22.     /**
  23.      * 模糊查询所有以 “三” 结尾的姓名
  24.      */
  25.     public Object fuzzyQuery() {
  26.         try {
  27.             // 构建查询条件
  28.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  29.             searchSourceBuilder.query(QueryBuilders.fuzzyQuery("name""三").fuzziness(Fuzziness.AUTO));
  30.             // 创建查询请求对象,将查询对象配置到其中
  31.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  32.             searchRequest.source(searchSourceBuilder);
  33.             // 执行查询,然后处理响应结果
  34.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  35.             // 根据状态和数据条数验证是否返回了数据
  36.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  37.                 SearchHits hits = searchResponse.getHits();
  38.                 for (SearchHit hit : hits) {
  39.                     // 将 JSON 转换成对象
  40.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  41.                     // 输出查询信息
  42.                     log.info(userInfo.toString());
  43.                 }
  44.             }
  45.         } catch (IOException e) {
  46.             log.error("", e);
  47.         }
  48.     }
  49. }

4、范围查询(range)

(1)、Restful 操作示例

查询岁数 ≥ 30 岁的员工数据:

  1. GET /mydlq-user/_search
  2. {
  3.   "query": {
  4.     "range": {
  5.       "age": {
  6.         "gte"30
  7.       }
  8.     }
  9.   }
  10. }

查询生日距离现在 30 年间的员工数据:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "range": {
  5.       "birthDate": {
  6.         "gte""now-30y"
  7.       }
  8.     }
  9.   }
  10. }
(2)、Java 代码示例
  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.search.SearchRequest;
  5. import org.elasticsearch.action.search.SearchResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.index.query.QueryBuilders;
  9. import org.elasticsearch.rest.RestStatus;
  10. import org.elasticsearch.search.SearchHit;
  11. import org.elasticsearch.search.SearchHits;
  12. import org.elasticsearch.search.builder.SearchSourceBuilder;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Service;
  15. import java.io.IOException;
  16. @Slf4j
  17. @Service
  18. public class RangeQueryService {
  19.     @Autowired
  20.     private RestHighLevelClient restHighLevelClient;
  21.     /**
  22.      * 查询岁数 ≥ 30 岁的员工数据
  23.      */
  24.     public void rangeQuery() {
  25.         try {
  26.             // 构建查询条件
  27.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  28.             searchSourceBuilder.query(QueryBuilders.rangeQuery("age").gte(30));
  29.             // 创建查询请求对象,将查询对象配置到其中
  30.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  31.             searchRequest.source(searchSourceBuilder);
  32.             // 执行查询,然后处理响应结果
  33.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  34.             // 根据状态和数据条数验证是否返回了数据
  35.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  36.                 SearchHits hits = searchResponse.getHits();
  37.                 for (SearchHit hit : hits) {
  38.                     // 将 JSON 转换成对象
  39.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  40.                     // 输出查询信息
  41.                     log.info(userInfo.toString());
  42.                 }
  43.             }
  44.         } catch (IOException e) {
  45.             log.error("", e);
  46.         }
  47.     }
  48.     /**
  49.      * 查询距离现在 30 年间的员工数据
  50.      * [年(y)、月(M)、星期(w)、天(d)、小时(h)、分钟(m)、秒(s)]
  51.      * 例如:
  52.      * now-1h 查询一小时内范围
  53.      * now-1d 查询一天内时间范围
  54.      * now-1y 查询最近一年内的时间范围
  55.      */
  56.     public void dateRangeQuery() {
  57.         try {
  58.             // 构建查询条件
  59.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  60.             // includeLower(是否包含下边界)、includeUpper(是否包含上边界)
  61.             searchSourceBuilder.query(QueryBuilders.rangeQuery("birthDate")
  62.                     .gte("now-30y").includeLower(true).includeUpper(true));
  63.             // 创建查询请求对象,将查询对象配置到其中
  64.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  65.             searchRequest.source(searchSourceBuilder);
  66.             // 执行查询,然后处理响应结果
  67.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  68.             // 根据状态和数据条数验证是否返回了数据
  69.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  70.                 SearchHits hits = searchResponse.getHits();
  71.                 for (SearchHit hit : hits) {
  72.                     // 将 JSON 转换成对象
  73.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  74.                     // 输出查询信息
  75.                     log.info(userInfo.toString());
  76.                 }
  77.             }
  78.         } catch (IOException e) {
  79.             log.error("", e);
  80.         }
  81.     }
  82. }

5、通配符查询(wildcard)

(1)、Restful 操作示例

查询所有以 “三” 结尾的姓名:

  1. GET mydlq-user/_search
  2. {
  3.   "query": {
  4.     "wildcard": {
  5.       "name.keyword": {
  6.         "value""*三"
  7.       }
  8.     }
  9.   }
  10. }
(2)、Java 代码示例
  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.search.SearchRequest;
  5. import org.elasticsearch.action.search.SearchResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.index.query.QueryBuilders;
  9. import org.elasticsearch.rest.RestStatus;
  10. import org.elasticsearch.search.SearchHit;
  11. import org.elasticsearch.search.SearchHits;
  12. import org.elasticsearch.search.builder.SearchSourceBuilder;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Service;
  15. import java.io.IOException;
  16. @Slf4j
  17. @Service
  18. public class WildcardQueryService {
  19.     @Autowired
  20.     private RestHighLevelClient restHighLevelClient;
  21.     /**
  22.      * 查询所有以 “三” 结尾的姓名
  23.      *
  24.      * *:表示多个字符(0个或多个字符)
  25.      * ?:表示单个字符
  26.      */
  27.     public Object wildcardQuery() {
  28.         try {
  29.             // 构建查询条件
  30.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  31.             searchSourceBuilder.query(QueryBuilders.wildcardQuery("name.keyword""*三"));
  32.             // 创建查询请求对象,将查询对象配置到其中
  33.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  34.             searchRequest.source(searchSourceBuilder);
  35.             // 执行查询,然后处理响应结果
  36.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  37.             // 根据状态和数据条数验证是否返回了数据
  38.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  39.                 SearchHits hits = searchResponse.getHits();
  40.                 for (SearchHit hit : hits) {
  41.                     // 将 JSON 转换成对象
  42.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  43.                     // 输出查询信息
  44.                     log.info(userInfo.toString());
  45.                 }
  46.             }
  47.         } catch (IOException e) {
  48.             log.error("", e);
  49.         }
  50.     }
  51. }

6、布尔查询(bool)

(1)、Restful 操作示例

查询出生在 1990-1995 年期间,且地址在 北京市昌平区、北京市大兴区、北京市房山区 的员工信息:

  1. GET /mydlq-user/_search
  2. {
  3.   "query": {
  4.     "bool": {
  5.       "filter": {
  6.         "range": {
  7.           "birthDate": {
  8.             "format""yyyy"
  9.             "gte"1990,
  10.             "lte"1995
  11.           }
  12.         }
  13.       },
  14.       "must": [
  15.         {
  16.           "terms": {
  17.             "address.keyword": [
  18.               "北京市昌平区",
  19.               "北京市大兴区",
  20.               "北京市房山区"
  21.             ]
  22.           }
  23.         }
  24.       ]
  25.     }
  26.   }
  27. }
(2)、Java 代码示例
  1. import club.mydlq.elasticsearch.model.entity.UserInfo;
  2. import com.alibaba.fastjson.JSON;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.elasticsearch.action.search.SearchRequest;
  5. import org.elasticsearch.action.search.SearchResponse;
  6. import org.elasticsearch.client.RequestOptions;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.elasticsearch.index.query.BoolQueryBuilder;
  9. import org.elasticsearch.index.query.QueryBuilders;
  10. import org.elasticsearch.rest.RestStatus;
  11. import org.elasticsearch.search.SearchHit;
  12. import org.elasticsearch.search.SearchHits;
  13. import org.elasticsearch.search.builder.SearchSourceBuilder;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.stereotype.Service;
  16. import java.io.IOException;
  17. @Slf4j
  18. @Service
  19. public class BoolQueryService {
  20.     @Autowired
  21.     private RestHighLevelClient restHighLevelClient;
  22.     public Object boolQuery() {
  23.         try {
  24.             // 创建 Bool 查询构建器
  25.             BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  26.             // 构建查询条件
  27.             boolQueryBuilder.must(QueryBuilders.termsQuery("address.keyword""北京市昌平区""北京市大兴区""北京市房山区"))
  28.                     .filter().add(QueryBuilders.rangeQuery("birthDate").format("yyyy").gte("1990").lte("1995"));
  29.             // 构建查询源构建器
  30.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  31.             searchSourceBuilder.query(boolQueryBuilder);
  32.             // 创建查询请求对象,将查询对象配置到其中
  33.             SearchRequest searchRequest = new SearchRequest("mydlq-user");
  34.             searchRequest.source(searchSourceBuilder);
  35.             // 执行查询,然后处理响应结果
  36.             SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  37.             // 根据状态和数据条数验证是否返回了数据
  38.             if (RestStatus.OK.equals(searchResponse.status()) && searchResponse.getHits().totalHits > 0) {
  39.                 SearchHits hits = searchResponse.getHits();
  40.                 for (SearchHit hit : hits) {
  41.                     // 将 JSON 转换成对象
  42.                     UserInfo userInfo = JSON.parseObject(hit.getSourceAsString(), UserInfo.class);
  43.                     // 输出查询信息
  44.                     log.info(userInfo.toString());
  45.                 }
  46.             }
  47.         }catch (IOException e){
  48.             log.error("",e);
  49.         }
  50.     }
  51. }

八、聚合查询操作示例

1、Metric 聚合分析

(1)、Restful 操作示例

统计员工总数、工资最高值、工资最低值、工资平均工资、工资总和:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_stats": {
  6.       "stats": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }

统计员工工资最低值:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_min": {
  6.       "min": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }

统计员工工资最高值:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_max": {
  6.       "max": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }

统计员工工资平均值:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_avg": {
  6.       "avg": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }

统计员工工资总值:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_sum": {
  6.       "sum": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }

统计员工总数:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "employee_count": {
  6.       "value_count": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }

统计员工工资百分位:

  1. GET /mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_percentiles": {
  6.       "percentiles": {
  7.         "field""salary"
  8.       }
  9.     }
  10.   }
  11. }
(2)、Java 代码示例
  1. import lombok.extern.slf4j.Slf4j;
  2. import org.elasticsearch.action.search.SearchRequest;
  3. import org.elasticsearch.action.search.SearchResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.rest.RestStatus;
  7. import org.elasticsearch.search.aggregations.AggregationBuilder;
  8. import org.elasticsearch.search.aggregations.AggregationBuilders;
  9. import org.elasticsearch.search.aggregations.Aggregations;
  10. import org.elasticsearch.search.aggregations.metrics.avg.ParsedAvg;
  11. import org.elasticsearch.search.aggregations.metrics.max.ParsedMax;
  12. import org.elasticsearch.search.aggregations.metrics.min.ParsedMin;
  13. import org.elasticsearch.search.aggregations.metrics.percentiles.ParsedPercentiles;
  14. import org.elasticsearch.search.aggregations.metrics.percentiles.Percentile;
  15. import org.elasticsearch.search.aggregations.metrics.stats.ParsedStats;
  16. import org.elasticsearch.search.aggregations.metrics.sum.ParsedSum;
  17. import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
  18. import org.elasticsearch.search.aggregations.metrics.valuecount.ParsedValueCount;
  19. import org.elasticsearch.search.builder.SearchSourceBuilder;
  20. import org.springframework.beans.factory.annotation.Autowired;
  21. import org.springframework.stereotype.Service;
  22. import java.io.IOException;
  23. @Slf4j
  24. @Service
  25. public class AggrMetricService {
  26.     @Autowired
  27.     private RestHighLevelClient restHighLevelClient;
  28.     /**
  29.      * stats 统计员工总数、员工工资最高值、员工工资最低值、员工平均工资、员工工资总和
  30.      */
  31.     public Object aggregationStats() {
  32.         String responseResult = "";
  33.         try {
  34.             // 设置聚合条件
  35.             AggregationBuilder aggr = AggregationBuilders.stats("salary_stats").field("salary");
  36.             // 查询源构建器
  37.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  38.             searchSourceBuilder.aggregation(aggr);
  39.             // 设置查询结果不返回,只返回聚合结果
  40.             searchSourceBuilder.size(0);
  41.             // 创建查询请求对象,将查询条件配置到其中
  42.             SearchRequest request = new SearchRequest("mydlq-user");
  43.             request.source(searchSourceBuilder);
  44.             // 执行请求
  45.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  46.             // 获取响应中的聚合信息
  47.             Aggregations aggregations = response.getAggregations();
  48.             // 输出内容
  49.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  50.                 // 转换为 Stats 对象
  51.                 ParsedStats aggregation = aggregations.get("salary_stats");
  52.                 log.info("-------------------------------------------");
  53.                 log.info("聚合信息:");
  54.                 log.info("count:{}", aggregation.getCount());
  55.                 log.info("avg:{}", aggregation.getAvg());
  56.                 log.info("max:{}", aggregation.getMax());
  57.                 log.info("min:{}", aggregation.getMin());
  58.                 log.info("sum:{}", aggregation.getSum());
  59.                 log.info("-------------------------------------------");
  60.             }
  61.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  62.             responseResult = response.toString();
  63.         } catch (IOException e) {
  64.             log.error("", e);
  65.         }
  66.         return responseResult;
  67.     }
  68.     /**
  69.      * min 统计员工工资最低值
  70.      */
  71.     public Object aggregationMin() {
  72.         String responseResult = "";
  73.         try {
  74.             // 设置聚合条件
  75.             AggregationBuilder aggr = AggregationBuilders.min("salary_min").field("salary");
  76.             // 查询源构建器
  77.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  78.             searchSourceBuilder.aggregation(aggr);
  79.             searchSourceBuilder.size(0);
  80.             // 创建查询请求对象,将查询条件配置到其中
  81.             SearchRequest request = new SearchRequest("mydlq-user");
  82.             request.source(searchSourceBuilder);
  83.             // 执行请求
  84.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  85.             // 获取响应中的聚合信息
  86.             Aggregations aggregations = response.getAggregations();
  87.             // 输出内容
  88.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  89.                 // 转换为 Min 对象
  90.                 ParsedMin aggregation = aggregations.get("salary_min");
  91.                 log.info("-------------------------------------------");
  92.                 log.info("聚合信息:");
  93.                 log.info("min:{}", aggregation.getValue());
  94.                 log.info("-------------------------------------------");
  95.             }
  96.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  97.             responseResult = response.toString();
  98.         } catch (IOException e) {
  99.             log.error("", e);
  100.         }
  101.         return responseResult;
  102.     }
  103.     /**
  104.      * max 统计员工工资最高值
  105.      */
  106.     public Object aggregationMax() {
  107.         String responseResult = "";
  108.         try {
  109.             // 设置聚合条件
  110.             AggregationBuilder aggr = AggregationBuilders.max("salary_max").field("salary");
  111.             // 查询源构建器
  112.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  113.             searchSourceBuilder.aggregation(aggr);
  114.             searchSourceBuilder.size(0);
  115.             // 创建查询请求对象,将查询条件配置到其中
  116.             SearchRequest request = new SearchRequest("mydlq-user");
  117.             request.source(searchSourceBuilder);
  118.             // 执行请求
  119.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  120.             // 获取响应中的聚合信息
  121.             Aggregations aggregations = response.getAggregations();
  122.             // 输出内容
  123.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  124.                 // 转换为 Max 对象
  125.                 ParsedMax aggregation = aggregations.get("salary_max");
  126.                 log.info("-------------------------------------------");
  127.                 log.info("聚合信息:");
  128.                 log.info("max:{}", aggregation.getValue());
  129.                 log.info("-------------------------------------------");
  130.             }
  131.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  132.             responseResult = response.toString();
  133.         } catch (IOException e) {
  134.             log.error("", e);
  135.         }
  136.         return responseResult;
  137.     }
  138.     /**
  139.      * avg 统计员工工资平均值
  140.      */
  141.     public Object aggregationAvg() {
  142.         String responseResult = "";
  143.         try {
  144.             // 设置聚合条件
  145.             AggregationBuilder aggr = AggregationBuilders.avg("salary_avg").field("salary");
  146.             // 查询源构建器
  147.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  148.             searchSourceBuilder.aggregation(aggr);
  149.             searchSourceBuilder.size(0);
  150.             // 创建查询请求对象,将查询条件配置到其中
  151.             SearchRequest request = new SearchRequest("mydlq-user");
  152.             request.source(searchSourceBuilder);
  153.             // 执行请求
  154.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  155.             // 获取响应中的聚合信息
  156.             Aggregations aggregations = response.getAggregations();
  157.             // 输出内容
  158.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  159.                 // 转换为 Avg 对象
  160.                 ParsedAvg aggregation = aggregations.get("salary_avg");
  161.                 log.info("-------------------------------------------");
  162.                 log.info("聚合信息:");
  163.                 log.info("avg:{}", aggregation.getValue());
  164.                 log.info("-------------------------------------------");
  165.             }
  166.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  167.             responseResult = response.toString();
  168.         } catch (IOException e) {
  169.             log.error("", e);
  170.         }
  171.         return responseResult;
  172.     }
  173.     /**
  174.      * sum 统计员工工资总值
  175.      */
  176.     public Object aggregationSum() {
  177.         String responseResult = "";
  178.         try {
  179.             // 设置聚合条件
  180.             SumAggregationBuilder aggr = AggregationBuilders.sum("salary_sum").field("salary");
  181.             // 查询源构建器
  182.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  183.             searchSourceBuilder.aggregation(aggr);
  184.             searchSourceBuilder.size(0);
  185.             // 创建查询请求对象,将查询条件配置到其中
  186.             SearchRequest request = new SearchRequest("mydlq-user");
  187.             request.source(searchSourceBuilder);
  188.             // 执行请求
  189.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  190.             // 获取响应中的聚合信息
  191.             Aggregations aggregations = response.getAggregations();
  192.             // 输出内容
  193.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  194.                 // 转换为 Sum 对象
  195.                 ParsedSum aggregation = aggregations.get("salary_sum");
  196.                 log.info("-------------------------------------------");
  197.                 log.info("聚合信息:");
  198.                 log.info("sum:{}", String.valueOf((aggregation.getValue())));
  199.                 log.info("-------------------------------------------");
  200.             }
  201.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  202.             responseResult = response.toString();
  203.         } catch (IOException e) {
  204.             log.error("", e);
  205.         }
  206.         return responseResult;
  207.     }
  208.     /**
  209.      * count 统计员工总数
  210.      */
  211.     public Object aggregationCount() {
  212.         String responseResult = "";
  213.         try {
  214.             // 设置聚合条件
  215.             AggregationBuilder aggr = AggregationBuilders.count("employee_count").field("salary");
  216.             // 查询源构建器
  217.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  218.             searchSourceBuilder.aggregation(aggr);
  219.             searchSourceBuilder.size(0);
  220.             // 创建查询请求对象,将查询条件配置到其中
  221.             SearchRequest request = new SearchRequest("mydlq-user");
  222.             request.source(searchSourceBuilder);
  223.             // 执行请求
  224.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  225.             // 获取响应中的聚合信息
  226.             Aggregations aggregations = response.getAggregations();
  227.             // 输出内容
  228.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  229.                 // 转换为 ValueCount 对象
  230.                 ParsedValueCount aggregation = aggregations.get("employee_count");
  231.                 log.info("-------------------------------------------");
  232.                 log.info("聚合信息:");
  233.                 log.info("count:{}", aggregation.getValue());
  234.                 log.info("-------------------------------------------");
  235.             }
  236.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  237.             responseResult = response.toString();
  238.         } catch (IOException e) {
  239.             log.error("", e);
  240.         }
  241.         return responseResult;
  242.     }
  243.     /**
  244.      * percentiles 统计员工工资百分位
  245.      */
  246.     public Object aggregationPercentiles() {
  247.         String responseResult = "";
  248.         try {
  249.             // 设置聚合条件
  250.             AggregationBuilder aggr = AggregationBuilders.percentiles("salary_percentiles").field("salary");
  251.             // 查询源构建器
  252.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  253.             searchSourceBuilder.aggregation(aggr);
  254.             searchSourceBuilder.size(0);
  255.             // 创建查询请求对象,将查询条件配置到其中
  256.             SearchRequest request = new SearchRequest("mydlq-user");
  257.             request.source(searchSourceBuilder);
  258.             // 执行请求
  259.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  260.             // 获取响应中的聚合信息
  261.             Aggregations aggregations = response.getAggregations();
  262.             // 输出内容
  263.             if (RestStatus.OK.equals(response.status()) || aggregations != null) {
  264.                 // 转换为 Percentiles 对象
  265.                 ParsedPercentiles aggregation = aggregations.get("salary_percentiles");
  266.                 log.info("-------------------------------------------");
  267.                 log.info("聚合信息:");
  268.                 for (Percentile percentile : aggregation) {
  269.                     log.info("百分位:{}:{}", percentile.getPercent(), percentile.getValue());
  270.                 }
  271.                 log.info("-------------------------------------------");
  272.             }
  273.             // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
  274.             responseResult = response.toString();
  275.         } catch (IOException e) {
  276.             log.error("", e);
  277.         }
  278.         return responseResult;
  279.     }
  280. }

2、Bucket 聚合分析

(1)、Restful 操作示例

按岁数进行聚合分桶,统计各个岁数员工的人数:

  1. GET mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "age_bucket": {
  6.       "terms": {
  7.         "field""age",
  8.         "size""10"
  9.       }
  10.     }
  11.   }
  12. }

按工资范围进行聚合分桶,统计工资在 3000-5000、5000-9000 和 9000 以上的员工信息:

  1. GET mydlq-user/_search
  2. {
  3.   "aggs": {
  4.     "salary_range_bucket": {
  5.       "range": {
  6.         "field""salary",
  7.         "ranges": [
  8.           {
  9.             "key""低级员工"
  10.             "to"3000
  11.           },{
  12.             "key""中级员工",
  13.             "from"5000,
  14.             "to"9000
  15.           },{
  16.             "key""高级员工",
  17.             "from"9000
  18.           }
  19.         ]
  20.       }
  21.     }
  22.   }
  23. }

按照时间范围进行分桶,统计 1985-1990 年和 1990-1995 年出生的员工信息:

  1. GET mydlq-user/_search
  2. {
  3.   "size"10,
  4.   "aggs": {
  5.     "date_range_bucket": {
  6.       "date_range": {
  7.         "field""birthDate",
  8.         "format""yyyy"
  9.         "ranges": [
  10.           {
  11.             "key""出生日期1985-1990的员工"
  12.             "from""1985",
  13.             "to""1990"
  14.           },{
  15.             "key""出生日期1990-1995的员工"
  16.             "from""1990",
  17.             "to""1995"
  18.           }
  19.         ]
  20.       }
  21.     }
  22.   }
  23. }

按工资多少进行聚合分桶,设置统计的最小值为 0,最大值为 12000,区段间隔为 3000:

  1. GET mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_histogram": {
  6.       "histogram": {
  7.         "field""salary",
  8.         "extended_bounds": {
  9.           "min"0,
  10.           "max"12000
  11.         }, 
  12.         "interval"3000
  13.       }
  14.     }
  15.   }
  16. }

按出生日期进行分桶:

  1. GET mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "birthday_histogram": {
  6.       "date_histogram": {
  7.         "format""yyyy"
  8.         "field""birthDate",
  9.         "interval""year"
  10.       }
  11.     }
  12.   }
  13. }
(2)、Java 代码示例
  1. import lombok.extern.slf4j.Slf4j;
  2. import org.elasticsearch.action.search.SearchRequest;
  3. import org.elasticsearch.action.search.SearchResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.rest.RestStatus;
  7. import org.elasticsearch.search.aggregations.AggregationBuilder;
  8. import org.elasticsearch.search.aggregations.AggregationBuilders;
  9. import org.elasticsearch.search.aggregations.Aggregations;
  10. import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
  11. import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
  12. import org.elasticsearch.search.aggregations.bucket.range.Range;
  13. import org.elasticsearch.search.aggregations.bucket.terms.Terms;
  14. import org.elasticsearch.search.builder.SearchSourceBuilder;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import java.io.IOException;
  18. import java.util.List;
  19. @Slf4j
  20. @Service
  21. public class AggrBucketService {
  22.     @Autowired
  23.     private RestHighLevelClient restHighLevelClient;
  24.     /**
  25.      * 按岁数进行聚合分桶
  26.      */
  27.     public Object aggrBucketTerms() {
  28.         try {
  29.             AggregationBuilder aggr = AggregationBuilders.terms("age_bucket").field("age");
  30.             // 查询源构建器
  31.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  32.             searchSourceBuilder.size(10);
  33.             searchSourceBuilder.aggregation(aggr);
  34.             // 创建查询请求对象,将查询条件配置到其中
  35.             SearchRequest request = new SearchRequest("mydlq-user");
  36.             request.source(searchSourceBuilder);
  37.             // 执行请求
  38.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  39.             // 获取响应中的聚合信息
  40.             Aggregations aggregations = response.getAggregations();
  41.             // 输出内容
  42.             if (RestStatus.OK.equals(response.status())) {
  43.                 // 分桶
  44.                 Terms byCompanyAggregation = aggregations.get("age_bucket");
  45.                 List<? extends Terms.Bucket> buckets = byCompanyAggregation.getBuckets();
  46.                 // 输出各个桶的内容
  47.                 log.info("-------------------------------------------");
  48.                 log.info("聚合信息:");
  49.                 for (Terms.Bucket bucket : buckets) {
  50.                     log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
  51.                 }
  52.                 log.info("-------------------------------------------");
  53.             }
  54.         } catch (IOException e) {
  55.             log.error("", e);
  56.         }
  57.     }
  58.     /**
  59.      * 按工资范围进行聚合分桶
  60.      */
  61.     public Object aggrBucketRange() {
  62.         try {
  63.             AggregationBuilder aggr = AggregationBuilders.range("salary_range_bucket")
  64.                     .field("salary")
  65.                     .addUnboundedTo("低级员工"3000)
  66.                     .addRange("中级员工"50009000)
  67.                     .addUnboundedFrom("高级员工"9000);
  68.             // 查询源构建器
  69.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  70.             searchSourceBuilder.size(0);
  71.             searchSourceBuilder.aggregation(aggr);
  72.             // 创建查询请求对象,将查询条件配置到其中
  73.             SearchRequest request = new SearchRequest("mydlq-user");
  74.             request.source(searchSourceBuilder);
  75.             // 执行请求
  76.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  77.             // 获取响应中的聚合信息
  78.             Aggregations aggregations = response.getAggregations();
  79.             // 输出内容
  80.             if (RestStatus.OK.equals(response.status())) {
  81.                 // 分桶
  82.                 Range byCompanyAggregation = aggregations.get("salary_range_bucket");
  83.                 List<? extends Range.Bucket> buckets = byCompanyAggregation.getBuckets();
  84.                 // 输出各个桶的内容
  85.                 log.info("-------------------------------------------");
  86.                 log.info("聚合信息:");
  87.                 for (Range.Bucket bucket : buckets) {
  88.                     log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
  89.                 }
  90.                 log.info("-------------------------------------------");
  91.             }
  92.         } catch (IOException e) {
  93.             log.error("", e);
  94.         }
  95.     }
  96.     /**
  97.      * 按照时间范围进行分桶
  98.      */
  99.     public Object aggrBucketDateRange() {
  100.         try {
  101.             AggregationBuilder aggr = AggregationBuilders.dateRange("date_range_bucket")
  102.                     .field("birthDate")
  103.                     .format("yyyy")
  104.                     .addRange("1985-1990""1985""1990")
  105.                     .addRange("1990-1995""1990""1995");
  106.             // 查询源构建器
  107.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  108.             searchSourceBuilder.size(0);
  109.             searchSourceBuilder.aggregation(aggr);
  110.             // 创建查询请求对象,将查询条件配置到其中
  111.             SearchRequest request = new SearchRequest("mydlq-user");
  112.             request.source(searchSourceBuilder);
  113.             // 执行请求
  114.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  115.             // 获取响应中的聚合信息
  116.             Aggregations aggregations = response.getAggregations();
  117.             // 输出内容
  118.             if (RestStatus.OK.equals(response.status())) {
  119.                 // 分桶
  120.                 Range byCompanyAggregation = aggregations.get("date_range_bucket");
  121.                 List<? extends Range.Bucket> buckets = byCompanyAggregation.getBuckets();
  122.                 // 输出各个桶的内容
  123.                 log.info("-------------------------------------------");
  124.                 log.info("聚合信息:");
  125.                 for (Range.Bucket bucket : buckets) {
  126.                     log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
  127.                 }
  128.                 log.info("-------------------------------------------");
  129.             }
  130.         } catch (IOException e) {
  131.             log.error("", e);
  132.         }
  133.     }
  134.     /**
  135.      * 按工资多少进行聚合分桶
  136.      */
  137.     public Object aggrBucketHistogram() {
  138.         try {
  139.             AggregationBuilder aggr = AggregationBuilders.histogram("salary_histogram")
  140.                     .field("salary")
  141.                     .extendedBounds(012000)
  142.                     .interval(3000);
  143.             // 查询源构建器
  144.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  145.             searchSourceBuilder.size(0);
  146.             searchSourceBuilder.aggregation(aggr);
  147.             // 创建查询请求对象,将查询条件配置到其中
  148.             SearchRequest request = new SearchRequest("mydlq-user");
  149.             request.source(searchSourceBuilder);
  150.             // 执行请求
  151.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  152.             // 获取响应中的聚合信息
  153.             Aggregations aggregations = response.getAggregations();
  154.             // 输出内容
  155.             if (RestStatus.OK.equals(response.status())) {
  156.                 // 分桶
  157.                 Histogram byCompanyAggregation = aggregations.get("salary_histogram");
  158.                 List<? extends Histogram.Bucket> buckets = byCompanyAggregation.getBuckets();
  159.                 // 输出各个桶的内容
  160.                 log.info("-------------------------------------------");
  161.                 log.info("聚合信息:");
  162.                 for (Histogram.Bucket bucket : buckets) {
  163.                     log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
  164.                 }
  165.                 log.info("-------------------------------------------");
  166.             }
  167.         } catch (IOException e) {
  168.             log.error("", e);
  169.         }
  170.     }
  171.     /**
  172.      * 按出生日期进行分桶
  173.      */
  174.     public Object aggrBucketDateHistogram() {
  175.         try {
  176.             AggregationBuilder aggr = AggregationBuilders.dateHistogram("birthday_histogram")
  177.                     .field("birthDate")
  178.                     .interval(1)
  179.                     .dateHistogramInterval(DateHistogramInterval.YEAR)
  180.                     .format("yyyy");
  181.             // 查询源构建器
  182.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  183.             searchSourceBuilder.size(0);
  184.             searchSourceBuilder.aggregation(aggr);
  185.             // 创建查询请求对象,将查询条件配置到其中
  186.             SearchRequest request = new SearchRequest("mydlq-user");
  187.             request.source(searchSourceBuilder);
  188.             // 执行请求
  189.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  190.             // 获取响应中的聚合信息
  191.             Aggregations aggregations = response.getAggregations();
  192.             // 输出内容
  193.             if (RestStatus.OK.equals(response.status())) {
  194.                 // 分桶
  195.                 Histogram byCompanyAggregation = aggregations.get("birthday_histogram");
  196.                 List<? extends Histogram.Bucket> buckets = byCompanyAggregation.getBuckets();
  197.                 // 输出各个桶的内容
  198.                 log.info("-------------------------------------------");
  199.                 log.info("聚合信息:");
  200.                 for (Histogram.Bucket bucket : buckets) {
  201.                     log.info("桶名:{} | 总数:{}", bucket.getKeyAsString(), bucket.getDocCount());
  202.                 }
  203.                 log.info("-------------------------------------------");
  204.             }
  205.         } catch (IOException e) {
  206.             log.error("", e);
  207.         }
  208.     }
  209. }

3、Metric 与 Bucket 聚合分析

(1)、Restful 操作示例

按照员工岁数分桶、然后统计每个岁数员工工资最高值:

  1. GET mydlq-user/_search
  2. {
  3.   "size"0,
  4.   "aggs": {
  5.     "salary_bucket": {
  6.       "terms": {
  7.         "field""age",
  8.         "size""10"
  9.       },
  10.       "aggs": {
  11.         "salary_max_user": {
  12.           "top_hits": {
  13.             "size"1,
  14.             "sort": [
  15.               {
  16.                 "salary": {
  17.                   "order""desc"
  18.                 }
  19.               }
  20.             ]
  21.           }
  22.         }
  23.       }
  24.     }
  25.   }
  26. }

(2)、Java 代码示例

  1. import lombok.extern.slf4j.Slf4j;
  2. import org.elasticsearch.action.search.SearchRequest;
  3. import org.elasticsearch.action.search.SearchResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.rest.RestStatus;
  7. import org.elasticsearch.search.SearchHit;
  8. import org.elasticsearch.search.aggregations.AggregationBuilder;
  9. import org.elasticsearch.search.aggregations.AggregationBuilders;
  10. import org.elasticsearch.search.aggregations.Aggregations;
  11. import org.elasticsearch.search.aggregations.bucket.terms.Terms;
  12. import org.elasticsearch.search.aggregations.metrics.tophits.ParsedTopHits;
  13. import org.elasticsearch.search.builder.SearchSourceBuilder;
  14. import org.elasticsearch.search.sort.SortOrder;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import java.io.IOException;
  18. import java.util.List;
  19. @Slf4j
  20. @Service
  21. public class AggrBucketMetricService {
  22.     @Autowired
  23.     private RestHighLevelClient restHighLevelClient;
  24.     /**
  25.      * topHits 按岁数分桶、然后统计每个员工工资最高值
  26.      */
  27.     public Object aggregationTopHits() {
  28.         try {
  29.             AggregationBuilder testTop = AggregationBuilders.topHits("salary_max_user")
  30.                     .size(1)
  31.                     .sort("salary", SortOrder.DESC);
  32.             AggregationBuilder salaryBucket = AggregationBuilders.terms("salary_bucket")
  33.                     .field("age")
  34.                     .size(10);
  35.             salaryBucket.subAggregation(testTop);
  36.             // 查询源构建器
  37.             SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  38.             searchSourceBuilder.size(0);
  39.             searchSourceBuilder.aggregation(salaryBucket);
  40.             // 创建查询请求对象,将查询条件配置到其中
  41.             SearchRequest request = new SearchRequest("mydlq-user");
  42.             request.source(searchSourceBuilder);
  43.             // 执行请求
  44.             SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  45.             // 获取响应中的聚合信息
  46.             Aggregations aggregations = response.getAggregations();
  47.             // 输出内容
  48.             if (RestStatus.OK.equals(response.status())) {
  49.                 // 分桶
  50.                 Terms byCompanyAggregation = aggregations.get("salary_bucket");
  51.                 List<? extends Terms.Bucket> buckets = byCompanyAggregation.getBuckets();
  52.                 // 输出各个桶的内容
  53.                 log.info("-------------------------------------------");
  54.                 log.info("聚合信息:");
  55.                 for (Terms.Bucket bucket : buckets) {
  56.                     log.info("桶名:{}", bucket.getKeyAsString());
  57.                     ParsedTopHits topHits = bucket.getAggregations().get("salary_max_user");
  58.                     for (SearchHit hit:topHits.getHits()){
  59.                         log.info(hit.getSourceAsString());
  60.                     }
  61.                 }
  62.                 log.info("-------------------------------------------");
  63.             }
  64.         } catch (IOException e) {
  65.             log.error("", e);
  66.         }
  67.     }
  68. }

来源 | http://www.mydlq.club/article/64/

  1. 觉得本文对你有帮助?请分享给更多人
  2. 关注「全栈开发者社区」加星标,提升全栈技能
  3. 本公众号会不定期给大家发福利,包括送书、学习资源等,敬请期待吧!
  4. 如果感觉推送内容不错,不妨右下角点个在看转发朋友圈或收藏,感谢支持。
  5. 好文章,留言、点赞、在看和分享一条龙吧❤️
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/68748
推荐阅读
相关标签
  

闽ICP备14008679号