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 对象检查结果是否正确

相关推荐
Elastic 中国社区官方博客14 分钟前
使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
大数据·人工智能·elasticsearch·搜索引擎·全文检索
极客先躯30 分钟前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略
alfiy1 小时前
Elasticsearch学习笔记(四) Elasticsearch集群安全配置一
笔记·学习·elasticsearch
夜月行者1 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
潘多编程1 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
_阿伟_1 小时前
SpringMVC
java·spring
代码在改了2 小时前
springboot厨房达人美食分享平台(源码+文档+调试+答疑)
java·spring boot
alfiy2 小时前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
猿java2 小时前
使用 Kafka面临的挑战
java·后端·kafka