mongodb按照时间分组统计

使用spring data mongodb v1.8

需求1、

数据结构如下。说明:改集合记录的是公司各个系统的访问情况(localPath表示系统,requestTime 表示请求时间,字符串类型,)

需求:选中某一天,然后按照系统和小时进行分组,统计这一天中每个小时各个系统的访问情况。

业务代码:

Criteria criteria = new Criteria();
criteria.andOperator(Criteria.where("createTime").lt(DateUtil.addDay(sdf.parse(sdf.format(date)), 1)), Criteria.where("createTime").gte(sdf.parse(sdf.format(date))));
// 匹配查询
MatchOperation matchOperation = Aggregation.match(criteria);// localPath
// 返回参数
ProjectionOperation return1 = Aggregation.project("localPath").andExpression("substr(requestTime,11,2)").as("dimension");
// 按条件分组
GroupOperation go2 = Aggregation.group("dimension", "localPath").count().as("times");
// 设置排序
SortOperation sortOperation = Aggregation.sort(Sort.Direction.ASC, "localPath", "dimension");
// 构建参数
Aggregation aggregation = Aggregation.newAggregation(matchOperation, return1, go2, sortOperation);
// 分组聚合查询
AggregationResults<SysCountResultVo> aggregate = mongoTemplate.aggregate(aggregation, getCollectionName(date), SysCountResultVo.class);
// 获取结果
List<SysCountResultVo> resultVos = aggregate.getMappedResults();

SysCountResultVo类

public class SysCountResultVo {
    /**次数**/
    private int times;
    /**服务**/
    private String localPath;
    /**维度**/
    private String dimension;

    public int getTimes() {
	return times;
    }

    public void setTimes(int times) {
	this.times = times;
    }

    public String getLocalPath() {
	return localPath;
    }

    public void setLocalPath(String localPath) {
	this.localPath = localPath;
    }

    public String getDimension() {
	return dimension;
    }

    public void setDimension(String dimension) {
	this.dimension = dimension;
    }

    @Override
    public String toString() {
	return "SysCountResultVo [times=" + times + ", localPath=" + localPath + ", dimension=" + dimension + "]";
    }

}

需求二、

数据结构如下。说明:该集合存储的是投递信息(isView 表示的类型,deliveryTime 表示 投递时间)

需求:

选择一个时间段,要求按天和投递类型进行分组统计。

难点:

mongodb存储的时间是utc时间,这个时间比本地时间少8个小时,例如 本地时间为:2018.7.18 00:00:00日,mongodb中存储的是 2018.7.17 t16:00:00z之类的东西。

按天统计的时候,如果集合中存了字符处,可以使用需求1中的方法,使用substr函数进行处理。但是如果像需求2中,没有存储字符串,怎么办?以下是我的思路。

service

Criteria criteria = new Criteria();
	/**此处设置匹配条件**/
	// 匹配查询
	MatchOperation matchOperation = Aggregation.match(criteria);
	// 返回参数,对日期进行处理
	ProjectionOperation return1 = Aggregation.project("isView").andExpression("year(deliveryTime)").as("year").andExpression("month(deliveryTime)").as("month").andExpression("dayOfMonth(deliveryTime)").as("day").andExpression("hour(deliveryTime)").as("hour");
	// 按条件分组
	GroupOperation go2 = Aggregation.group("isView", "year", "month", "day", "hour").count().as("times");
	// 设置排序
	SortOperation sortOperation = Aggregation.sort(Sort.Direction.ASC, "times");
	// 构建参数
	Aggregation aggregation = Aggregation.newAggregation(matchOperation, return1, go2, sortOperation);
	// 分组聚合查询
	AggregationResults<SysCountResultVo> aggregate = mongoTemplate.aggregate(aggregation, "resumeDeliveryRecordVo", SysCountResultVo.class);
	// 获取结果
	List<SysCountResultVo> resultVos = aggregate.getMappedResults();

SysCountResultVo类

public class SysCountResultVo {
    /**次数**/
    private int times;
    /**服务**/
    private String isView;
    /**年**/
    private Integer year;
    /**月**/
    private Integer month;
    /**日**/
    private Integer day;
    /**小时**/
    private Integer hour;
    /**时间**/
    private String time;

    private String isViewStr;

    public int getTimes() {
	return times;
    }

    public void setTimes(int times) {
	this.times = times;
    }

    public String getIsView() {
	return isView;
    }

    public void setIsView(String isView) {
	this.isView = isView;
    }

    public Integer getYear() {
	return year;
    }

    public void setYear(Integer year) {
	this.year = year;
    }

    public Integer getMonth() {
	return month;
    }

    public void setMonth(Integer month) {
	this.month = month;
    }

    public Integer getDay() {
	return day;
    }

    public void setDay(Integer day) {
	this.day = day;
    }
    // 此处为重点,如果时>=16,则认为是下一天
    public String getTime() {
	try {
	    if (hour >= 16) {
		return DateUtil.date2DateStr(DateUtil.addDay(DateUtil.dateStr2Date(this.getYear() + "-" + this.getMonth() + "-" + this.getDay(), DateUtil.PATTERN_DTSHORTLINE), 1), DateUtil.PATTERN_DTSHORTLINE);
	    }
	    return this.getYear() + "-" + this.getMonth() + "-" + this.getDay();
	} catch (Exception e) {
	    e.printStackTrace();
	}
	return null;
    }

    public Integer getHour() {
        return hour;
    }

    public void setHour(Integer hour) {
        this.hour = hour;
    }

    public void setTime(String time) {
	this.time = time;
    }

    public String getIsViewStr() {
	return Integer.valueOf(isView) == 1 ? "未查看" : Integer.valueOf(isView) == 2 ? "待沟通" : Integer.valueOf(isView) == 4 ? "已查看" : Integer.valueOf(isView) == 6 ? "不合适" : "其他";
    }

    public void setIsViewStr(String isViewStr) {
	this.isViewStr = isViewStr;
    }

    @Override
    public String toString() {
	return "time:" + getTime() + ";times:" + getTimes() + ";isView:" + getIsView();
    }

}

可能说明的不是很清楚,不过可以作为一个参考。我的QQ:1208576787,如有什么问题,可以加QQ讨论下。

原文地址:http://blog.51cto.com/fengcl/2146887

时间: 2024-10-08 18:16:21

mongodb按照时间分组统计的相关文章

Oracle按不同时间分组统计

Oracle按不同时间分组统计 Oracle按不同时间分组统计的sql 如下表table1: 日期(exportDate) 数量(amount) -------------- ----------- 14-2月 -08 20 10-3月 -08 2 14-4月 -08 6 14-6月 -08 75 24-10月-09 23 14-11月-09 45 04-8月 -10 5 04-9月 -10 44 04-10月-10 88 注意:为了显示更直观,如下查询已皆按相应分组排序 1.按年份分组 sel

Mongodb按照日期分组统计

目录 1.使用时间格式化方法 2.进行时间补偿(默认当前时区是东八区,即8x3600x1000=28800000) mongodb的默认时间是格林尼治时间,如果是要按照日期进行分组需要注意!!!. 解决方案: 1.使用时间格式化方法 Aggregation.project().and("createTime").dateAsFormattedString("%Y-%m-%d").as("time"), Aggregation.group(&quo

[Mongo]分组统计时间 aggregate,group,distinct

开发中有些按日期记录的记录需要各种维度的统计,按天,按月,按年,按小时,..分组统计,还有些需要对字段去重统计,在之前的 [Mongo] 按时间分组统计(group时间格式化)  中用group实现了按天的统计,不过使用new Date()方法会有些坑,今天看了下aggregate中,使用聚合来写个时间统计. tips: aggregate 挺复杂,弄明白了再做笔记,现在只是根据需求来查询. 数据结构还是: /* 0 */ { "_id" : ObjectId("541fcc

MongoDB的分组统计 group

mongodb中的分组聚合用$group,它是不能进行sort的,使用格式如下: { $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } } 其中_id属性是必须要有的,目的是用来指定分组的字段或依据,field1为自定义字段,accumulator为累加器,下面以统计每天用户注册数为列 db.user.aggregate([ { $group:{

010.简单查询、分组统计查询、多表连接查询(sql实例)

-------------------------------------day3------------ --添加多行数据:------INSERT [INTO] 表名 [(列的列表)] --SELECT UNION --SELECT 'HAHA',1,32--UNION ALL --全部显示/显示重复数据 即使集合相同--UNION---------将查询的两个结果集合并.结构必须一致 -->常见面试题 --SELECT 'HEHE',2,33------将查询结果添加到列表中(子查询)IN

MySql按周/月/日分组统计数据的方法

知识关键词:DATE_FORMAT select DATE_FORMAT(create_time,'%Y%u') weeks,count(caseid) count from tc_case group by weeks; select DATE_FORMAT(create_time,'%Y%m%d') days,count(caseid) count from tc_case group by days; select DATE_FORMAT(create_time,'%Y%m') month

【案例分享】电力设备生产数据的多层分组统计报表实现

多层分组统计报表即按照不同的数据字段,形成多级分组,并分层级进行合计. 传统报表的实现方式大多基于 Table 控件,虽然可实现多个分组功能,但在报表显示方面有限制,只能呈现上下级的分组,而现代的复杂报表的需求,通常是左右级嵌套,有时甚至要求相同内容的单元格合并,使用 Table 控件,有太多的局限,有了矩表控件,通过简单的拖拽就能轻松实现多层分组报表,不管有多少个分组和分组小计都能简单解决. 下面会通过一个具体的案例,使用葡萄城报表中的矩表控件来讲解实现多层分组统计报表. (一)原始数据 (二

Dev用于界面按选中列进行分组统计数据源(实用技巧)

如果有用U8的可以明白这个功能就是模仿他的统计功能.我不过是把他造成通用的与适应于DEV的. (效率为6000条数据分组统计时间为3秒左右分组列过多5秒.1000条以下0.几秒,500条下0.00几秒) 前置准备 需求DevExpress.XtraGrid.Views.Grid.GridView 一个grid数据源.原生为DataGridView .Dev重写为gridview 由于Dev的绑定entity与datatable绑定上去Gridview类型会不一致.前者导致gridview.Get

Oracle按时间段分组统计

想要按时间段分组查询,首先要了解level,connect by,oracle时间的加减. 关于level这里不多说,我只写出一个查询语句: ----level 是一个伪例 select level from dual connect by level <=10 ---结果: 1 2 3 4 5 6 7 8 9 10 关于connect by可以看 http://www.cnblogs.com/johnnyking39/articles/1155497.html oracle时间的加减看看试一下