点击上方☝SpringForAll社区 轻松关注!及时获取有趣有料的技术文章

本文来源:http://www.mydlq.club/article/64/

一、ElasticSearch 简介

. 1、简介

. 2、特性

. 3、使用场景

. 二、ElasticSearch 基础概念

. 1、ElaticSearch 和 DB 的关系

. 2、索引

. 3、文档

. 4、映射

. 三、SpringBoot 项目引入 ElasticSearch 依赖

. 1、Maven 引入相关依赖

. 2、ElasticSearch 连接配置

. 四、索引操作示例

. 1、Restful 操作示例

. 2、Java 代码示例

. 五、文档操作示例

. 1、Restful 操作示例

. 2、Java 代码示例

. 六、插入初始化数据

. 1、单条插入

. 2、批量插入

. 3、查询数据

. 七、查询操作示例

. 1、精确查询(term)

. 2、匹配查询(match)

. 3、模糊查询(fuzzy)

. 4、范围查询(range)

. 5、通配符查询(wildcard)

. 6、布尔查询(bool)

. 八、聚合查询操作示例

. 1、Metric 聚合分析

. 2、Bucket 聚合分析

. 3、Metric 与 Bucket 聚合分析


参考地址:

  • 百度百科

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

系统环境:

  • SpringBoot 版本:2.2.4

  • ElasticSearch 版本:6.5.3

一、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.0modelVersion> 5    <parent> 6        <groupId>org.springframework.bootgroupId> 7        <artifactId>spring-boot-starter-parentartifactId> 8        <version>2.2.4.RELEASEversion> 9        <relativePath/> 10    parent>11    <groupId>club.mydlqgroupId>12    <artifactId>springboot-elasticsearch-exampleartifactId>13    <version>0.0.1-SNAPSHOTversion>14    <name>springboot-elasticsearch-examplename>15    <description>Demo project for Spring Boot ElasticSearchdescription>1617    <properties>18        <java.version>1.8java.version>19    properties>20    <dependencies>21        22        <dependency>23            <groupId>org.springframework.bootgroupId>24            <artifactId>spring-boot-starter-webartifactId>25        dependency>26        27        <dependency>28            <groupId>org.projectlombokgroupId>29            <artifactId>lombokartifactId>30            <optional>trueoptional>31        dependency>32        33        <dependency>34            <groupId>com.alibabagroupId>35            <artifactId>fastjsonartifactId>36            <version>1.2.61version>37        dependency>38        39        <dependency>40            <groupId>org.elasticsearch.clientgroupId>41            <artifactId>elasticsearch-rest-high-level-clientartifactId>42            <version>6.5.4version>43        dependency>44        <dependency>45            <groupId>org.elasticsearchgroupId>46            <artifactId>elasticsearchartifactId>47            <version>6.5.4version>48        dependency>49    dependencies>5051    <build>52        <plugins>53            <plugin>54                <groupId>org.springframework.bootgroupId>55                <artifactId>spring-boot-maven-pluginartifactId>56            plugin>57        plugins>58    build>5960project>

2、ElasticSearch 连接配置

(1)、application.yml 配置文件

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

 1#base 2server: 3  port: 8080 4#spring 5spring: 6  application: 7    name: springboot-elasticsearch-example 8#elasticsearch 9elasticsearch:10  schema: http11  address: 127.0.0.1:920012  connectTimeout: 500013  socketTimeout: 500014  connectionRequestTimeout: 500015  maxConnectNum: 10016  maxConnectPerRoute: 100

(2)、java 连接配置类

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

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

四、索引操作示例

这里示例会指出通过 Kibana 的 Restful 工具操作与对应的 Java 代码操作的两个示例。

1、Restful 操作示例

创建索引

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

 1PUT /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 索引。

1DELETE /mydlq-user

2、Java 代码示例

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

五、文档操作示例

1、Restful 操作示例

增加文档信息

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

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

获取文档信息

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

1GET /mydlq-user/doc/1

更新文档信息

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

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

删除文档信息

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

1DELETE /mydlq-user/doc/1

2、Java 代码示例

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

六、插入初始化数据

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

1、单条插入

  • POST mydlq-user/_doc

1{"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、查询数据

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

1GET 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 字段是专门用于不分词查询的子字段。

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

精确查询-多内容查询

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

 1GET mydlq-user/_search 2{ 3  "query": { 4    "terms": { 5      "address.keyword": [ 6        "北京市丰台区", 7        "北京市昌平区", 8        "北京市大兴区" 9      ]10    }11  }12}

(2)、Java 代码示例

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

2、匹配查询(match)

(1)、Restful 操作示例

匹配查询全部数据与分页

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

 1GET 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}

匹配查询数据

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

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

词语匹配查询

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

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

内容多字段查询

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

1GET mydlq-user/_search2{3  "query": {4    "multi_match": {5      "query": "北京",6      "fields": ["address","remark"]7    }8  }9}

(2)、Java 代码示例

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

3、模糊查询(fuzzy)

(1)、Restful 操作示例

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

1GET mydlq-user/_search2{3  "query": {4    "fuzzy": {5      "name": "三"6    }7  }8}

(2)、Java 代码示例

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

4、范围查询(range)

(1)、Restful 操作示例

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

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

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

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

(2)、Java 代码示例

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

5、通配符查询(wildcard)

(1)、Restful 操作示例

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

 1GET mydlq-user/_search 2{ 3  "query": { 4    "wildcard": { 5      "name.keyword": { 6        "value": "*三" 7      } 8    } 9  }10}

(2)、Java 代码示例

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

6、布尔查询(bool)

(1)、Restful 操作示例

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

 1GET /mydlq-user/_search 2{ 3  "query": { 4    "bool": { 5      "filter": { 6        "range": { 7          "birthDate": { 8            "format": "yyyy",  9            "gte": 1990,10            "lte": 199511          }12        }13      },14      "must": [15        {16          "terms": {17            "address.keyword": [18              "北京市昌平区",19              "北京市大兴区",20              "北京市房山区"21            ]22          }23        }24      ]25    }26  }27}

(2)、Java 代码示例

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

八、聚合查询操作示例

1、Metric 聚合分析

(1)、Restful 操作示例

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

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

统计员工工资最低值:

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

统计员工工资最高值:

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

统计员工工资平均值:

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

统计员工工资总值:

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

统计员工总数:

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

统计员工工资百分位:

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

(2)、Java 代码示例

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

2、Bucket 聚合分析

(1)、Restful 操作示例

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

 1GET 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 以上的员工信息:

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

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

 1GET 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:

 1GET 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": 1200011        }, 12        "interval": 300013      }14    }15  }16}

按出生日期进行分桶:

 1GET 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 代码示例

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

3、Metric 与 Bucket 聚合分析

(1)、Restful 操作示例

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

 1GET 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 代码示例

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

● SpringBoot 使用 Caffeine 本地缓存

● Github推出了GitHub CLI

● (很全面)SpringBoot 集成 Apollo 配置中心

● 你知道如何成为一名靠谱的架构师不?

● Tomcat 在 SpringBoot 中是如何启动的?

● SpringBoot 深度调优,让你的项目飞起来!

● 8种经常被忽视的SQL错误用法,你有没有踩过坑?

● Java面试应该知道之深入理解Java的接口和抽象类

● Spring系列之beanFactory与ApplicationContext

● 多线程同步的五种方法

● redis应用场景

● 手把手带你剖析 Springboot 启动原理!

● Java多线程:synchronized关键字和Lock

● Java多线程:多线程基础知识

● Kafka基本架构及原理

springboot实体映射到数据库_SpringBoot 操作 ElasticSearch 详解相关推荐

  1. ElasticSearch-.net平台下c#操作ElasticSearch详解

    ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...

  2. golang操作elasticsearch详解

    golang操作elasticsearch详解 直接上代码 package mainimport ("bytes""context""fmt" ...

  3. SpringBoot 操作 ElasticSearch 详解(万字长文)

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:超级小豆丁 http://www.mydlq.club/ar ...

  4. 5万字长文!SpringBoot 操作 ElasticSearch 详解

    点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 No one can go to bear for you, no one ...

  5. springboot自动配置的原理_SpringBoot实战:详解SpringBoot自动配置原理

    SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...

  6. [Python从零到壹] 八.数据库之MySQL和Sqlite基础知识及操作万字详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  7. Java操作MongoDB详解

    Java操作MongoDB详解 1. MongoDB概述 1.1 MongoDB简介 1.2 MongoDB概念 2. MongoDB安装 2.1 MongoDB下载 2.2 MongoDB安装 2. ...

  8. vsftp建立虚拟用户不同目录分配不同权限操作步骤详解

    这篇文章主要介绍了vsftp建立虚拟用户不同目录分配不同权限操作步骤详解,大家参考设置自己的FTP服务器吧vsftpd服务器同时支持匿名用户.本地用户和虚拟用户三类用户账号,使用虚拟用户账号可以提供集 ...

  9. oracle数据库中索值,Oracle数据库中的索引详解

    Oracle数据库中的索引详解以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一 ROWID的概念 存储了row在数据文 ...

最新文章

  1. 系统架构的过程 浮现式设计
  2. linux sa 命令,Linux 常用命令全拼
  3. 代理模式、动态代理和面向方面
  4. 启动两个Tomcat的方法
  5. vue 对象里面放数组刷新问题_Vue 数组和对象更新,但是页面没有刷新的解决方式...
  6. [故障引起的故事]URL中带加号(+)的处理
  7. 探索 .NET Core 依赖注入的 IServiceCollection
  8. wamp替换mysql_将wamp集成的mysql替换成安装版的
  9. Shell 编程:Bash空格的那点事
  10. 微服务间保持事务一致性
  11. hget如何获取多个value_《深入微服务》之 如何给老婆解释什么是微服务的基础框架SpringBoot?...
  12. QTP连接数据库,并将数据保存至Excel中
  13. excel多列数据生成图分类有间隔
  14. ida 反编译 php,飘云阁安全论坛在IDA pro中的这样一段反编译代码能够改写成易语言吗 - Powered by Discuz!...
  15. matlab神经网络结果怎么看,matlab神经网络实验报告
  16. 神仙道玄奇套装材料大全
  17. 电脑连接另一台电脑发出wifi时,显示ip4无访问权限,ip6无访问权限
  18. 云朵怎么画好看?超简单的天空上色教程
  19. Python量化选股入门:资本资产定价模型(CAPM)
  20. 没有群晖却要共享文件?试试HFS搭建精简版NAS吧

热门文章

  1. 一个模型搞定多个CTR业务!阿里STAR网络介绍(附代码实现)
  2. addeventlistener不支持ajax_好程序员web前端学习路线分享了解AJAX是什么
  3. http抓包实战 pdf_抓包实战 | 浏览器里的HTTP请求到底是如何完成的?
  4. Google浏览器一开启就提示“请停用以开发者模式运行的扩展程序“解决方案
  5. Python3爬虫入门之beautifulsoup库的使用
  6. JavaScript逻辑运算符
  7. 尼克老湿の面试回顾(7)
  8. Java自动化测试框架-06 - 来给你的测试报告化个妆整个形 - (下)(详细教程)
  9. log4j 日志级别_log4j-Mybatis(5)
  10. python安卓版开发环境搭建_python+appium环境搭建