• ES初使用记录——写入与查询数据


    本周接到一个任务:定时统计订单表中的数据,将异常订单挑出来,放入ES中供统计页面从总数点击跳转过去进行列表展示。

    一、配置ES

    配置maven,注入template

    @Resource

    private ElasticsearchTemplate elasticsearchTemplate;

    二、构建实体

    其实就是实体类,一般是将业务实体中的部分字段写入ES。

    构建IndexQuery(),设置ES的实体类,数据 类型 _doc、索引名

    1. package org.springblade.chargingpile.es.data;
    2. import com.fasterxml.jackson.annotation.JsonFormat;
    3. import io.swagger.annotations.ApiModelProperty;
    4. import lombok.Data;
    5. import org.springframework.data.elasticsearch.annotations.DateFormat;
    6. import org.springframework.data.elasticsearch.annotations.Document;
    7. import org.springframework.data.elasticsearch.annotations.Field;
    8. import org.springframework.data.elasticsearch.annotations.FieldType;
    9. import java.io.Serializable;
    10. import java.util.Date;
    11. /**
    12. * 异常订单明细信息
    13. *
    14. * @date 2022/11/9
    15. */
    16. @Data
    17. @Document(indexName = "charging_order_exception", type = "_doc")
    18. public class OrderExceptionES implements Serializable {
    19. @ApiModelProperty("订单编号")
    20. @Field(type = FieldType.Text)
    21. private Long id;
    22. @ApiModelProperty("充电桩编码")
    23. @Field(type = FieldType.Text)
    24. private String pileSn;
    25. @ApiModelProperty("充电枪id")
    26. @Field(type = FieldType.Text)
    27. private Long gunId;
    28. @ApiModelProperty("枪口")
    29. @Field(type = FieldType.Text)
    30. private Integer gunPort;
    31. @ApiModelProperty("结束时间")
    32. @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
    33. @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    34. private Date endDate;
    35. @ApiModelProperty("城市代码")
    36. @Field(type = FieldType.Text)
    37. private Long cityCode;
    38. @ApiModelProperty("场站的id")
    39. @Field(type = FieldType.Text)
    40. private Long stationId;
    41. @ApiModelProperty("启动失败次数")
    42. @Field(type = FieldType.Text)
    43. private Integer isBootFailure;
    44. @ApiModelProperty("异常跳枪次数")
    45. @Field(type = FieldType.Text)
    46. private Integer isGunFailure;
    47. @ApiModelProperty("结束原因编码")
    48. @Field(type = FieldType.Text)
    49. private String endReason;
    50. @ApiModelProperty("开始时间")
    51. @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
    52. @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    53. private Date startDate;
    54. }

    三、向ES写入数据

    其实这里是两个步骤,ES可以用MySQL来类比,先创建索引(MySQL中的表)再写入数据。

    如下方法可以将单个实体类数据写入ES

    1. @Resource
    2. private ElasticsearchTemplate elasticsearchTemplate;
    3. @Override
    4. public String saveChargingWarnDetailES(ChargingWarnDetailES chargingWarnDetailES) {
    5. //构建插入数据
    6. IndexQuery indexQuery = new IndexQuery();
    7. //插入的实体类
    8. indexQuery.setObject(chargingWarnDetailES);
    9. //索引
    10. indexQuery.setIndexName(WarnConstants.WARN_ES_INDEX);
    11. //类型
    12. indexQuery.setType("_doc");
    13. String index = StringUtils.EMPTY;
    14. try {
    15. // 保存数据
    16. index = elasticsearchTemplate.index(indexQuery);
    17. } catch (Exception e) {
    18. e.printStackTrace();
    19. }
    20. return index;
    21. }

    四、从ES查询数据

    这个步骤问题是比较多的,记录一下。

    通过ES查询的字段有:充电场站ID、充电枪ID、时间范围、是否异常订单

    同时需要根据时间,也就是ID倒序排列,因为ID是根据时间递增的。

    1、构建QueryBuilder,这里用到的是BoolQueryBuilder

            这个BoolQueryBuilder适用于这个场景,是最基本的查询类似于mysql的where条件,条件执行的时候只有true和false这两种结果。must 就类似于 查询条件拼接的 and 字段。

            这里用到的ES时间范围查询,统计从开始到结束时间的订单。用到了rangeQuery("要查询的字段").from("开始时间").to("结束时间”),需要注意的是,这里的要查询的字段要加后缀.keyword,不然查询不出来,时间范围格式和存入时对应,可以用string,因为实体类日期字段标注了格式的

    2、构建SearchSourceBuilder

           这里用到的场景是分页、排序。

            ES的查询分页网上主要有三种方法,主要有from..size的浅分页,滑动分页Scroll等。我这里用到的是最简单的浅分页。from参数传入查询数据截取的开始范围,传入前端传过来的(页号-1)*页大小。from + size数值不能超过10000,且是ES查询全部数据再截取得到的效率差了一点点,浅分页就是有这些缺陷。分页要设置searchSourceBuilder.trackTotalHits(true);这样在searchResponse可以通过getTotalHits()得到总的数据量条数。

    3、构建SearchRequest 

    使用ActionFuture包装的SearchResponse接收返回结果,遍历里面的hit中的对象放入结果集

    这里的包装,可以用actionGet()获取到与ES的查询请求结果,为成功再进行下一步。

    最终代码如下:

    1. //构建BoolQueryBuilder 布尔条件查询
    2. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    3. if (!ObjectUtils.isEmpty(exceptionVO.getIsBootFailure())) {
    4. boolQueryBuilder.must(QueryBuilders.termsQuery("isBootFailure", new int[]{1}));
    5. }
    6. if (!ObjectUtils.isEmpty(exceptionVO.getIsGunFailure())) {
    7. boolQueryBuilder.must(QueryBuilders.termsQuery("isGunFailure", new int[]{1}));
    8. }
    9. if (!ObjectUtils.isEmpty(exceptionVO.getGunId())) {
    10. boolQueryBuilder.must(QueryBuilders.termsQuery("gunId", new Object[]{exceptionVO.getGunId()}));
    11. }
    12. if (!ObjectUtils.isEmpty(exceptionVO.getStart()) && !ObjectUtils.isEmpty(exceptionVO.getEnd())) {
    13. boolQueryBuilder.must(QueryBuilders.rangeQuery("endDate.keyword").from(exceptionVO.getStart() + " 00:00:00").to(exceptionVO.getEnd() + " 23:59:59"));
    14. }
    15. //构建SearchSourceBuilder
    16. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    17. searchSourceBuilder.trackTotalHits(true);
    18. if (!ObjectUtils.isEmpty(exceptionVO.getCurrent()) && !ObjectUtils.isEmpty(exceptionVO.getSize())) {
    19. searchSourceBuilder.from((exceptionVO.getCurrent() - 1) * exceptionVO.getSize());
    20. searchSourceBuilder.size(exceptionVO.getSize());
    21. } else {
    22. searchSourceBuilder.from(0);
    23. searchSourceBuilder.size(9999);
    24. }
    25. searchSourceBuilder.sort("id", SortOrder.DESC);
    26. searchSourceBuilder.query(boolQueryBuilder);
    27. //构建SearchRequest
    28. SearchRequest searchRequest = new SearchRequest("charging_order_exception");
    29. searchRequest.source(searchSourceBuilder);
    30. ActionFuture searchResponse = elasticsearchTemplate.getClient().search(searchRequest);
    31. List list = new LinkedList<>();
    32. if (searchResponse.actionGet().status().getStatus() == RestStatus.OK.getStatus()) {
    33. page.setTotal(Long.valueOf(String.valueOf(searchResponse.actionGet().getHits().getTotalHits())));
    34. SearchHit[] searchHits = searchResponse.actionGet().getHits().getHits();
    35. for (SearchHit searchHit : searchHits) {
    36. list.add(JSONObject.parseObject(searchHit.getSourceAsString(), OrderExceptionES.class));
    37. }
    38. }

    五、其他工具

    数据发到ES了,怎么查看。

    笔者也是刚结束,下载了官网的kibana但是各种原因没法正常连上使用。

    使用谷歌浏览器的插件看看还可以,有ElasticSearchHead

    还有ElasticVue

  • 相关阅读:
    算法总结10 线段树
    Linux/CentOS 安装 flutter 与 jenkins 构建 (踩坑)
    热烈祝贺方正璞华两款产品入选2021年度江苏省工业软件优秀产品和应用解决方案拟推广名单
    多线程与高并发——并发编程(5)
    SpringBoot 中到底如何解决跨域问题?
    SD卡格式化怎么恢复?
    每日刷题3——牛客,算术转换和二级指针
    JavaScript基础语法
    Vue模板语法(下)
    【ARM Coresight OpenOCD 系列 3 -- OpenOCD 常用命令与扫描链scan_chain】
  • 原文地址:https://blog.csdn.net/Mr_Chenn/article/details/127852586