当前位置: 代码网 > it编程>编程语言>Java > springboot + elasticsearch 实现聚合查询的详细代码

springboot + elasticsearch 实现聚合查询的详细代码

2025年02月17日 Java 我要评论
需求背景:终端上报表读数 记录在elasticsearch统计每天 最大值最小值springboot版本:2.2.6 默认的elasticsearch <groupid>org.sprin

需求背景:

终端上报表读数 记录在elasticsearch

统计每天 最大值最小值

springboot版本:2.2.6   

默认的elasticsearch

 <groupid>org.springframework.data</groupid>
      <artifactid>spring-data-elasticsearch</artifactid>
      <version>3.2.6.release</version>

版本 elasticsearch

{
  "name" : "node1",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "lg0bd-e-thuaw4cdn5uqrq",
  "version" : {
    "number" : "7.4.2",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
    "build_date" : "2019-10-28t20:40:44.881551z",
    "build_snapshot" : false,
    "lucene_version" : "8.2.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "you know, for search"
}

根据springdata官网

spring data elasticsearch - reference documentation

 版本符合

这里为了方便 采用的是 api创建索引

切记这里没有采用spring-data 去创建索引 而是采用的是 api 接口创建 原因后面再提

    @putmapping("/createindex")
    @apioperation(value = "创建索引")
    public r<object> createindex() {
        boolean index = elasticsearchresttemplate.createindex(datauploadinfo.class);
        elasticsearchresttemplate.putmapping(datauploadinfo.class);
        return r.success();
    }
 
import io.swagger.annotations.apimodelproperty;
import lombok.data;
import org.springframework.data.annotation.id;
import org.springframework.data.annotation.typealias;
import org.springframework.data.elasticsearch.annotations.dateformat;
import org.springframework.data.elasticsearch.annotations.document;
import org.springframework.data.elasticsearch.annotations.field;
import org.springframework.data.elasticsearch.annotations.fieldtype;
/**
 *  {
 *   "busid": "1000010814",
 *   "createtime": 1649408879000,
 *   "devicenum": "ae0007a1gmbc00047p",
 *   "gunno": "1",
 *   "rdchargecurrent": 5.617,
 *   "rdchargingpower": 1220.0,
 *   "rdchargingvoltage": 225.11,
 *   "totalelectricalpower": 270305.0
 * }
 *
 *
 *
 * @field(type=fieldtype.text, analyzer=“ik_max_word”) 表示该字段是一个文本,并作最大程度拆分,默认建立索引
 * @field(type=fieldtype.text,index=false) 表示该字段是一个文本,不建立索引
 * @field(type=fieldtype.date) 表示该字段是一个文本,日期类型,默认不建立索引
 * @field(type=fieldtype.long) 表示该字段是一个长整型,默认建立索引
 * @field(type=fieldtype.keyword) 表示该字段内容是一个文本并作为一个整体不可分,默认建立索引
 * @field(type=fieldtype.float) 表示该字段内容是一个浮点类型并作为一个整体不可分,默认建立索引
 * <p>
 * date 、float、long都是不能够被拆分的
 */
@data
@document(indexname = "charging-monitor-data", indexstoretype = "_doc", useserverconfiguration = true, createindex = false)
@typealias("_doc")
public class datauploadinfo {
    /**
     * 主键
     */
    @id
    @apimodelproperty(value = "主键", example = "11", hidden = true)
    private string id;
    @apimodelproperty(value = "枪号", example = "1")
    @field(type = fieldtype.keyword )
    private string gunno;
    @apimodelproperty(value = "桩号", example = "dg1120b1cn1c000125")
    @field(type = fieldtype.keyword)
    private string devicenum;
    @apimodelproperty(value = "流水id", example = "au22188888888888")
    @field(type = fieldtype.keyword )
    private string busid;
    @apimodelproperty(value = "充电电流(毫安)", example = "21.21")
    @field(type = fieldtype.double, index = false)
    private double rdchargecurrent;
    @apimodelproperty(value = "充电电压(毫伏)", example = "212.21")
    @field(type = fieldtype.double, index = false)
    private double rdchargingvoltage;
    @apimodelproperty(value = "充电电能(瓦)", example = "212.21")
    @field(type = fieldtype.double, index = false)
    private double rdchargingpower;
    @apimodelproperty(value = "剩余时间(分钟)", example = "21")
    @field(type = fieldtype.integer, index = false)
    private integer rdtimeleft;
    @apimodelproperty(value = "电量百分比(soc)", example = "29")
    @field(type = fieldtype.integer, index = false)
    private integer rdcurrentsoc;
    @apimodelproperty(value = "电表读数 单位kwh 保留三位小数,启动成功时才有", example = "2.292")
    @field(type = fieldtype.double, index = false)
    private double totalelectricalpower;
    @apimodelproperty(value = "正极温度", example = "22")
    @field(type = fieldtype.integer, index = false)
    private integer gunpositivetemperature;
    @apimodelproperty(value = "负极温度", example = "83")
    @field(type = fieldtype.integer, index = false)
    private integer gunnegativetemperature;
    @apimodelproperty(value = "电量上报时间", example = "1648646486000")
    @field(type = fieldtype.date, format = dateformat.custom, pattern = "yyyy-mm-dd hh:mm:ss||yyyy-mm-dd||epoch_millis")
    private long createtime;
}

这里是创建 映射的java文件 注意配置   createindex = false

这里不自动创建索引

我们调用上面的rest 接口创建 索引

查看_mapping 会发现

{
-"charging-monitor-data": {
-"mappings": {
-"properties": {
-"busid": {
"type": "keyword"
},
-"createtime": {
"format": "yyyy-mm-dd hh:mm:ss||yyyy-mm-dd||epoch_millis",
"type": "date"
},
-"devicenum": {
"type": "keyword"
},
-"gunnegativetemperature": {
"index": false,
"type": "integer"
},
-"gunno": {
"type": "keyword"
},
-"gunpositivetemperature": {
"index": false,
"type": "integer"
},
-"id": {
-"fields": {
-"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
-"rdchargecurrent": {
"index": false,
"type": "double"
},
-"rdchargingpower": {
"index": false,
"type": "double"
},
-"rdchargingvoltage": {
"index": false,
"type": "double"
},
-"rdcurrentsoc": {
"index": false,
"type": "integer"
},
-"rdtimeleft": {
"index": false,
"type": "integer"
},
-"totalelectricalpower": {
"index": false,
"type": "double"
}
}
}
}
}

keyword类型会增加keyword属性 而不是直接增加到我定义gunnegativetemperature的属性下面

"pojo里面定义的属性": {
   -"fields": {
     -"keyword": {
        "ignore_above": 256,
        "type": "keyword"
      }
    },
   "type": "text"
}

下面按照桩枪做每日电表的最大最小值

上代码

 
import com.haoran.cloud.app.monitor.entity.datauploadinfo;
import com.haoran.cloud.app.monitor.ocpp.ocppresult;
import io.swagger.annotations.api;
import io.swagger.annotations.apioperation;
import lombok.extern.log4j.log4j2;
import org.elasticsearch.index.query.boolquerybuilder;
import org.elasticsearch.index.query.querybuilders;
import org.elasticsearch.search.aggregations.aggregation;
import org.elasticsearch.search.aggregations.aggregationbuilders;
import org.elasticsearch.search.aggregations.aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.parsedstringterms;
import org.elasticsearch.search.aggregations.bucket.terms.terms;
import org.elasticsearch.search.aggregations.bucket.terms.termsaggregationbuilder;
import org.elasticsearch.search.aggregations.metrics.max.maxaggregationbuilder;
import org.elasticsearch.search.aggregations.metrics.max.parsedmax;
import org.elasticsearch.search.aggregations.metrics.min.minaggregationbuilder;
import org.elasticsearch.search.aggregations.metrics.min.parsedmin;
import org.joda.time.datetime;
import org.springframework.data.elasticsearch.core.elasticsearchresttemplate;
import org.springframework.data.elasticsearch.core.query.nativesearchquery;
import org.springframework.data.elasticsearch.core.query.nativesearchquerybuilder;
import org.springframework.validation.annotation.validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.resource;
import java.text.dateformat;
import java.text.parseexception;
import java.text.simpledateformat;
import java.util.date;
import java.util.list;
import java.util.map;
/**
 * @author wenhaoran
 * @version 1.0
 */
@restcontroller
@requestmapping("/test")
@api(value = "test", tags = "test")
@log4j2
@validated
public class pilemonitorcontroller1 {
    /**
     * @return
     */
    @getmapping("/dailysummaryenergy")
    @apioperation(value = "每日电力汇总")
    public ocppresult<object> dailysummaryenergy() throws parseexception {
        boolquerybuilder querybuilder = querybuilders.boolquery();
        datetime now = datetime.now();
        datetime plus = now.plusdays(1);
        string fromdatestr = df.format(now.todate());
        date fromdate = df.parse(fromdatestr);
        string todatestr = df.format(plus.todate());
        date todate = df.parse(todatestr);
        querybuilder.must(querybuilders.rangequery("createtime").gte(fromdate.gettime()).lt(todate.gettime()));
        nativesearchquerybuilder nativesearchquerybuilder = new nativesearchquerybuilder().withquery(querybuilder);
        termsaggregationbuilder pile = aggregationbuilders.terms("group_devicenum").field("devicenum");
        termsaggregationbuilder gun = aggregationbuilders.terms("group_gunno").field("gunno");
        minaggregationbuilder minnumber = aggregationbuilders.min("minnumber").field("totalelectricalpower");
        maxaggregationbuilder maxnumber = aggregationbuilders.max("maxnumber").field("totalelectricalpower");
        gun.subaggregation(minnumber).subaggregation(maxnumber);
        pile.subaggregation(gun);
        nativesearchquerybuilder.addaggregation(pile);
        nativesearchquery nativesearchquery = nativesearchquerybuilder.build();
        aggregations query = elasticsearchresttemplate.query(nativesearchquery, searchresponse -> searchresponse.getaggregations());
        map<string, aggregation> stringaggregationmap = query.asmap();
        parsedstringterms stringterms = (parsedstringterms) stringaggregationmap.get("group_devicenum");
        list<? extends terms.bucket> buckets = stringterms.getbuckets();
        for (terms.bucket bucket : buckets) {
            map<string, aggregation> pilemap = bucket.getaggregations().asmap();
            parsedstringterms gunagg = (parsedstringterms) pilemap.get("group_gunno");
            list<? extends terms.bucket> gunbucketlist = gunagg.getbuckets();
            for (terms.bucket gunbucket : gunbucketlist) {
                aggregations aggregations = gunbucket.getaggregations();
                map<string, aggregation> asmap = aggregations.getasmap();
                if (asmap.containskey("minnumber")) {
                    parsedmin aggregation = (parsedmin) asmap.get("minnumber");
                    system.out.println("minnumber=" + aggregation.getvalue());
                }
                if (asmap.containskey("maxnumber")) {
                    parsedmax aggregation = (parsedmax) asmap.get("maxnumber");
                    system.out.println("maxnumber=" + aggregation.getvalue());
                }
            }
        }
        return ocppresult.success("success");
    }
    @deletemapping("/deleteindex")
    @apioperation(value = "删除索引")
    public ocppresult<object> deleteindex() {
        elasticsearchresttemplate.deleteindex(datauploadinfo.class);
        return ocppresult.success();
    }
    @putmapping("/createindex")
    @apioperation(value = "创建索引")
    public ocppresult<object> createindex() {
        boolean index = elasticsearchresttemplate.createindex(datauploadinfo.class);
        elasticsearchresttemplate.putmapping(datauploadinfo.class);
        return ocppresult.success();
    }
    final dateformat df = new simpledateformat("yyyy-mm-dd");
    @resource
    private elasticsearchresttemplate elasticsearchresttemplate;
}

到此这篇关于springboot + elasticsearch 实现聚合查询的文章就介绍到这了,更多相关springboot elasticsearch聚合查询内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com