1、前置条件

1.1、运行环境

1.1.1、硬件配置要求

服务器:
CPU 8核 i5以上
内存 32GB以上
硬盘 500GB 以上

1.1.2、软件配置要求

jdk1.8.0_241, nodejs 14+
数据库 mysql 8.0.x
Elasticsearch 7.17.3
Kibana 7.17.3
Logstash 7.17.3
操作系统 CentOS7.6 1810
Chrome81.0.4044.122及以上

1.2、服务器环境准备

1.2.1、安装

1.2.1.1、JDK

安装JDK8版本
Linux可参考(https://www.cnblogs.com/Pycainiao/p/13170053.html)

1.2.1.2、ElasticSearch安装
1.2.1.2.1、修改elastsearch文件夹下config\elasticsearch.yml

修改cluster.name参数
设置node.name参数
修改network.host为当前主机ip
设置cluster.initial_master_nodes参数:数组值需与参数node.name相同
http.cors.enabled: true
http.cors.allow-origin: "*"
#是否主节点
node.master: true
#集群地址
discovery.seed_hosts:["10.86.97.200"]
#节点列表
cluster.initial_master_nodes: ["node-1"]
1.2.1.2.2、创建账号

#创建的普通账号为 elk
[root@localhost config]# useradd elk
#给普通账号(elk)设置密码为:Ser@0322
[root@localhost config]# echo Ser@0322 | passwd --stdin elk
#将elasticsearch安装路径下的所有文件权限(所属者)设置为elk
[root@localhost config]# chown -R elk.elk /elasticsearch安装路径

1.2.1.2.3、生成证书,到elastsearch文件夹的bin目录下执行以下命令
./elasticsearch-certutil cert -out config/elastic-certificates.p12 -pass ""

后修改config目录下elasticsearch.yml文件,在最后新增以下参数

xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.type: PKCS12
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.type: PKCS12
1.2.1.2.4、修改elastsearch文件夹的bin目录下elasticsearch-env


增加ES_JAVA_HOME=“$ES_HOME/jdk”

1.2.1.2.5、修改/etc/sysctl.conf /etc/security/limits.conf
#在/etc/sysctl.conf文件最后添加一行
vm.max_map_count=655360
#并执行命令
sysctl -p
#修改/etc/security/limits.conf文件
增加
* soft nofile 65536
* hard nofile 65536
1.2.1.2.6、启动
切换为elk账户,进入elastsearch文件夹的bin目录
./elasticsearch -d
1.2.1.2.7、自定义修改相关账户密码
./bin/elasticsearch-setup-passwords interactive
1.2.1.3、kibana安装(用于管理elasticsearch)
1.2.1.3.1、将kibana安装路径下的所有文件权限(所属者)设置为elk
1.2.1.3.2、修改kibana文件夹下config\kibana.yml
server.host: "主机ip"
server.name: "mcos-kibana"
elasticsearch.hosts: ["http://elasticsearch的IP:9200"]
kibana.index: ".kibana"
elasticsearch.username: "kibana_system"
elasticsearch.password: "es安装时设置的kibana_system账户密码"
i18n.locale: "zh-CN"
1.2.1.3.3、启动

切换为elk账户,进入kibana文件夹的bin目录

nohup ./kibana >> /dev/null 2>&1 &
1.2.1.3.4、登录kibana

http://xx.xx.xx.xx:5601/
开发工具中执行对应命令,创建索引模板

#创建track_record索引模板
PUT _index_template/track_record
{"template": {"settings": {"index": {"refresh_interval": "5s","requests": {"cache": {"enable": "true"}},"store": {"preload": ["nvd","dvd"]},"number_of_shards": "3","number_of_replicas": "1"}},"mappings": {"_routing": {"required": false},"numeric_detection": false,"dynamic_date_formats": ["strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"],"dynamic": true,"_source": {"excludes": [],"includes": [],"enabled": true},"date_detection": true,"properties": {"create_time": {"type": "long"},"pass_time": {"index": true,"ignore_malformed": false,"store": false,"type": "date_nanos","doc_values": true},"section_name": {"eager_global_ordinals": false,"norms": false,"index": true,"store": false,"type": "keyword","index_options": "docs","split_queries_on_whitespace": false,"doc_values": true},"illegal_code": {"eager_global_ordinals": false,"norms": false,"index": true,"store": false,"type": "keyword","split_queries_on_whitespace": false,"index_options": "docs","doc_values": true},"report_type": {"eager_global_ordinals": false,"norms": false,"index": true,"store": false,"type": "keyword","split_queries_on_whitespace": false,"index_options": "docs","doc_values": true},"uc_lane": {"type": "integer"},"plate_type": {"eager_global_ordinals": false,"norms": false,"index": true,"store": false,"type": "keyword","split_queries_on_whitespace": false,"index_options": "docs","doc_values": true},"snapshot_info": {"eager_global_ordinals": false,"index_phrases": false,"fielddata": false,"norms": false,"index": true,"store": false,"type": "text","index_options": "positions"},"is_delete": {"type": "integer"},"device_ip": {"type": "ip"},"first_timestamp": {"type": "long"},"@timestamp": {"index": true,"ignore_malformed": false,"store": false,"type": "date_nanos","doc_values": true},"id": {"type": "long"},"plate_number": {"eager_global_ordinals": false,"norms": false,"index": true,"store": false,"type": "keyword","split_queries_on_whitespace": false,"index_options": "docs","doc_values": true},"cid": {"eager_global_ordinals": false,"index_phrases": false,"fielddata": false,"norms": false,"index": true,"store": false,"type": "text","index_options": "positions"}}},"aliases": {"track_record": {}}},"index_patterns": ["track_record*"],"composed_of": []
}
1.2.1.4、 logstash安装
1.2.1.4.1、将logstash-conf.tar解压至logstash目录下

“logstash-conf.tar”见https://download.csdn.net/download/taotao_guiwang/86744452

1.2.1.4.2、修改图中目录所有.conf文件


jdbc_connection_string: 修改ip为对应mysql地址
jdbc_driver_library: 修改/home/es/logstash-7.17.3为logstash目录全路径
jdbc_user: mysql账户
jdbc_password: mysql密码
last_run_metadata_path: 修改/home/es/logstash-7.17.3为logstash目录全路径
hosts: elasticsearch地址
User: elasticsearch账户
Password: elasticsearch密码

1.2.1.4.3、 启动

进入logstash的bin目录下执行对应命令,启动图中实例(XX为图中各个文件夹名称)

nohup ./logstash -f ../XX/XX.conf --path.data=../XX/data_XX/ >/dev/null 2>&1 &

1.2.2、SpringBoot配置

完整demo见:https://download.csdn.net/download/taotao_guiwang/86745175

1.2.2.1、完整pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.1.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>ESDemo</artifactId><version>0.0.1-SNAPSHOT</version><name>ESDemo</name><description>ESDemo</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- pool 对象池 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--常用工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!--SpringBoot集成elasticsearch--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId><exclusions><exclusion><artifactId>elasticsearch-rest-client</artifactId><groupId>org.elasticsearch.client</groupId></exclusion></exclusions></dependency><dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>7.17.3</version><exclusions><exclusion><artifactId>elasticsearch-rest-client</artifactId><groupId>org.elasticsearch.client</groupId></exclusion></exclusions></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.17.3</version><exclusions><exclusion><artifactId>httpclient</artifactId><groupId>org.apache.httpcomponents</groupId></exclusion></exclusions></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
1.2.2.2、yml
# elasticsearch配置信息
elasticsearch:username: elasticpassword: 123456urls: 10.86.97.200:9200pool:maxTotal: 10maxWaitMillis: 30000timeoutMillis: 1800000
1.2.2.3、ES工具类
package com.zit.cac.project.tool.esUtil;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;public class EsClientPoolFactory implements PooledObjectFactory<ElasticsearchClient> {private HttpHost[] hosts;private String username;private String password;public EsClientPoolFactory(String username,String password,HttpHost[] hosts) {this.username=username;this.password=password;this.hosts=hosts;}@Overridepublic void activateObject(PooledObject<ElasticsearchClient> arg0) throws Exception {System.out.println("activateObject");}/*** 销毁对象*/@Overridepublic void destroyObject(PooledObject<ElasticsearchClient> pooledObject) throws Exception {ElasticsearchClient elasticsearchClient = pooledObject.getObject();elasticsearchClient.shutdown();}/*** 生产对象*/@Overridepublic PooledObject<ElasticsearchClient> makeObject() {ElasticsearchClient client = null;try {//密码验证final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username, password));// Create the low-level clientRestClient restClient = RestClient.builder(hosts).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {@Overridepublic HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider).setMaxConnTotal(10);}}).build();// Create the transport with a Jackson mapperElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());// And create the API clientclient = new ElasticsearchClient(transport);} catch (Exception e) {e.printStackTrace();}return new DefaultPooledObject<ElasticsearchClient>(client);}@Overridepublic void passivateObject(PooledObject<ElasticsearchClient> arg0) throws Exception {System.out.println("passivateObject");}@Overridepublic boolean validateObject(PooledObject<ElasticsearchClient> arg0) {return true;}
}
package com.zit.cac.project.tool.esUtil;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.http.HttpHost;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class EsConfig {/*** elasticsearch连接用户*/@Value("${elasticsearch.username}")private String usaerName;/*** elasticsearch连接密码*/@Value("${elasticsearch.password}")private String password;/*** elasticsearch集群路径*/@Value("${elasticsearch.urls}")private String urls;/*** elasticsearch客户端连接池最大数量*/@Value("${elasticsearch.pool.maxTotal}")private int maxTotal;/*** elasticsearch客户端连接池等待时长*/@Value("${elasticsearch.pool.maxWaitMillis}")private int maxWaitMillis;/*** elasticsearch客户端连接池超时时长*/@Value("${elasticsearch.pool.timeoutMillis}")private int timeoutMillis;@Beanpublic GenericObjectPool<ElasticsearchClient> getGenericObjectPool() {GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();poolConfig.setMaxTotal(maxTotal);poolConfig.setMaxWaitMillis(maxWaitMillis);poolConfig.setEvictorShutdownTimeoutMillis(timeoutMillis);poolConfig.setTestOnBorrow(true);poolConfig.setTestOnReturn(true);poolConfig.setTestWhileIdle(true);poolConfig.setJmxEnabled(false);String[] strs = urls.split(",");HttpHost[] hosts = new HttpHost[strs.length];for (int i = 0; i < strs.length; i++) {String[] connection = strs[i].split(":");hosts[i] = new HttpHost(connection[0],Integer.parseInt(connection[1]));}EsClientPoolFactory esClientPoolFactory = new EsClientPoolFactory(usaerName, password,hosts);GenericObjectPool<ElasticsearchClient> clientPool = new GenericObjectPool<>(esClientPoolFactory,poolConfig);return clientPool;}
}
package com.zit.cac.project.tool.esUtil;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.*;import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import com.zit.cac.project.nvlms.domain.IllegalRecord;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.UpdateByQueryAction;
import org.elasticsearch.index.reindex.UpdateByQueryRequestBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Collections;
import java.util.List;/*** @DateTime: 2022/6/22 15:38* @Description: es查询*/
@Component
public class EsSearch {@Autowiredprivate EsConfig esConfig;public SearchResponse<?> search(SearchRequest request, Class<?> classN) {ElasticsearchClient client = null;try {client = esConfig.getGenericObjectPool().borrowObject();SearchResponse<?> searchResponse = client.search(request, classN);return searchResponse;} catch (Exception e) {System.out.println("报错" + e.getMessage());e.printStackTrace();} finally {esConfig.getGenericObjectPool().returnObject(client);}return null;}public UpdateResponse<?> update(UpdateRequest request, Class<?> classN) {ElasticsearchClient client = null;try {client = esConfig.getGenericObjectPool().borrowObject();UpdateResponse<?> searchResponse = client.update(request, classN);return searchResponse;} catch (Exception e) {System.out.println("报错" + e.getMessage());e.printStackTrace();} finally {esConfig.getGenericObjectPool().returnObject(client);}return null;}public BulkResponse bulk(List<BulkOperation> list) {ElasticsearchClient client = null;try {client = esConfig.getGenericObjectPool().borrowObject();BulkResponse bulkResponse = client.bulk(e -> e.operations(list));return bulkResponse;} catch (Exception e) {System.out.println("报错" + e.getMessage());e.printStackTrace();} finally {esConfig.getGenericObjectPool().returnObject(client);}return null;}public CreateResponse insert(Object obj,String index,String id) {ElasticsearchClient client = null;try {client = esConfig.getGenericObjectPool().borrowObject();CreateResponse createResponse = client.create(e -> e.index(index).id(id).document(obj));return createResponse;} catch (Exception e) {System.out.println("插入报错" + e.getMessage());e.printStackTrace();} finally {esConfig.getGenericObjectPool().returnObject(client);}return null;}public UpdateByQueryResponse updateByQuery(UpdateByQueryRequest request) {ElasticsearchClient client = null;try {client = esConfig.getGenericObjectPool().borrowObject();UpdateByQueryResponse updateResponse = client.updateByQuery(request);return updateResponse;} catch (Exception e) {System.out.println("查询更新报错" + e.getMessage());e.printStackTrace();} finally {esConfig.getGenericObjectPool().returnObject(client);}return null;}}

1.2.3、启动

2、算法实现

2.1、参数配置

2.2、java API实现

package com.example.esdemo.controller;import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.aggregations.CompositeAggregationSource;
import co.elastic.clients.elasticsearch._types.aggregations.CompositeBucket;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.example.esdemo.model.HdonResult;
import com.example.esdemo.tool.DateUtils;
import com.example.esdemo.tool.EsSearch;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;@Controller
@RequestMapping("/es")
public class AnalysisServiceController {@Autowiredprivate EsSearch esSearch;@Value("${nvlms.analysis.hdon.dayBegin}")private String dayBegin;@Value("${nvlms.analysis.hdon.dayEnd}")private String dayEnd;@Value("${nvlms.analysis.hdon.dayOutLimit}")private Integer dayOutLimit;@Value("${nvlms.analysis.hdon.nightOutLimit}")private Integer nightOutLimit;@Value("${nvlms.analysis.hdon.subLimitBetweenDayAndNight}")private Integer subLimitBetweenDayAndNight;@GetMapping("/getHdon")public List<HdonResult> getHdonEs(Date start, Date end, String sectionName) throws IOException {List<FieldValue> sectionList = Stream.of(sectionName).map(FieldValue::of).collect(Collectors.toList());String script = "InternalQlScriptUtils.nullSafeFilter(" +"InternalQlScriptUtils.%s(" +// lte"InternalSqlScriptUtils.dateTimeFormat(InternalSqlScriptUtils.add(InternalQlScriptUtils.docValue(doc,'pass_time'),InternalSqlScriptUtils.intervalDayTime('PT8H','INTERVAL_HOUR'))" +",'HH:mm:ss','Z')" +",'%s')" +// dayBegin")";String script2 = "InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.%s(params.a0,%s))";long startTime = start.getTime();long endTime = end.getTime();BoolQuery boolQueryNight = BoolQuery.of(builder -> {builder.must(m -> m.bool(b -> b.must(bb -> bb.terms(t -> t.field("section_name").terms(tt -> tt.value(sectionList)))).must(bb2 -> bb2.range(r -> r.field("pass_time").from(String.valueOf(startTime)).to(String.valueOf(DateUtils.getEndOfDay(end))))))).must(m2 -> m2.bool(b2 -> b2.should(s -> s.script(ss -> ss.script(sss -> sss.inline(i -> i.source(String.format(script, "lte", dayBegin)))))).should(s -> s.script(ss -> ss.script(sss -> sss.inline(i -> i.source(String.format(script, "gte", dayEnd))))))));return builder;});// 号牌号码、号牌种类/*"aggs": {"my_buckets": {"composite": {"sources": [{ "plate_number": { "terms": { "field": "plate_number" } } }]}}}*/List<Map<String, CompositeAggregationSource>> listMap = new ArrayList();Map<String, CompositeAggregationSource> map = new HashMap<>();map.put("plate_number", CompositeAggregationSource.of(cc -> cc.terms(t -> t.field("plate_number").missingBucket(true))));Map<String, CompositeAggregationSource> map2 = new HashMap<>();map2.put("plate_type", CompositeAggregationSource.of(cc -> cc.terms(t -> t.field("plate_type").missingBucket(true))));listMap.add(map);listMap.add(map2);// 根据号牌号码分组-得到出现次数Map<String, Aggregation> mapAgg = new HashMap<>();mapAgg.put("TIMES", Aggregation.of(a -> a.filter(f -> f.exists(e -> e.field("plate_number")))));// 号牌号码,按照昼伏夜出参数进一步筛选Map<String, String> dict = new HashMap<>();dict.put("a0", "TIMES._count");mapAgg.put("having.TIMES", Aggregation.of(a -> a.bucketSelector(b -> b.bucketsPath(path -> path.dict(dict)).script(s -> s.inline(i -> i.source(String.format(script2, "gte", Math.max(nightOutLimit, // 夜晚出现的次数subLimitBetweenDayAndNight))))))// 白天夜晚出现次数差值));//mapAgg.put("myBucketSort", Aggregation.of(a -> a.bucketSort(b -> b.from((param.getPageNum() - 1) * param.getPageSize()).size(param.getPageSize()).gapPolicy(GapPolicy.Skip))));SearchRequest request = SearchRequest.of(s -> s.index("track_record").size(0).query(q -> q.bool(boolQueryNight)).aggregations("groupby", a -> a.composite(c -> c.size(65536).sources(listMap)).aggregations(mapAgg)));SearchResponse<?> resNight = esSearch.search(request, Map.class);List<CompositeBucket> night = resNight.aggregations().get("groupby").composite().buckets().array();List<FieldValue> dayFilter = night.stream().map(compositeBucket -> compositeBucket.key().get("plate_number").to(String.class)).map(FieldValue::of).collect(Collectors.toList());BoolQuery boolQueryDay = BoolQuery.of(builder -> {builder.must(m -> m.bool(b -> b.must(bb -> bb.terms(t -> t.field("section_name").terms(tt -> tt.value(sectionList)))).must(bb -> bb.terms(t -> t.field("plate_number").terms(tt -> tt.value(dayFilter)))).must(bb2 -> bb2.range(r -> r.field("pass_time").from(String.valueOf(startTime)).to(String.valueOf(DateUtils.getEndOfDay(end))))))).must(m2 -> m2.bool(b2 -> b2.must(s -> s.script(ss -> ss.script(sss -> sss.inline(i -> i.source(String.format(script, "gte", dayBegin)))))).must(s -> s.script(ss -> ss.script(sss -> sss.inline(i -> i.source(String.format(script, "lte", dayEnd))))))));return builder;});mapAgg.put("having.TIMES", Aggregation.of(a -> a.bucketSelector(b -> b.bucketsPath(path -> path.dict(dict)).script(s -> s.inline(i -> i.source(String.format(script2, "lte", dayOutLimit)))))));SearchRequest requestDay = SearchRequest.of(s -> s.index("track_record").size(0).query(q -> q.bool(boolQueryDay)).aggregations("groupby", a -> a.composite(c -> c.size(65536).sources(listMap)).aggregations(mapAgg)));SearchResponse<?> resDay = esSearch.search(requestDay, Map.class);List<CompositeBucket> day = resDay.aggregations().get("groupby").composite().buckets().array();Map<String, Long> dayMap = day.stream().collect(Collectors.toMap(c -> c.key().get("plate_number").to(String.class) + "-" + c.key().get("plate_type").to(String.class), CompositeBucket::docCount));List<HdonResult> list = new ArrayList<>();night.forEach(n -> {String key = n.key().get("plate_number").to(String.class) + "-" + n.key().get("plate_type").to(String.class);if (dayMap.containsKey(key)) {if (n.docCount() - dayMap.get(key) >= subLimitBetweenDayAndNight) {list.add(hdonResultBuild(n, dayMap.get(key)));}} else if (n.docCount() >= subLimitBetweenDayAndNight) {list.add(hdonResultBuild(n, null));}});// 遍历list,用于查看执行结果list.stream().forEach(l->{System.out.println(l);});return list;}private HdonResult hdonResultBuild(CompositeBucket night, Long dayTimes) {HdonResult hdonResult = new HdonResult();hdonResult.setPlateNum(night.key().get("plate_number").to(String.class));hdonResult.setPlateType(night.key().get("plate_type").to(String.class));hdonResult.setNightTimes(Long.valueOf(night.docCount()).intValue());hdonResult.setDayTimes(dayTimes == null ? 0 : Long.valueOf(dayTimes).intValue());return hdonResult;}
}

3、最终效果

3.1、请求实例

3.2、后台打印

3.3、页面效果

从0到1使用ES实现昼伏夜出算法(环境搭建到页面效果)相关推荐

  1. 大神程序员,夜夜coding到天明?Python之父昼伏夜出,PHP创始人24小时都在线

    栗子 鱼羊 发自 凹非寺 量子位 出品 | 公众号 QbitAI 大神程序员,夜夜coding到天明? 有位名叫Ivan Bessarabov (简称"伊万") 的好事者,刚刚统计 ...

  2. “飞檐走壁”的铁路“小黄人”:昼伏夜出护航春运

    接触网工夜间检修铁路. 杭州供电段 摄 接触网工夜间检修铁路. 杭州供电段 摄 中新网杭州1月31日电 题:"飞檐走壁"的铁路"小黄人":昼伏夜出护航春运 作者 ...

  3. 震惊!原来Android OpenGL ES可以这样用,实现 (水波纹)涟漪效果超惊艳!

    用几行代码实现惊艳的特效. 作者:字节流动 链接:https://juejin.im/post/5ed9c9445188254344768bd6 水波纹效果原理 最近一个做视频滤镜的朋友,让我给他做一 ...

  4. 从零搭建ES搜索服务(一)基本概念及环境搭建

    一.前言 本系列文章最终目标是为了快速搭建一个简易可用的搜索服务.方案并不一定是最优,但实现难度较低. 二.背景 近期公司在重构老系统,需求是要求知识库支持全文检索. 我们知道普通的数据库 like ...

  5. 保姆级教程——Ubuntu16.04 Server下深度学习环境搭建:安装CUDA8.0,cuDNN6.0,Bazel0.5.4,源码编译安装TensorFlow1.4.0(GPU版)...

    写在前面 本文叙述了在Ubuntu16.04 Server下安装CUDA8.0,cuDNN6.0以及源码编译安装TensorFlow1.4.0(GPU版)的亲身经历,包括遇到的问题及解决办法,也有一些 ...

  6. Anaconda3+python3.7.10+TensorFlow2.3.0+PyQt5环境搭建

    Anaconda3+python3.7.10+TensorFlow2.3.0+PyQt5环境搭建 一.Anaconda 创建 python3.7环境 1.进入 C:\Users\用户名 目录下,找到 ...

  7. ESXi6.5环境搭建(三:vSphere Client6.0安装)

    实验目的及要求 完成VMware workstations安装,会应用相关操作: 完成虚拟机中ESXI6.5平台的安装及网络环境配置: 完成VMware vSphere Client 6.0软件在PC ...

  8. heritrix 3.2.0 -- 环境搭建

    heritrix作为一个比较经典的开源爬虫,写这篇文章目的是因为,3.X之后的heritrix的介绍以及配置的文章比较少了. heritrix 3.x 以后使用maven 2配置jar包引用,但是总是 ...

  9. 2W 字详解 Redis 6.0 集群环境搭建实践

    原文链接:https://www.cnblogs.com/hueyxu/p/13884800.html 本文是Redis集群学习的实践总结(基于Redis 6.0+),详细介绍逐步搭建Redis集群环 ...

最新文章

  1. 2.0 pomelo-treasure官方demo的使用
  2. Jenkins执行shell脚本启动tomcat失败解决方法
  3. TCP 和IP的区别
  4. 详解道路标记数据集 CeyMo: See More on Roads -- A Novel Benchmark Dataset for Road Marking Detection
  5. 5 Django系列之通过list_display展示多对多与外键内容在admin-web界面下
  6. 最简单的6种防止数据重复提交的方法!(干货)
  7. C/C++混淆点-strcat和strcpy区别
  8. NServiceBus主机
  9. html+css+js实现网页拼图游戏
  10. python画布位置_如何调整tkinter画布的位置
  11. windows使用ffmpeg将mp4文件转变成h264视频文件
  12. GDB使用小结- 可带参数
  13. 软件架构设计_架构师内功心法,软件架构设计的七大原则精选案例
  14. 生态版图 | 10月份YashanDB获信创产品认证,并与3款产品完成互认证
  15. C++学习方法(经典)
  16. [4G+5G专题-144]: 测试-频谱分析仪工作原理与测试结果分析
  17. python的多任务处理
  18. 面试中自我介绍的小技巧
  19. TVS管与ESD保护二极管的区别
  20. 使用Iframe打印预览pdf,兼容谷歌火狐浏览器

热门文章

  1. 计算机维修基础知识pdf,电脑主板维修基础知识.pdf
  2. 用显卡测试软件蓝屏,windows7安装显卡驱动时蓝屏
  3. 基于C语言实现的网络嗅探器设计课程设计
  4. 威马百亿融资的背后是百度决胜AI时代的决心
  5. django 基础安装配置流程
  6. 【5G系列】NAS层PLMN选择(2)——选网过程
  7. python图片转手绘软件_酷!一个仿漫画手绘风格的 Python 图表库
  8. 关于掌纹识别的android版本开发(实例调用JNI)
  9. Python美股量化交易填坑记录——13b.Vegas隧道交易机器人(实盘记录)
  10. Linux Shell/python等脚本总结