SpringBoot 整合 Elasticsearch 基本查询详解

官网

提示:建议先熟悉利用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常规用法总结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值