ElasticSearch查询工具类分享

文章目录

      • [1. sql转ES工具](#1. sql转ES工具)
      • [2. Kibana VS Postman /ApiPost](#2. Kibana VS Postman /ApiPost)
      • [3 .es json 转java](#3 .es json 转java)
      • [4. ElasticSearch查询工具类 esHelper](#4. ElasticSearch查询工具类 esHelper)
      • [5. 在IDE 控制台看到效果如图](#5. 在IDE 控制台看到效果如图)

前言

最近需要对ES数据进行分析和查询, 之前因为在入门ES时没有好好做笔记和整理 。

1. sql转ES工具

https://printlove.cn/tools/sql2es/

可以把基本的sql查询条件 转成es查询条件 , 适当的使用的可以增加自己写es的效果

2. Kibana VS Postman /ApiPost

一般在写java ES查询时, 习惯先用 kibana 或者postman 构建ES 查询json,

其实两个工具各有优势,

  • kibana 的优势是具备词语提示 ,只能请求kibana绑定的es地址
  • postman的优势是可以注释json , 请求多个ES地址( 比如开发、测试环境)

两个工具都还不错, 个人偏向于postman 一点,因为注释 调试起来比较方便。

3 .es json 转java

按照json的结构,可以轻松的写出java代码 ,根据query key的名称,使用QueryBuilders 构建 , 根据aggs (aggregations 的简称) key的名称,使用AggregationBuilders构建 , 示例如下

  • 示例json
json 复制代码
{
  "query": {
    "bool": {
      "must": [
        {
          // 时间范围
          "range": {
            "create_at": {
              "from": "2023-09-01",
              "to": "2023-09-12"
            }
          }
        },
          // 分值
        {
          "exists": {
            "field": "score"
          }
        }
      ]
    }
  },
  "aggs": {
    "name_group": {
      // 根据name分组 ,根据每组最大score排序 
      "terms": {
        "field": "name",
        "order": {
          "max_score": "desc"
        }
      },
      "aggs": {
        // 最大分值
        "max_score": {
          "max": {
            "field": "score"
          }
        }
      }
    }
  }
}
  • java示例
java 复制代码
          // query --> java
        BoolQueryBuilder conditionsBoolQuery =QueryBuilders.boolQuery()
                .must(QueryBuilders.rangeQuery("create_at").from(query.getStartDateTimestamp()).to(query.getEndDateTimestamp()))
                .must(QueryBuilders.existsQuery("location.county_code"));

        // agg -->java
        AggregationBuilder aggGroup = AggregationBuilders
                .terms("name_group").field("name").order(BucketOrder.aggregation("max_score", false))
                .subAggregation(AggregationBuilders.max("max_score").field("score"));

创建请求即可

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(conditionsBoolQuery).aggregation(aggGroup);

4. ElasticSearch查询工具类 esHelper

当使用RestHighLevelClient 进行es请求时 , 关心转换 的searchSourceBuilder 入参对不对 ? searchResponse 出参对不对? 那么需要对es对象进行json序列化 。

当你查看es源码时 ,大部分es对象都是继承自ToXContent 对象, 而XContentBuilder 支持ToXContent 对象的自定义转换 。所以封装esHelper 方便查看调用RestHighLevelClient 入参和出参。

java 复制代码
@Slf4j
@Component
public class EsHelper {

    @Resource
    private RestHighLevelClient client;

    private ObjectMapper mapper;

    @Value("${eshelper.debug:false}")
    private boolean debug;

    @PostConstruct
    public void init() {
        mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        // 下划线转驼峰
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    }

    /**
     * 获取查询数量
     *
     * @param queryBuilder 查询器
     * @param indexes      索引目录
     */
    public long count(QueryBuilder queryBuilder, String... indexes) throws IOException {
        CountRequest countRequest = new CountRequest(indexes);
        countRequest.query(queryBuilder);
        client.count(countRequest, RequestOptions.DEFAULT);
        CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
        return countResponse.getCount();
    }


    /**
     * 获取查询列表 List<T>
     */
    public <T> List<T> listHits(Class<T> entityClass, SearchSourceBuilder sourceBuilder, String... indexes) throws IOException {
        return listHits(mapper.getTypeFactory().constructType(entityClass), sourceBuilder, indexes);
    }

    /**
     * 获取查询列表 List<Map<String, Object>>
     */
    public List<Map<String, Object>> listHits(SearchSourceBuilder sourceBuilder, String... indexes) throws IOException {
        return listHits(mapper.getTypeFactory().constructParametricType(Map.class, String.class, Object.class), sourceBuilder, indexes);

    }

    /**
     * 从Hits 获取结果
     *
     * @param javaType      动态java类型
     * @param sourceBuilder 查询构建器
     * @param indexes       引目录
     * @throws IOException
     */
    private <T> List<T> listHits(JavaType javaType, SearchSourceBuilder sourceBuilder, String... indexes) throws IOException {
        Map<String, List<T>> resultMap = new HashMap<>();
        responseFilter(searchResponse -> {
            SearchHit[] hits = searchResponse.getHits().getHits();
            resultMap.put("result", hits2List(javaType, hits));
        }, sourceBuilder, indexes);
        return resultMap.getOrDefault("result", null);
    }


    /**
     * 转换hits为java List对象
     */
    public <T> List<T> hits2List(JavaType javaType, SearchHit[] hits) {
        List<T> resultList = new ArrayList<>();
        for (SearchHit hit : hits) {
            try {
                Map<String, Object> source = hit.getSourceAsMap();
                source.put("id", hit.getId());
                T result = mapper.readValue(mapper.writeValueAsString(source), javaType);
                resultList.add(result);
            } catch (Exception e) {
                log.error("hit 转换对象异常!", e);
            }
        }
        return resultList;
    }


    public <T> T toBean(String str, Class<T> entityClass) throws JsonProcessingException {
        return mapper.readValue(str, mapper.constructType(entityClass));
    }

    /**
     * @param responseConsumer response消费者
     * @param sourceBuilder    查询构建器
     * @param indexes          索引
     */
    public void responseFilter(ResponseConsumer responseConsumer, SearchSourceBuilder sourceBuilder, String... indexes) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexes);
        searchRequest.source(sourceBuilder);
        if (debug) {
            log.info("ES Request json==>{}", toStringEsObject(sourceBuilder, true));
        }
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        if (debug) {
            log.info("ES Response json==>{} ", toStringEsObject(searchResponse, false));
        }
        responseConsumer.accept(searchResponse);
    }


    /**
     * 转换es对象 为json文本
     */
    protected String toStringEsObject(ToXContent xContent, boolean prettyPrint) {
        XContentBuilder xContentBuilder = null;
        try {
            xContentBuilder = XContentBuilder.builder(XContentType.JSON.xContent());
            xContent.toXContent(xContentBuilder, ToXContent.EMPTY_PARAMS);
            return XContentHelper.convertToJson(BytesReference.bytes(xContentBuilder), prettyPrint, prettyPrint, XContentType.JSON);
        } catch (IOException e) {
            log.error("ES对象转json字符串失败: !!!!", e);
        }
        return null;
    }


    @FunctionalInterface
    public interface ResponseConsumer {
        public void accept(SearchResponse searchResponse);
    }
}

5. 在IDE 控制台看到效果如图

ES Request json 输出SearchRequest json ,可以复制json对象至postman或 kibana 查看效果是不是正确

ES Response json输出SearchResponse json ,可以根据json 对象检查结果是否正确

相关推荐
小鑫记得努力4 分钟前
Java类和对象(下篇)
java
binishuaio8 分钟前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE10 分钟前
【Java SE】StringBuffer
java·开发语言
老友@10 分钟前
aspose如何获取PPT放映页“切换”的“持续时间”值
java·powerpoint·aspose
wrx繁星点点25 分钟前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
Upaaui28 分钟前
Aop+自定义注解实现数据字典映射
java
zzzgd81628 分钟前
easyexcel实现自定义的策略类, 最后追加错误提示列, 自适应列宽,自动合并重复单元格, 美化表头
java·excel·表格·easyexcel·导入导出
友善的鸡蛋29 分钟前
解决:使用EasyExcel导入Excel模板时出现数据导入不进去的问题
java·easyexcel·excel导入
星沁城30 分钟前
240. 搜索二维矩阵 II
java·线性代数·算法·leetcode·矩阵
NoneCoder42 分钟前
Java企业级开发系列(1)
java·开发语言·spring·团队开发·开发