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

相关推荐
星河梦瑾26 分钟前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富29 分钟前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想31 分钟前
JMeter 使用详解
java·jmeter
言、雲34 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇41 分钟前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
Yvemil71 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。1 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴2 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
爱上语文2 小时前
宠物管理系统:Dao层
java·开发语言·宠物
成长的小牛2332 小时前
es使用knn向量检索中numCandidates和k应该如何配比更合适
大数据·elasticsearch·搜索引擎