当前位置:   article > 正文

一文全览各种ES查询在Java中的实现

java实现es搜索多个index的多个字段

点击关注公众号:互联网架构师,后台回复 2T获取2TB学习资源!

上一篇:Alibaba开源内网高并发编程手册.pdf

ElasticSearch多种查询操作

  • 前言

  • 词条查询

  • 等值查询-term

  • 多值查询-terms

  • 范围查询-range

  • 前缀查询-prefix

  • 通配符查询-wildcard

  • 复合查询

  • 布尔查询

  • Filter查询

  • 聚合查询

  • 最值、平均值、求和

  • 去重查询

  • 分组聚合

  • 单条件分组

  • 多条件分组

  • 过滤聚合

前言

完整项目已上传至:ElasticSearch Demo,https://github.com/ThinkMugz/springboot-demo-major项目,该项目是关于springboot的集成项目,ElasticSearch部分请关注【elasticSearch-demo】模块。觉得有帮助的随手点个start!

这篇博文的主题是ES的查询,因此我整理了尽可能齐全的ES查询场景,形成下面的图:

0dc65aeb13e7efc77ca5187edf920a41.png

ES查询场景

本文基于elasticsearch 7.13.2版本,es从7.0以后,发生了很大的更新。7.3以后,已经不推荐使用TransportClient这个client,取而代之的是Java High Level REST Client

「测试使用的数据示例」

首先是,Mysql中的部分测试数据:

idnameagesexaddresssectskillpowercreate_timemodify_time
1张无忌18光明顶明教九阳神功992021-05-14 16:50:332021-06-29 16:48:56
2周芷若17峨眉山峨嵋派九阴真经882021-05-14 11:37:072021-06-29 16:56:40
3赵敏14大都朝廷402021-05-14 11:37:072021-06-29 15:22:24

Mysql中的一行数据在ES中以一个文档形式存在:

  1. {
  2.   "_index" : "person",
  3.   "_type" : "_doc",
  4.   "_id" : "4",
  5.   "_score" : 1.0,
  6.   "_source" : {
  7.     "address" : "峨眉山",
  8.     "modifyTime" : "2021-06-29 19:46:25",
  9.     "createTime" : "2021-05-14 11:37:07",
  10.     "sect" : "峨嵋派",
  11.     "sex" : "男",
  12.     "skill" : "降龙十八掌",
  13.     "name" : "宋青书",
  14.     "id" : 4,
  15.     "power" : 50,
  16.     "age" : 21
  17.   }
  18. }

简单梳理了一下ES JavaAPI的相关体系,感兴趣的可以自己研读一下源码。

26c10d67481d85337c5eb82107af34d3.png

ES JavaAPI的相关体系

接下来,我们用十几个实例,迅速上手ES的查询操作,每个示例将提供SQL语句、ES语句和Java代码。

词条查询

所谓词条查询,也就是ES不会对查询条件进行分词处理,只有当词条和查询字符串完全匹配时,才会被查询到。

等值查询-term

等值查询,即筛选出一个字段等于特定值的所有记录。

「SQL:」

select * from person where name = '张无忌';

而使用ES查询语句却很不一样(「注意查询字段带上keyword」):

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "term": {
  5.    "name.keyword": {
  6.     "value""张无忌",
  7.     "boost"1.0
  8.    }
  9.   }
  10.  }
  11. }

ElasticSearch 5.0以后,string类型有重大变更,移除了string类型,string字段被拆分成两种新的数据类型: text用于全文搜索的,而keyword用于关键词搜索。

「查询结果:」

  1. {
  2.   "took" : 0,
  3.   "timed_out" : false,
  4.   "_shards" : { // 分片信息
  5.     "total" : 1// 总计分片数
  6.     "successful" : 1// 查询成功的分片数
  7.     "skipped" : 0// 跳过查询的分片数
  8.     "failed" : 0  // 查询失败的分片数
  9.   },
  10.   "hits" : { // 命中结果
  11.     "total" : {
  12.       "value" : 1// 数量
  13.       "relation" : "eq"  // 关系:等于
  14.     },
  15.     "max_score" : 2.8526313,  // 最高分数
  16.     "hits" : [
  17.       {
  18.         "_index" : "person"// 索引
  19.         "_type" : "_doc"// 类型
  20.         "_id" : "1",
  21.         "_score" : 2.8526313,
  22.         "_source" : {
  23.           "address" : "光明顶",
  24.           "modifyTime" : "2021-06-29 16:48:56",
  25.           "createTime" : "2021-05-14 16:50:33",
  26.           "sect" : "明教",
  27.           "sex" : "男",
  28.           "skill" : "九阳神功",
  29.           "name" : "张无忌",
  30.           "id" : 1,
  31.           "power" : 99,
  32.           "age" : 18
  33.         }
  34.       }
  35.     ]
  36.   }
  37. }

「Java中构造ES请求的方式:」(后续例子中只保留SearchSourceBuilder的构建语句)

  1. /**
  2.  * term精确查询
  3.  *
  4.  * @throws IOException
  5.  */
  6. @Autowired
  7. private RestHighLevelClient client;
  8. @Test
  9. public void queryTerm() throws IOException {
  10.  // 根据索引创建查询请求
  11.     SearchRequest searchRequest = new SearchRequest("person");
  12.     SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  13.     // 构建查询语句
  14.     searchSourceBuilder.query(QueryBuilders.termQuery("name.keyword""张无忌"));
  15.     System.out.println("searchSourceBuilder=====================" + searchSourceBuilder);
  16.     searchRequest.source(searchSourceBuilder);
  17.     SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
  18.     System.out.println(JSONObject.toJSON(response));
  19. }

仔细观察查询结果,会发现ES查询结果中会带有_score这一项,ES会根据结果匹配程度进行评分。打分是会耗费性能的,如果确认自己的查询不需要评分,就设置查询语句关闭评分:

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "constant_score": {
  5.    "filter": {
  6.     "term": {
  7.      "sect.keyword": {
  8.       "value""张无忌",
  9.       "boost"1.0
  10.      }
  11.     }
  12.    },
  13.    "boost"1.0
  14.   }
  15.  }
  16. }

「Java构建查询语句:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 这样构造的查询条件,将不进行score计算,从而提高查询效率
  3. searchSourceBuilder.query(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("sect.keyword""明教")));

多值查询-terms

多条件查询类似Mysql里的IN查询,例如:

select * from persons where sect in('明教','武当派');

「ES查询语句:」

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "terms": {
  5.    "sect.keyword": [
  6.     "明教",
  7.     "武当派"
  8.    ],
  9.    "boost"1.0
  10.   }
  11.  }
  12. }

「Java实现:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.termsQuery("sect.keyword", Arrays.asList("明教""武当派")));
  4. }

范围查询-range

范围查询,即查询某字段在特定区间的记录。

「SQL:」

select * from pesons where age between 18 and 22;

「ES查询语句:」

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "range": {
  5.    "age": {
  6.     "from"10,
  7.     "to"20,
  8.     "include_lower"true,
  9.     "include_upper"true,
  10.     "boost"1.0
  11.    }
  12.   }
  13.  }
  14. }

「Java构建查询条件:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.rangeQuery("age").gte(10).lte(30));
  4. }

前缀查询-prefix

前缀查询类似于SQL中的模糊查询。

「SQL:」

select * from persons where sect like '武当%';

「ES查询语句:」

  1. {
  2.  "query": {
  3.   "prefix": {
  4.    "sect.keyword": {
  5.     "value""武当",
  6.     "boost"1.0
  7.    }
  8.   }
  9.  }
  10. }

「Java构建查询条件:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.prefixQuery("sect.keyword","武当"));

通配符查询-wildcard

通配符查询,与前缀查询类似,都属于模糊查询的范畴,但通配符显然功能更强。

「SQL:」

select * from persons where name like '张%忌';

「ES查询语句:」

  1. {
  2.  "query": {
  3.   "wildcard": {
  4.    "sect.keyword": {
  5.     "wildcard""张*忌",
  6.     "boost"1.0
  7.    }
  8.   }
  9.  }
  10. }

「Java构建查询条件:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.wildcardQuery("sect.keyword","张*忌"));

复合查询

前面的例子都是单个条件查询,在实际应用中,我们很有可能会过滤多个值或字段。先看一个简单的例子:

select * from persons where sex = '女' and sect = '明教';

这样的多条件等值查询,就要借用到组合过滤器了,其查询语句是:

  1. {
  2.  "query": {
  3.   "bool": {
  4.    "must": [
  5.     {
  6.         "term": {
  7.       "sex": {
  8.        "value""女",
  9.        "boost"1.0
  10.       }
  11.      }
  12.     },
  13.     {
  14.      "term": {
  15.       "sect.keywords": {
  16.        "value""明教",
  17.        "boost"1.0
  18.       }
  19.      }
  20.     }
  21.    ],
  22.    "adjust_pure_negative"true,
  23.    "boost"1.0
  24.   }
  25.  }
  26. }

Java构造查询语句:

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.boolQuery()
  4.         .must(QueryBuilders.termQuery("sex""女"))
  5.         .must(QueryBuilders.termQuery("sect.keyword""明教"))
  6. );

布尔查询

布尔过滤器(bool filter)属于复合过滤器(compound filter)的一种 ,可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合。

19abd66b551e8f9c18d38a1500cd8237.jpeg
布尔(逻辑)组合

bool 过滤器下可以有4种子条件,可以任选其中任意一个或多个。filter是比较特殊的,这里先不说。

  1. {
  2.    "bool" : {
  3.       "must" :     [],
  4.       "should" :   [],
  5.       "must_not" : [],
  6.    }
  7. }
  • **must**:所有的语句都必须匹配,与 ‘=’ 等价。

  • **must_not**:所有的语句都不能匹配,与 ‘!=’ 或 not in 等价。

  • **should**:至少有n个语句要匹配,n由参数控制。

「精度控制:」

所有 must 语句必须匹配,所有 must_not 语句都必须不匹配,但有多少 should 语句应该匹配呢?默认情况下,没有 should 语句是必须匹配的,只有一个例外:那就是当没有 must 语句的时候,至少有一个 should 语句必须匹配。

我们可以通过 minimum_should_match 参数控制需要匹配的 should 语句的数量,它既可以是一个绝对的数字,又可以是个百分比:

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "bool": {
  5.    "must": [
  6.     {
  7.      "term": {
  8.       "sex": {
  9.        "value""女",
  10.        "boost"1.0
  11.       }
  12.      }
  13.     }
  14.    ],
  15.    "should": [
  16.     {
  17.      "term": {
  18.       "address.keyword": {
  19.        "value""峨眉山",
  20.        "boost"1.0
  21.       }
  22.      }
  23.     },
  24.     {
  25.      "term": {
  26.       "sect.keyword": {
  27.        "value""明教",
  28.        "boost"1.0
  29.       }
  30.      }
  31.     }
  32.    ],
  33.    "adjust_pure_negative"true,
  34.    "minimum_should_match""1",
  35.    "boost"1.0
  36.   }
  37.  }
  38. }

「Java构建查询语句:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.boolQuery()
  4.         .must(QueryBuilders.termQuery("sex""女"))
  5.         .should(QueryBuilders.termQuery("address.word""峨眉山"))
  6.         .should(QueryBuilders.termQuery("sect.keyword""明教"))
  7.         .minimumShouldMatch(1)
  8. );

最后,看一个复杂些的例子,将bool的各子句联合使用:

  1. select 
  2.  *
  3. from
  4.  persons
  5. where 
  6.  sex = '女'
  7. and
  8.  age between 30 and 40
  9. and 
  10.  sect != '明教'
  11. and 
  12.  (address = '峨眉山' OR skill = '暗器')

用 Elasticsearch 来表示上面的 SQL 例子:

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "bool": {
  5.    "must": [
  6.     {
  7.      "term": {
  8.       "sex": {
  9.        "value""女",
  10.        "boost"1.0
  11.       }
  12.      }
  13.     },
  14.     {
  15.      "range": {
  16.       "age": {
  17.        "from"30,
  18.        "to"40,
  19.        "include_lower"true,
  20.        "include_upper"true,
  21.        "boost"1.0
  22.       }
  23.      }
  24.     }
  25.    ],
  26.    "must_not": [
  27.     {
  28.      "term": {
  29.       "sect.keyword": {
  30.        "value""明教",
  31.        "boost"1.0
  32.       }
  33.      }
  34.     }
  35.    ],
  36.    "should": [
  37.     {
  38.      "term": {
  39.       "address.keyword": {
  40.        "value""峨眉山",
  41.        "boost"1.0
  42.       }
  43.      }
  44.     },
  45.     {
  46.      "term": {
  47.       "skill.keyword": {
  48.        "value""暗器",
  49.        "boost"1.0
  50.       }
  51.      }
  52.     }
  53.    ],
  54.    "adjust_pure_negative"true,
  55.    "minimum_should_match""1",
  56.    "boost"1.0
  57.   }
  58.  }
  59. }

「用Java构建这个查询条件:」

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
  4.         .must(QueryBuilders.termQuery("sex""女"))
  5.         .must(QueryBuilders.rangeQuery("age").gte(30).lte(40))
  6.         .mustNot(QueryBuilders.termQuery("sect.keyword""明教"))
  7.         .should(QueryBuilders.termQuery("address.keyword""峨眉山"))
  8.         .should(QueryBuilders.rangeQuery("power.keyword").gte(50).lte(80))
  9.         .minimumShouldMatch(1);  // 设置should至少需要满足几个条件
  10. // 将BoolQueryBuilder构建到SearchSourceBuilder中
  11. searchSourceBuilder.query(boolQueryBuilder);

Filter查询

query和filter的区别:query查询的时候,会先比较查询条件,然后计算分值,最后返回文档结果;而filter是先判断是否满足查询条件,如果不满足会缓存查询结果(记录该文档不满足结果),满足的话,就直接缓存结果,「filter不会对结果进行评分,能够提高查询效率」

filter的使用方式比较多样,下面用几个例子演示一下。

「方式一,单独使用:」

  1. {
  2.  "query": {
  3.   "bool": {
  4.    "filter": [
  5.     {
  6.      "term": {
  7.       "sex": {
  8.        "value""男",
  9.        "boost"1.0
  10.       }
  11.      }
  12.     }
  13.    ],
  14.    "adjust_pure_negative"true,
  15.    "boost"1.0
  16.   }
  17.  }
  18. }

单独使用时,filter与must基本一样,不同的是「filter不计算评分,效率更高」

Java构建查询语句:

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.boolQuery()
  4.         .filter(QueryBuilders.termQuery("sex""男"))
  5. );

「方式二,和must、must_not同级,相当于子查询:」

select * from (select * from persons where sect = '明教')) a where sex = '女';

ES查询语句:

  1. {
  2.  "query": {
  3.   "bool": {
  4.    "must": [
  5.     {
  6.      "term": {
  7.       "sect.keyword": {
  8.        "value""明教",
  9.        "boost"1.0
  10.       }
  11.      }
  12.     }
  13.    ],
  14.    "filter": [
  15.     {
  16.      "term": {
  17.       "sex": {
  18.        "value""女",
  19.        "boost"1.0
  20.       }
  21.      }
  22.     }
  23.    ],
  24.    "adjust_pure_negative"true,
  25.    "boost"1.0
  26.   }
  27.  }
  28. }

Java:

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.boolQuery()
  4.         .must(QueryBuilders.termQuery("sect.keyword""明教"))
  5.         .filter(QueryBuilders.termQuery("sex""女"))
  6. );

「方式三,将must、must_not置于filter下,这种方式是最常用的:」

  1. {
  2.  "query": {
  3.   "bool": {
  4.    "filter": [
  5.     {
  6.      "bool": {
  7.       "must": [
  8.        {
  9.         "term": {
  10.          "sect.keyword": {
  11.           "value""明教",
  12.           "boost"1.0
  13.          }
  14.         }
  15.        },
  16.        {
  17.         "range": {
  18.          "age": {
  19.           "from"20,
  20.           "to"35,
  21.           "include_lower"true,
  22.           "include_upper"true,
  23.           "boost"1.0
  24.          }
  25.         }
  26.        }
  27.       ],
  28.       "must_not": [
  29.        {
  30.         "term": {
  31.          "sex.keyword": {
  32.           "value""女",
  33.           "boost"1.0
  34.          }
  35.         }
  36.        }
  37.       ],
  38.       "adjust_pure_negative"true,
  39.       "boost"1.0
  40.      }
  41.     }
  42.    ],
  43.    "adjust_pure_negative"true,
  44.    "boost"1.0
  45.   }
  46.  }
  47. }

Java:

  1. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  2. // 构建查询语句
  3. searchSourceBuilder.query(QueryBuilders.boolQuery()
  4.         .filter(QueryBuilders.boolQuery()
  5.                 .must(QueryBuilders.termQuery("sect.keyword""明教"))
  6.                 .must(QueryBuilders.rangeQuery("age").gte(20).lte(35))
  7.                 .mustNot(QueryBuilders.termQuery("sex.keyword""女")))
  8. );

聚合查询

接下来,我们将用一些案例演示ES聚合查询。

最值、平均值、求和

「案例:查询最大年龄、最小年龄、平均年龄。」

「SQL:」

select max(age) from persons;

「ES:」

  1. GET /person/_search
  2. {
  3.  "aggregations": {
  4.   "max_age": {
  5.    "max": {
  6.     "field""age"
  7.    }
  8.   }
  9.  }
  10. }

「Java:」

  1. @Autowired
  2. private RestHighLevelClient client;
  3. @Test
  4. public void maxQueryTest() throws IOException {
  5.  // 聚合查询条件
  6.     AggregationBuilder aggBuilder = AggregationBuilders.max("max_age").field("age");
  7.     SearchRequest searchRequest = new SearchRequest("person");
  8.     SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  9.     // 将聚合查询条件构建到SearchSourceBuilder中
  10.     searchSourceBuilder.aggregation(aggBuilder);
  11.     System.out.println("searchSourceBuilder----->" + searchSourceBuilder);
  12.     searchRequest.source(searchSourceBuilder);
  13.     // 执行查询,获取SearchResponse
  14.     SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
  15.     System.out.println(JSONObject.toJSON(response));
  16. }

使用聚合查询,结果中默认只会返回10条文档数据(当然我们关心的是聚合的结果,而非文档)。返回多少条数据可以自主控制:

  1. GET /person/_search
  2. {
  3.  "size"20,
  4.  "aggregations": {
  5.   "max_age": {
  6.    "max": {
  7.     "field""age"
  8.    }
  9.   }
  10.  }
  11. }

而Java中只需增加下面一条语句即可:

searchSourceBuilder.size(20);

与max类似,其他统计查询也很简单:

  1. AggregationBuilder minBuilder = AggregationBuilders.min("min_age").field("age");
  2. AggregationBuilder avgBuilder = AggregationBuilders.avg("min_age").field("age");
  3. AggregationBuilder sumBuilder = AggregationBuilders.sum("min_age").field("age");
  4. AggregationBuilder countBuilder = AggregationBuilders.count("min_age").field("age");

去重查询

「案例:查询一共有多少个门派。」

「SQL:」

select count(distinct sect) from persons;

ES:

  1. {
  2.  "aggregations": {
  3.   "sect_count": {
  4.    "cardinality": {
  5.     "field""sect.keyword"
  6.    }
  7.   }
  8.  }
  9. }

Java:

  1. @Test
  2. public void cardinalityQueryTest() throws IOException {
  3.  // 创建某个索引的request
  4.     SearchRequest searchRequest = new SearchRequest("person");
  5.     // 查询条件
  6.     SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  7.     // 聚合查询
  8.     AggregationBuilder aggBuilder = AggregationBuilders.cardinality("sect_count").field("sect.keyword");
  9.     searchSourceBuilder.size(0);
  10.     // 将聚合查询构建到查询条件中
  11.     searchSourceBuilder.aggregation(aggBuilder);
  12.     System.out.println("searchSourceBuilder----->" + searchSourceBuilder);
  13.     searchRequest.source(searchSourceBuilder);
  14.     // 执行查询,获取结果
  15.     SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
  16.     System.out.println(JSONObject.toJSON(response));
  17. }

分组聚合

单条件分组

「案例:查询每个门派的人数」

「SQL:」

select sect,count(id) from mytest.persons group by sect;

「ES:」

  1. {
  2.  "size"0,
  3.  "aggregations": {
  4.   "sect_count": {
  5.    "terms": {
  6.     "field""sect.keyword",
  7.     "size"10,
  8.     "min_doc_count"1,
  9.     "shard_min_doc_count"0,
  10.     "show_term_doc_count_error"false,
  11.     "order": [
  12.      {
  13.       "_count""desc"
  14.      },
  15.      {
  16.       "_key""asc"
  17.      }
  18.     ]
  19.    }
  20.   }
  21.  }
  22. }

「Java:」

  1. SearchRequest searchRequest = new SearchRequest("person");
  2. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  3. searchSourceBuilder.size(0);
  4. // 按sect分组
  5. AggregationBuilder aggBuilder = AggregationBuilders.terms("sect_count").field("sect.keyword");
  6. searchSourceBuilder.aggregation(aggBuilder);

多条件分组

「案例:查询每个门派各有多少个男性和女性」

「SQL:」

select sect,sex,count(id) from mytest.persons group by sect,sex;

「ES:」

  1. {
  2.  "aggregations": {
  3.   "sect_count": {
  4.    "terms": {
  5.     "field""sect.keyword",
  6.     "size"10
  7.    },
  8.    "aggregations": {
  9.     "sex_count": {
  10.      "terms": {
  11.       "field""sex.keyword",
  12.       "size"10
  13.      }
  14.     }
  15.    }
  16.   }
  17.  }
  18. }

过滤聚合

前面所有聚合的例子请求都省略了 query ,整个请求只不过是一个聚合。这意味着我们对全部数据进行了聚合,但现实应用中,我们常常对特定范围的数据进行聚合,例如下例。

「案例:查询明教中的最大年龄。」 这涉及到聚合与条件查询一起使用。

「SQL:」

select max(age) from mytest.persons where sect = '明教';

「ES:」

  1. GET /person/_search
  2. {
  3.  "query": {
  4.   "term": {
  5.    "sect.keyword": {
  6.     "value""明教",
  7.     "boost"1.0
  8.    }
  9.   }
  10.  },
  11.  "aggregations": {
  12.   "max_age": {
  13.    "max": {
  14.     "field""age"
  15.    }
  16.   }
  17.  }
  18. }

「Java:」

  1. SearchRequest searchRequest = new SearchRequest("person");
  2. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  3. // 聚合查询条件
  4. AggregationBuilder maxBuilder = AggregationBuilders.max("max_age").field("age");
  5. // 等值查询
  6. searchSourceBuilder.query(QueryBuilders.termQuery("sect.keyword""明教"));
  7. searchSourceBuilder.aggregation(maxBuilder);

另外还有一些更复杂的查询例子。

「案例:查询0-20,21-40,41-60,61以上的各有多少人。」

SQL:

  1. select 
  2.  sum(case when age<=20 then 1 else 0 end) ageGroup1,
  3.  sum(case when age >20 and age <=40 then 1 else 0 end) ageGroup2,
  4.  sum(case when age >40 and age <=60 then 1 else 0 end) ageGroup3,
  5.  sum(case when age >60 and age <=200 then 1 else 0 end) ageGroup4
  6. from 
  7.  mytest.persons;

ES:

  1. {
  2.  "size"0,
  3.  "aggregations": {
  4.   "age_avg": {
  5.    "range": {
  6.     "field""age",
  7.     "ranges": [
  8.      {
  9.       "from"0.0,
  10.       "to"20.0
  11.      },
  12.      {
  13.       "from"21.0,
  14.       "to"40.0
  15.      },
  16.      {
  17.       "from"41.0,
  18.       "to"60.0
  19.      },
  20.      {
  21.       "from"61.0,
  22.       "to"200.0
  23.      }
  24.     ],
  25.     "keyed"false
  26.    }
  27.   }
  28.  }
  29. }

Java:

查询结果:

  1. "aggregations" : {
  2.   "age_avg" : {
  3.     "buckets" : [
  4.       {
  5.         "key" : "0.0-20.0",
  6.         "from" : 0.0,
  7.         "to" : 20.0,
  8.         "doc_count" : 3
  9.       },
  10.       {
  11.         "key" : "21.0-40.0",
  12.         "from" : 21.0,
  13.         "to" : 40.0,
  14.         "doc_count" : 13
  15.       },
  16.       {
  17.         "key" : "41.0-60.0",
  18.         "from" : 41.0,
  19.         "to" : 60.0,
  20.         "doc_count" : 4
  21.       },
  22.       {
  23.         "key" : "61.0-200.0",
  24.         "from" : 61.0,
  25.         "to" : 200.0,
  26.         "doc_count" : 1
  27.       }
  28.     ]
  29.   }
  30. }

以上是ElasticSearch查询的全部内容,丰富详实,堪比操作手册,强烈建议收藏!

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

正文结束

推荐阅读 ↓↓↓

1.对领域的认知比会写代码更重要

2.从零开始搭建创业公司后台技术栈

3.程序员一般可以从什么平台接私活?

4.流程引擎的架构设计

5.为什么国内 996 干不过国外的 955呢?

6.中国的铁路订票系统在世界上属于什么水平?                        

7.15张图看懂瞎忙和高效的区别!

6869ccf6f81bcfaefe207527472e4eb2.gif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/68192
推荐阅读
相关标签
  

闽ICP备14008679号