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常规用法总结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SpringBoot整合Elasticsearch常用API主要包括以下几个方面: 1. 配置Elasticsearch信息 首先需要在application.yml中配置Elasticsearch的连接信息: ``` spring: data: elasticsearch: cluster-name: elasticsearch cluster-nodes: 127.0.0.1:9300 ``` 2. 创建ElasticsearchRepository 在SpringBoot中,可以通过ElasticsearchRepository来访问Elasticsearch,只需要继承该接口即可。 ``` public interface UserRepository extends ElasticsearchRepository<User, Long> { } ``` 其中,User是实体类,Long是主键类型。 3. 创建实体类 创建实体类,使用注解来映射Elasticsearch中的索引和字段。 ``` @Document(indexName = "user", type = "_doc") public class User { @Id private Long id; @Field(type = FieldType.Keyword) private String name; @Field(type = FieldType.Integer) private Integer age; // getter and setter } ``` 4. 增删改查 通过ElasticsearchRepository提供的方法,可以实现增删改查的操作。如下: ``` @Autowired UserRepository userRepository; // 新增 userRepository.save(user); // 删除 userRepository.deleteById(id); // 修改 userRepository.save(user); // 查询 Optional<User> optional = userRepository.findById(id); ``` 5. 搜索 Elasticsearch提供了丰富的搜索API,可以通过QueryBuilder来构建查询条件,通过SearchRequest来执行搜索操作。如下: ``` @Autowired RestHighLevelClient restHighLevelClient; // 构建查询条件 QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "张三"); // 构建SearchRequest SearchRequest searchRequest = new SearchRequest("user"); searchRequest.types("_doc"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(queryBuilder); searchRequest.source(searchSourceBuilder); // 执行搜索 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // 处理搜索结果 SearchHits hits = searchResponse.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); User user = JSON.parseObject(sourceAsString, User.class); System.out.println(user); } ``` 以上就是SpringBoot整合Elasticsearch常用API的介绍。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值