空闲之余就把先前做过的一个通过ElasticSearch的聚合来实现查询当月实际签到的天数记录一下,纯留下点记忆,大家勿喷。
1.如果不了解elsticsearch聚合的概念可以自行网上查看一番,起码懂得概念以及使用方法。
我们的业务是需要查看某个人某个月的签到天数,不管一天签到多少次,只计算一次。根据签到天数计算获取的补贴数据入库。
elasticsearch依赖:
org.springframework.data
spring-data-elasticsearch
3.0.0.RELEASE
补贴入库接口:
/**
* @Author: Qzli
* @Description: 补贴入库接口
* @Date: Create by 2018/12/10 13:23
* @return:
*/
@RequestMapping("/saveAllowance")
public R saveAllowance(@RequestParam Map params){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
String organizationName = String.valueOf(params.get("organizationName")); //调用方传过来的学校名称 例:蘑菇丁体验学院
String organizationCode = String.valueOf(params.get("organizationCode")); //调用方传过来的学校code 例:88888
String roleType = String.valueOf(params.get("roleType")); //调用方传过来的角色 例:student
if(StringUtils.isEmpty(organizationName)){
return R.error(SystemErrorCode.DATA_NOTHADE.getCode(),"学校名称不能为空");
}
if(StringUtils.isEmpty(organizationCode)){
return R.error(SystemErrorCode.DATA_NOTHADE.getCode(),"学校CODE不能为空");
}
if(StringUtils.isEmpty(roleType)){
return R.error(SystemErrorCode.DATA_NOTHADE.getCode(),"角色不能为空");
}
// 获取当前日期 例:2018-10
Date now = new Date();
Map maps = DateUtils.getMonthInfo(now); //获取当前月的工作日(不考虑节假日的情况下)
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
int days = maps.get("workDaysAmount"); //获取当前月的工作日(不考虑节假日的情况下)
String dateTime = format.format(now);
String sst = dateTime+"-01";
SimpleDateFormat sDateFormat=new SimpleDateFormat(DateUtils.DATE_PATTERN);
Date sdate = null; //开始日期
try {
sdate = sDateFormat.parse(sst);
} catch (ParseException e) {
e.printStackTrace();
}
Date edate = DateUtils.addDateMonths(sdate,1); //结束日期
List userIndexList = queryLikeUserInfo.searchStudentList(organizationName,organizationCode,roleType);//获取深职院的学生
int count=0;
int count1=0;
boolean flag;
for(int i = 0;idays){ //判断实际工作天数是否大于正常工作日天数
gae.setActualWorkingDay(BigDecimal.valueOf(days)); //实际工作日天数
}else{
gae.setActualWorkingDay(BigDecimal.valueOf(workCount)); //计入补贴的实际工作天数
}
gae.setSignCount(BigDecimal.valueOf(signCount)); //学生总共签到的天数(不排除周末以及是否上下班等等)
int sum = 650*workCount;
long allowance = Math.round((sum+0.0)/days); //应发补贴算法
gae.setAllowance(BigDecimal.valueOf(allowance)); //应发补贴
}else{ // 为空的话就是未绑定用户 都默认设置为0
gae.setSignCount(BigDecimal.valueOf(0));
gae.setActualWorkingDay(BigDecimal.valueOf(0));
gae.setAllowance(BigDecimal.valueOf(0));
}
// 根据年、月、学生pfid 验证数据库是否存在
GxyStudentAllowanceEntity entity = gxyStudentAllowanceService.selectOne(new EntityWrapper()
.eq("YEAR",gae.getYear())
.eq("MONTH",gae.getMonth())
.eq("PF_ID",gae.getPfId()));
if (entity!=null){
flag = gxyStudentAllowanceService.update(gae,new EntityWrapper()
.eq("GXY_STUDENT_ALLOWANCE_ID",entity.getGxyStudentAllowanceId()));
if(flag){
count++;
}
}else{
flag = gxyStudentAllowanceService.insert(gae);
if(flag){
count1++;
}
}
}
logger.info("更新:"+count+"条记录");
logger.info("插入:"+count1+"条记录");
return R.ok();
}
从es里获取签到天数:
/**
* @Author: Qzli
* @Description: 根据用户id、类型(签到)、开始时间、结束时间 到es里面查询签到天数
* @Date: Create by 2018/11/28 14:26
* @param: 签到天数
* @return:
*/
public Long querySign(String userId,String type,String startTime,String endTime,String flag) {
// 测试一把 https://blog.csdn.net/qq_28988969/article/details/81565765
AggregationBuilder aggregationBuilder = AggregationBuilders.dateHistogram("dayAgg") //聚合名字
.field("publishtime") // 需要聚合分组的字段名称, 类型需要为date, 格式没有要求
.dateHistogramInterval(DateHistogramInterval.DAY) // 按什么时间段聚合, 这里是按月份, 可用的interval在上面给出
.format("yyyy-MM-dd") // 返回值格式化
.minDocCount(0L); // 为空的话则填充0,强制返回所有 buckets,即使 buckets 可能为空。
// .extendedBounds(new ExtendedBounds("2018-10-01", "2018-11-01"));//为了得到全月数据,我们需要告诉 Elasticsearch 我们想要全部 buckets, 即便那些 buckets 可能落在最小日期 之前 或 最大日期 之后
SearchRequestBuilder searchRequestBuilder = null;
if("1".equals(flag)){ //1:计算总的签到天数(不排除周末以及是否上下班等等)
searchRequestBuilder = elasticsearchTemplate.getClient()
.prepareSearch("article") //索引名
.setTypes("json") //索引类型
.setSize(0) // 不显示具体的内容
.setQuery(boolQuery()
.must(QueryBuilders.matchPhraseQuery("pfid", userId)) //用户id
.must(QueryBuilders.matchPhraseQuery("formtype", type)) //类型为签到
.must(QueryBuilders.rangeQuery("orderbytime").from(startTime).to(endTime)))
.addAggregation(aggregationBuilder);
}else{ //2:计算实际出勤天数
searchRequestBuilder = elasticsearchTemplate.getClient()
.prepareSearch("article") //索引名
.setTypes("json") //索引类型
.setSize(0) // 不显示具体的内容
.setQuery(boolQuery()
.must(QueryBuilders.matchPhraseQuery("pfid", userId)) //用户id
.must(QueryBuilders.matchPhraseQuery("formtype", type)) //类型为签到
.must(QueryBuilders.boolQuery()
.should(QueryBuilders.matchPhraseQuery("tagarray", "$mgonwork$"))//签到类型为上班
.should(QueryBuilders.matchPhraseQuery("tagarray", "$mgoffwork$")) //或者为下班mgoffwork
.should(QueryBuilders.matchPhraseQuery("tagarray", "$mglegwork$"))) //或者为外勤mglegwork
.must(QueryBuilders.matchPhraseQuery("tagarray", "$1$")) //已确认的签到
.must(QueryBuilders.rangeQuery("orderbytime").from(startTime).to(endTime)))
.addAggregation(aggregationBuilder);
}
SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); //执行查询
Aggregations aggs = searchResponse.getAggregations(); //聚合
Histogram agg = aggs.get("dayAgg"); //获取聚合自定义名称
long count = 0; //计入补贴的签到天数
for (Histogram.Bucket entry : agg.getBuckets()) {
System.out.println(entry.getKeyAsString() + "签到" + entry.getDocCount() + "次");
if (entry.getDocCount()>0){
count++;
}
}
return count;
}
elasticsearch客户端连接代理插件:putty
代理说明:
127.0.0.1:9300 --> 114.215.66.118 --> 120.27.26.68:9300
最终在你代码本地使用127.0.0.1:9300这个地址来访问es
用es head就一样的配置9200
第一步 在《会话》中添加 114.215.66.118 端口: 22
第二步 在《通道》中添加 120.27.26.68:9300 120.27.26.68:9200
点击添加
最后点打开 输入账号,密码就登录进来了。
然后本地就可以访问了,启动修改本地es地址 ;
es查看用的是es_site来查看(打开es_site——点击index.html):
以下数据是在测试服的一些测试数据:(查看es数据更为直观,也可以用条件查询来判断代码查询数据是否正确)
这个没有什么直观的效果。鄙人自己做个备忘录。望大神们勿喷