以前用MongoDB数据库都是简单的查询,直接用Query就可以,最近项目中用到了分组查询,完全不一样。第一次遇到,搞了好几天终于有点那意思了。

先上代码:

  1. import java.math.BigDecimal;
  2. import java.text.ParseException;
  3. import java.text.SimpleDateFormat;
  4. import java.util.ArrayList;
  5. import java.util.Date;
  6. import java.util.List;
  7.  
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.data.mongodb.core.MongoTemplate;
  12. import org.springframework.data.mongodb.core.aggregation.Aggregation;
  13. import org.springframework.data.mongodb.core.aggregation.AggregationResults;
  14. import org.springframework.data.mongodb.core.aggregation.Fields;
  15. import org.springframework.data.mongodb.core.aggregation.GroupOperation;
  16. import org.springframework.data.mongodb.core.aggregation.MatchOperation;
  17. import org.springframework.data.mongodb.core.aggregation.ProjectionOperation;
  18. import org.springframework.data.mongodb.core.mapreduce.GroupBy;
  19. import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
  20. import org.springframework.data.mongodb.core.query.Criteria;
  21. import org.springframework.stereotype.Service;
  22.  
  23. import com.mongodb.BasicDBList;
  24. import com.mongodb.BasicDBObject;
  25. import com.mongodb.CommandResult;
  26.  
  27. @Service
  28. public class EquipmentRepository implements EquipmentRepository{
  29.  
  30. private static final Logger logger = LoggerFactory.getLogger(EquipmentRepository.class);
  31.  
  32. @Autowired
  33. MongoTemplate mongoTemplate;
  34.  
  35. /**
  36. *<p>从登陆信息表中根据IP统计设备使用时间</p>
  37. * @param hostName 设备名称
  38. * @param startTime 统计开始时间
  39. * @param endTime 统计结束时间
  40. * @return 统计信息
  41. */
  42. @Override
  43. public List<EquipStatistics> statisticTime(String hostName, Date startTime, Date endTime) {
  44.  
  45. List<EquipStatistics> equipStatisticsList = new ArrayList<EquipStatistics>();
  46.  
  47. try {
  48.  
  49. String initial = "{hostName:'' ,equipmentTypeName:'', userDurateion : 0,count:0,"
  50. + "startTime:"+startTime.getTime()+",endTime:"+endTime.getTime()+",nowTime:"+new Date().getTime()+"}";
  51.  
  52. String reduceFunction = "function(doc,result){"
  53. + "if(doc.extraData.hostName) { result.hostName = doc.extraData.hostName;}"
  54. + "if(doc.extraData.deviceType) {result.equipmentTypeName = doc.extraData.deviceType;}"
  55. + "var time = doc.logoffTime.valueOf() - doc.logonTime.valueOf();"
  56. + "result.userDurateion +=time;"
  57. +" result.count+=1;"
  58. + "}";
  59.  
  60. //时间的计算分四种情况
  61. List<EquipStatistics> equipStatisticsListTemp =null;
  62. for (int i = 0; i < 4; i++) {
  63. switch (i) {
  64. case 0:
  65. //登出时间在开始和结束之间,登录在开始和结束之间的(登出-登录)
  66. Criteria criteria = Criteria.where("logonIp").exists(true);
  67. if(hostName !=null && !"".equals(hostName.trim())){
  68. criteria.and("extraData.hostName").regex(hostName);
  69. }
  70. criteria.and("logoffTime").lt(endTime).gt(startTime).and("logonTime").lt(endTime).gt(startTime);
  71. equipStatisticsListTemp = searchDB(criteria, reduceFunction, initial);
  72.  
  73. break;
  74. case 1:
  75. //1、 登出时间为空或 登出时间在结束之后, 登录时间在开始与结束之间的(结束-登录)
  76. reduceFunction = "function(doc,result){"
  77. + "if(doc.extraData.hostName) { result.hostName = doc.extraData.hostName;}"
  78. + "if(doc.extraData.deviceType) {result.equipmentTypeName = doc.extraData.deviceType;}"
  79. + "var time = result.endTime - doc.logonTime.valueOf();"
  80. + "result.userDurateion +=time;"
  81. +" result.count+=1;"
  82. + "}";
  83. Criteria criteria1 = Criteria.where("logonIp").exists(true);
  84. if(hostName !=null && !"".equals(hostName.trim())){
  85. criteria1.and("extraData.hostName").regex(hostName);
  86. }
  87.  
  88. criteria1.andOperator(Criteria.where("logonTime").lt(endTime).gt(startTime)
  89. .andOperator(Criteria.where("logoffTime").exists(false).orOperator(Criteria.where("logoffTime").gt(endTime))));
  90. equipStatisticsListTemp = searchDB(criteria1, reduceFunction, initial);
  91. break;
  92. case 2:
  93. //2、 登出时间为空, 登出时间在结束之后 ,登录时间在开始之前的 (结束-开始)
  94. reduceFunction = "function(doc,result){"
  95. + "if(doc.extraData.hostName) { result.hostName = doc.extraData.hostName;}"
  96. + "if(doc.extraData.deviceType) {result.equipmentTypeName = doc.extraData.deviceType;}"
  97. + "var time = result.endTime - result.startTime;"
  98. + "result.userDurateion +=time;"
  99. +" result.count+=1;"
  100. + "}";
  101. Criteria criteria2 = Criteria.where("logonIp").exists(true);
  102. if(hostName !=null && !"".equals(hostName.trim())){
  103. criteria2.and("extraData.hostName").regex(hostName);
  104. }
  105. criteria2.andOperator(Criteria.where("logonTime").lt(startTime)
  106. .andOperator(Criteria.where("logoffTime").exists(false).orOperator(Criteria.where("logoffTime").gt(endTime))));
  107. equipStatisticsListTemp = searchDB(criteria2, reduceFunction, initial);
  108. break;
  109. case 3:
  110. //4、 登出时间在开始和结束之间,登录时间在开始之前的(登出-开始)
  111. reduceFunction = "function(doc,result){"
  112. + "if(doc.extraData.hostName) { result.hostName = doc.extraData.hostName;}"
  113. + "if(doc.extraData.deviceType) {result.equipmentTypeName = doc.extraData.deviceType;}"
  114. + "var time = doc.logoffTime.valueOf() - result.startTime;"
  115. + "result.userDurateion +=time;"
  116. +" result.count+=1;"
  117. + "}";
  118. Criteria criteria3 = Criteria.where("logonIp").exists(true);
  119. if(hostName !=null && !"".equals(hostName.trim())){
  120. criteria3.and("extraData.hostName").regex(hostName);
  121. }
  122. criteria3.and("logonTime").lt(startTime).and("logoffTime").lt(endTime).gt(startTime);
  123. equipStatisticsListTemp = searchDB(criteria3, reduceFunction, initial);
  124. break;
  125. default:
  126. break;
  127. }
  128. equipStatisticsList.addAll(equipStatisticsListTemp);
  129. equipStatisticsListTemp = null;
  130. }
  131.  
  132. //去除重复数据 时长相加 赋值使用率
  133. equipStatisticsList = addDuration(equipStatisticsList,daysBetween(startTime,endTime));
  134. } catch (Throwable e) {
  135. logger.error("统计设备使用信息失败:"+e.getMessage(), e);
  136. throw new AssetRuntimeException(e);
  137. }
  138.  
  139. return equipStatisticsList;
  140. }
  141.  
  142. //获取相隔天数
  143. private int daysBetween(Date startTime, Date endTime) {
  144. return (int)((endTime.getTime()-startTime.getTime())/(1000 * 86400));
  145. }
  146.  
  147. //查询数据库
  148. private List<EquipStatistics> searchDB(Criteria criteria, String reduceFunction,
  149. String initial) {
  150. List<EquipStatistics> equipStatisticsList = new ArrayList<EquipStatistics>();
  151. EquipStatistics equipStatistics = null;
  152. GroupBy groupBy = GroupBy.key("logonIp")
  153. .initialDocument(initial)
  154. .reduceFunction(reduceFunction);
  155.  
  156. GroupByResults<Session> results = mongoTemplate.group(criteria,
  157. "sessions", groupBy, Session.class);
  158. BasicDBList list = (BasicDBList)results.getRawResults().get("retval");
  159. for (int i = 0; i < list.size(); i ++) {
  160. equipStatistics = new EquipStatistics();
  161. BasicDBObject obj = (BasicDBObject)list.get(i);
  162. equipStatistics.setIp(obj.getString("logonIp"));
  163. equipStatistics.setHostName(obj.getString("hostName"));
  164. equipStatistics.setEquipmentTypeName(obj.getString("equipmentTypeName"));
  165. equipStatistics.setUserDurateion(obj.getLong("userDurateion"));
  166. equipStatisticsList.add(equipStatistics);
  167. }
  168. return equipStatisticsList;
  169. }
  170.  
  171. //去重
  172. private List<EquipStatistics> addDuration(List<EquipStatistics> equipStatisticsList,int days) {
  173.  
  174. BigDecimal base = new BigDecimal(days*8*60*60*1000+"");
  175.  
  176. if(equipStatisticsList!=null){
  177. for (int i = 0; i < equipStatisticsList.size()-1; i++) {
  178. long userDurateion_i = equipStatisticsList.get(i).getUserDurateion();
  179. equipStatisticsList.get(i).setUserdDurationStr(formatTime(userDurateion_i));
  180. //
  181. BigDecimal userDur_i = new BigDecimal(userDurateion_i);
  182. double rate = userDur_i.divide(base, 4, BigDecimal.ROUND_HALF_UP).doubleValue();
  183. equipStatisticsList.get(i).setUserRate(rate);
  184. equipStatisticsList.get(i).setUserdRateStr(rate*100 + "%");
  185. for(int j = equipStatisticsList.size()-1; j>i;j--){
  186. long userDurateion_j = equipStatisticsList.get(j).getUserDurateion();
  187. BigDecimal userDur_j = new BigDecimal(userDurateion_j);
  188. rate = userDur_j.divide(base, 4, BigDecimal.ROUND_HALF_UP).doubleValue();
  189. if(equipStatisticsList.get(i).getIp().equals(equipStatisticsList.get(j).getIp())){
  190. equipStatisticsList.get(i).setUserDurateion(userDur_i.add(userDur_j).longValue());
  191. equipStatisticsList.get(i).setUserdDurationStr(formatTime(userDur_i.add(userDur_j).longValue()));
  192. rate = userDur_i.add(userDur_j).divide(base, 4, BigDecimal.ROUND_HALF_UP).doubleValue();
  193. equipStatisticsList.get(i).setUserRate(rate);
  194. equipStatisticsList.get(i).setUserdRateStr(rate*100 + "%");
  195. equipStatisticsList.remove(j);
  196. }else{
  197. equipStatisticsList.get(j).setUserdDurationStr(formatTime(userDurateion_j));
  198. equipStatisticsList.get(j).setUserRate(rate);
  199. equipStatisticsList.get(j).setUserdRateStr(rate*100 + "%");;
  200. }
  201. }
  202. }
  203. }
  204. return equipStatisticsList;
  205. }
  206.  
  207. /*
  208. * 毫秒转化时分秒毫秒
  209. */
  210. public String formatTime(Long ms) {
  211. Integer ss = 1000;
  212. Integer mi = ss * 60;
  213. Integer hh = mi * 60;
  214. Integer dd = hh * 24;
  215.  
  216. Long day = ms / dd;
  217. Long hour = (ms - day * dd) / hh;
  218. Long minute = (ms - day * dd - hour * hh) / mi;
  219. Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
  220. Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;
  221.  
  222. StringBuffer sb = new StringBuffer();
  223. if(day > 0) {
  224. sb.append(day+"天");
  225. }
  226. if(hour > 0) {
  227. sb.append(hour+"小时");
  228. }
  229. if(minute > 0) {
  230. sb.append(minute+"分");
  231. }
  232. if(second > 0) {
  233. sb.append(second+"秒");
  234. }
  235. if(milliSecond > 0) {
  236. sb.append(milliSecond+"毫秒");
  237. }
  238. return sb.toString();
  239. }
  240.  
  241. //测试代码
  242.  
  243. public List getSessionTime() {
  244. try {
  245. CommandResult result = mongoTemplate.executeCommand("{aggregate : 'sessions', pipeline : "
  246. + "[{ $match : { logoffTime : {$exists:false} } },"
  247. // + " { $group : { _id :logonIp,logonTime:{$sum:{logonTime.valueOf()}},logoffTime:{$sum:{logffTime.va}} } },"
  248. + " { $project : { _id : 0,logonHost : 1,logonIp : 1,logonTime : 1,extraData : 1,logoffTime : 1}}]}");
  249. System.out.println(result);
  250.  
  251. GroupBy groupBy = GroupBy.key("logonIp")
  252. .initialDocument("{logonHost:'', sessionTime : 0, extraData : {}}")
  253. .reduceFunction("function(doc,result){"
  254. + "result.logonHost = doc.logonHost;"
  255. + "var time = doc.logoffTime.valueOf() - doc.logonTime.valueOf();"
  256. + "result.sessionTime +=time ;"
  257. + "result.extraData = doc.extraData}");
  258. GroupByResults<Session> results = mongoTemplate.group(Criteria.where("logoffTime").exists(true),
  259. "sessions", groupBy, Session.class);
  260. BasicDBList list = (BasicDBList)results.getRawResults().get("retval");
  261. for (int i = 0; i < list.size(); i ++) {
  262. BasicDBObject obj = (BasicDBObject)list.get(i);
  263. System.out.println(obj.get("count"));
  264. }
  265. System.out.println(results);
  266. }catch (Exception e) {
  267. System.out.println(e);
  268. }finally {
  269. try{
  270. MatchOperation matchOperation;
  271.  
  272. matchOperation = new MatchOperation(Criteria.where("logonTime")
  273. .lte(new SimpleDateFormat("yyyy-MM-dd").parse("2016-09-14"))
  274. .gte(new SimpleDateFormat("yyyy-MM-dd").parse("2016-09-12"))
  275. .andOperator(Criteria.where("logoffTime")
  276. .lte(new SimpleDateFormat("yyyy-MM-dd").parse("2016-09-14"))
  277. .gte(new SimpleDateFormat("yyyy-MM-dd").parse("2016-09-12")))
  278. );
  279.  
  280. GroupOperation groupOperation = new GroupOperation(Fields.fields("logonIp"));
  281.  
  282. ProjectionOperation projectionOperation = new ProjectionOperation(Fields.fields("_id"));
  283.  
  284. Aggregation aggregation = Aggregation.newAggregation(matchOperation,groupOperation,projectionOperation);
  285.  
  286. AggregationResults<Object> groupResults
  287. = mongoTemplate.aggregate(aggregation, "sessions", Object.class);
  288.  
  289. List<Object> groupList = groupResults.getMappedResults();
  290. for (Object object : groupList) {
  291. System.out.println(object.toString());
  292. }
  293. } catch (ParseException e) {
  294. e.printStackTrace();
  295. }
  296. }
  297. return null;
  298. }
  299.  
  300. }

EquipmentRepository.java

  1. //查询数据库
  2. private List<EquipStatistics> searchDB(Criteria criteria, String reduceFunction,
  3. String initial) {
  4. List<EquipStatistics> equipStatisticsList = new ArrayList<EquipStatistics>();
  5. EquipStatistics equipStatistics = null;
  6. GroupBy groupBy = GroupBy.key("logonIp")
  7. .initialDocument(initial)
  8. .reduceFunction(reduceFunction);
  9.  
  10. GroupByResults<Session> results = mongoTemplate.group(criteria,
  11. "sessions", groupBy, Session.class);
  12. BasicDBList list = (BasicDBList)results.getRawResults().get("retval");
  13. for (int i = 0; i < list.size(); i ++) {
  14. equipStatistics = new EquipStatistics();
  15. BasicDBObject obj = (BasicDBObject)list.get(i);
  16. equipStatistics.setIp(obj.getString("logonIp"));
  17. equipStatistics.setHostName(obj.getString("hostName"));
  18. equipStatistics.setEquipmentTypeName(obj.getString("equipmentTypeName"));
  19. equipStatistics.setUserDurateion(obj.getLong("userDurateion"));
  20. equipStatisticsList.add(equipStatistics);
  21. }
  22. return equipStatisticsList;
  23. }

分组查询主要使用org.springframework.data.mongodb.core.mapreduce.GroupBy这个spring中的类:

例:

GroupBy groupBy = GroupBy.key("logonIp")
.initialDocument(initial)
.reduceFunction(reduceFunction);
GroupByResults<T> results = mongoTemplate.group(criteria,
"sessions", groupBy, T.class);

GroupBy.key('key'): key是所进行分组字段的字段名;

initial : 初始化对象,可理解为最后查询返回的数据初始化;

reduceFunction: js函数,用于对返回的结果进行处理操作;

function(doc,result){}:

doc是根据查询条件(相当于where条件)获取的每一条数据,result是最后的查询结果,初始值就是initial对象;

查询操作:

mongoTemplate.group(criteria,"session", groupBy, T.class);

criteria:相当于SQL中的where条件;

session: 数据库中的表名;

groupBy: -以上;

T.class: 这里是数据库表对应的domain

BasicDBList list = (BasicDBList)results.getRawResults().get("retval")

获取结果转为BasicDBList,"retval"是固定值,必须是它;

BasicDBObject obj = (BasicDBObject)list.get(i);  obj.getString("key");

key为initial中的key值,通过以上代码获取key值对应的value;

这只是其中一种用法......

MongoDB数据库GroupBy查询使用Spring-data-mongondb的实现的更多相关文章

  1. MongoDB数据库中查询数据(下)

    MongoDB数据库中查询数据(下) 在find中,options参数值为一个对象,用来设置查询数据时使用的选项,下面我们来对该参数值对象中可以使用的属性进行介绍: 1. fields; 该属性值为一 ...

  2. 在MongoDB数据库中查询数据(上)

    在MongoDB数据库中查询数据(上) 在MongoDB数据库中,可以使用Collection对象的find方法从一个集合中查询多个数据文档,find方法使用方法如下所示: collection.fi ...

  3. python 操作mongodb数据库模糊查询

    # -*- coding: utf-8 -*-import pymongoimport refrom pymongo import MongoClient #创建连接#10.20.66.106clie ...

  4. mongodb关联查询 和spring data mongodb

    GITHUB:https://github.com/peterowang/Springdata-mongo 使用DBRefs DBRefs中有三个字段 - $ref - 此字段指定引用文档的集合 $i ...

  5. mongodb数据库js查询

    #健康风险-disease db.disease.find({versions:'2'}).forEach(function(item){ item.diseaseDetail && ...

  6. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  7. Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)

    一.简介 Spring Data  MongoDB 项目提供与MongoDB文档数据库的集成.Spring Data MongoDB POJO的关键功能区域为中心的模型与MongoDB的DBColle ...

  8. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  9. SpringBoot入门 (五) 数据库访问之spring data jpa

    本文记录学习使用spring data jpa访问数据库 一 什么是Spring Data JPA JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java ...

随机推荐

  1. JVM探索之——内存管理(一)

    本系列的第一篇文章,预计本系列最后面会有两三个案例. Java与C.C++不一样Java不需要Coder进行手动内存管理,而这一切都交给JVM进行自动内存管理,这从某种程度上来说也减轻了我们Coder ...

  2. 从本地向 Github 上传项目步骤攻略(快速上手版)

    最近想把之前自己做的一些好玩的项目共享到Github,网上找了一圈上传教程,都感觉写的太深奥.复杂,云里雾里,特把自己的方法纪录如下: PS:这种方式一般适用于:开始做项目时,没有直接在github上 ...

  3. my_atoi()

    void my_atoi(const char* s){ int i=0,res=0; if(*s<='9' && *s>='0'){ //如果输入的一个字符是数字 for ...

  4. Redisd VS Memcached

    Redis也常常被当作 Memcached的挑战者被提到桌面上来.关于Redis与Memcached的比较更是比比皆是.然而,Redis真的在功能.性能以及内存使用效率上都超越了Memcached吗? ...

  5. 描述Linux系统开机到登陆界面的启动过程(计时2分钟)

    简述: 1.开机BIOS自检 2.MBR引导 3.grub引导菜单 4.加载内核kernel 5.启动init进程 6.读取inittab文件,执行rc.sysinit,rc等脚本 7.启动minge ...

  6. ubuntu16.04下vim安装失败

    问题? 重装了ubuntu系统,安装vim出现了以下问题:   sudo apt-get install vim   正在读取软件包列表... 完成 正在分析软件包的依赖关系树        正在读取 ...

  7. JAVA构造函数(方法)与方法是啥意思

    成员方法必须有返回类型即使是没有返回,也要写上void 构造函数(方法)没有返回类型,而且和类名一样!一个类里面,一看就知道了譬如:public class Test{public Test(){} ...

  8. Vim命令大全

    1.进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于 ...

  9. PHP读取超大文件的实例代码

    数据量大带来的问题就是单个文件很大,能够打开这个文件相当不容易,记事本就不要指望了,果断死机   去年年底的各种网站帐号信息的数据库泄漏,很是给力啊,趁机也下载了几个数据库,准备学学数据分析家来分析一 ...

  10. label的for属性

    一.使用介绍 <label>专为input元素服务,为其定义标记. for属性规定label与哪个表单元素绑定 label和表单控件绑定方式又两种: 1.将表单控件作为label的内容,这 ...