官网
提示:建议先熟悉利用kibana查询ES的语句,那样写起来更容易,也方便问题排查。
参考官方AP文档:elasticsearch 官网
文章目录
一、引入依赖
提示:本文章使用的是 Elasticsearch 提供的高级客户端 RestHighLevelClient的查询方法
maven 引入高级客户端依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</dependency>
二、查询接口的步骤
ES查询几个必须的对象
1. 普通查询的条件容器:BoolQueryBuilder 多条件查询容器
// 普通的QueryBuilders查询的boolQuery()方法,变成多条件查询
BoolQueryBuilder builder=QueryBuilders.boolQuery();
// 比如时间条件:
// boolQueryBuilder.filter(QueryBuilders.rangeQuery(EsConstant.ES_INSERT_TIME).gte(twoHoursInfo.get(0)).lte(twoHoursInfo.get(1)));
2. 分组查询的条件容器:AggregationBuilder
AggregationBuilder field = AggregationBuilders.terms(AGG_NAME).field(Constant.ES_TITLE);
3. 普通的分组查询
提示:如果要分组的字段是text类型,需要转成key类型才能分组,直接字段.key就行。在分组后直接.subAggregation(。。。。。) 可以添加子分组。
查询条件总容器:SearchSourceBuilder
// 比如:searchSourceBuilder.query(boolQueryBuilder).aggregation(termsAggregationBuilder);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
4. 创建查询容器:SearchRequest
// 方式一:
SearchRequest searchRequest = new SearchRequest(INDEX_NAME).source(searchSourceBuilder);
// 方式二:
SearchRequest searchRequest = new SearchRequest().indices(INDEX_NAME).source(searchSourceBuilder);
5. 放入提前配置好的客户端:
SearchResponse是返回值的容器
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
查询步骤
一个查询步骤如下
1、创建 SearchRequest搜索请求
创建 SearchRequest 搜索请求,如果不带参数,表示查询所有索引
2、创建 SearchSourceBuilder条件构造
创建 SearchSourceBuilder条件构造,构建搜索的条件。
添加大部分查询参数到 SearchSourceBuilder,还可以接收 QueryBuilders(BoolQueryBuilder)构建的查询参数。
3、将 SearchSourceBuilder 添加到 SearchRequest中
4、执行查询
5、解析查询结果
三、普通查询
1. 全量查询
代码如下(示例):
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void testMatchAll() throws IOException {
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchAllQueryBuilder qb = QueryBuilders.matchAllQuery();
searchSourceBuilder.query(qb);
//SearchRequest搜索请求,并指定要查询的索引
searchRequest.source(searchSourceBuilder);
System.out.println(searchRequest.source().toString());
try {
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach(x -> {
System.out.println("查询结果 --> " + x.getSourceAsString());
});
} catch (IOException e) {
}
}
2. 分页查询
size 关键字:指定查询结果中返回指定条数。 默认返回值10条。
from 关键字:用来指定起始返回位置,和size关键字连用可实现分页效果
@Test
public void testMatchAllPage() throws IOException {
RestHighLevelClient restHighLevelClient = ESUtil.getRestHighLevelClient();
//1.创建 SearchRequest搜索请求
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("db_idx4");//指定要查询的索引
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery());
//设置分页
searchSourceBuilder.from(1);
searchSourceBuilder.size(5);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//5.解析查询结果
System.out.println("花费的时长:" + searchResponse.getTook());
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(p -> System.out.println("文档原生信息:" + p.getSourceAsString()));
}
3. 数据排序
@Test
public void testSortByAge() throws IOException {
RestHighLevelClient restHighLevelClient = ESUtil.getRestHighLevelClient();
//1.创建 SearchRequest搜索请求
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("db_idx4");//指定要查询的索引
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery());
//年龄倒序
searchSourceBuilder.sort("age", SortOrder.DESC);
searchSourceBuilder.sort("id", SortOrder.DESC);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//5.解析查询结果
System.out.println("花费的时长:" + searchResponse.getTook());
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(p -> System.out.println("文档原生信息:" + p.getSourceAsString()));
}
4. 查询指定字段
@Test
public void testSource() throws IOException {
RestHighLevelClient restHighLevelClient = ESUtil.getRestHighLevelClient();
//1.创建 SearchRequest搜索请求
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("db_idx4");//指定要查询的索引
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery());
//指定需要返回或者排除的字段
String[] includes = {"id", "name"};
String[] excludes = {};
searchSourceBuilder.fetchSource(includes, excludes);
//3.将 SearchSourceBuilder 添加到 SearchRequest中
searchRequest.source(searchSourceBuilder);
//4.执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//5.解析查询结果
System.out.println("花费的时长:" + searchResponse.getTook());
SearchHits hits = searchResponse.getHits();
System.out.println("符合条件的总文档数量:" + hits.getTotalHits().value);
hits.forEach(p -> System.out.println("文档原生信息:" + p.getSourceAsString()));
}
5. 数据过滤
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void test() {
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 查询条件
BoolQueryBuilder qb = QueryBuilders.boolQuery();
// 单个条件过滤
qb.filter(QueryBuilders.termQuery("userId", 10030));
// 多个条件过滤
qb.filter(QueryBuilders.termsQuery("ancestors", new String[] {"150","158"}));
// 模糊查询
qb.filter(QueryBuilders.matchPhraseQuery("content", "【腾讯科技】"));
// 大于、小于和子查询(时间查询。查询今天的数据)
RangeQueryBuilder range = QueryBuilders.rangeQuery("date");
range.gte(DateUtils.getTodayDate().getTime());
range.lt(DateUtils.getNowDate().getTime());
qb.filter(range);
// 或查询
BoolQueryBuilder mobileQb = QueryBuilders.boolQuery();
mobileQb.should(QueryBuilders.termQuery("sender", "18711112542"));
mobileQb.should(QueryBuilders.termQuery("receiver", "18711112542"));
qb.filter(mobileQb);
searchSourceBuilder.query(qb);
// 也可以直接创建
// SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
// .query(qb)
// .from(1)
// .size(10)
// .fetchSource(INCLUDE_FIELDS, null);
//SearchRequest搜索请求,并指定要查询的索引
searchRequest.source(searchSourceBuilder);
try {
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach(x -> {
System.out.println(x.getSourceAsString());
});
} catch (IOException e) {
}
}
四、聚合查询
1. Aggregation
Aggregation 一些数学运算,可以对文档字段进行统计分析。
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void test() {
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//最大值、最小值和平均值
MaxAggregationBuilder maxAggregationBuilder = AggregationBuilders.max("maxStatus").field("status");
MinAggregationBuilder minAggregationBuilder = AggregationBuilders.min("minStatus").field("status");
AvgAggregationBuilder avgAggregationBuilder = AggregationBuilders.avg("avgStatus").field("status");
searchSourceBuilder.aggregation(maxAggregationBuilder);
searchSourceBuilder.aggregation(minAggregationBuilder);
searchSourceBuilder.aggregation(avgAggregationBuilder);
//SearchRequest搜索请求,并指定要查询的索引
searchRequest.source(searchSourceBuilder);
System.out.println(searchRequest.source().toString());
try {
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
ParsedMax maxSalary = aggregations.get("maxStatus");
ParsedMin minSalary = aggregations.get("minStatus");
ParsedAvg avgSalary = aggregations.get("avgStatus");
System.out.println("maxSalary:" + maxSalary);
System.out.println("最大" + maxSalary.getValue());
System.out.println("最小" + minSalary.getValue());
System.out.println("平均" + avgSalary.getValue());
} catch (IOException e) {
}
}
2. 分组统计
分组统计中还可以嵌套分组统计,实现多字段分组
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void test() {
//1.创建 SearchRequest搜索请求,并指定要查询的索引
SearchRequest searchRequest = new SearchRequest(INDEX_NAME);
//2.创建 SearchSourceBuilder条件构造。
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//去重统计
CardinalityAggregationBuilder typeDistinctBuilder = AggregationBuilders.cardinality("typeDistinct").field("type");
//统计数量
ValueCountAggregationBuilder userIdCountBuilder = AggregationBuilders.count("userIdCount").field("userId");
// 分组
TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("userIdGroup").field("userId");
termsAggregationBuilder.subAggregation(typeDistinctBuilder);
termsAggregationBuilder.subAggregation(userIdCountBuilder);
searchSourceBuilder.aggregation(termsAggregationBuilder);
//SearchRequest搜索请求,并指定要查询的索引
searchRequest.source(searchSourceBuilder);
System.out.println(searchRequest.source().toString());
try {
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
ParsedStringTerms userIdGroup = aggregations.get("userIdGroup");
List<? extends Terms.Bucket> buckets = userIdGroup.getBuckets();
buckets.forEach(x -> {
// 源数据
String keyAsString = x.getKeyAsString();
long typeDistinctCount = ((ParsedCardinality) x.getAggregations().get("typeDistinct")).getValue();
long userIdCount = ((ParsedValueCount) x.getAggregations().get("userIdCount")).getValue();
});
} catch (IOException e) {
}
}
总结
写好 ES语句很关键,然后通过 客户端编写出来就简单了。
创建 SearchSourceBuilder条件构造,构建搜索的条件很重要,根据业务构造r条件变化多端。
不管是 Query DSL还是 聚合操作,通过 ES语句的结果来编写 SearchResponse的解析查询结果就很容易了,注意里边的类型。
参考文章
Java 操作RestHighLevelClient查询详解
ElasticSearch结合springboot常规用法总结