【已解决】Nodejs mongoose 日期聚合的问题

【已解决】Nodejs mongoose 日期聚合的问题

##文档

{
   "_id": ObjectId("53c4190a4572483830000053"),
   "sendfrom": "joy",
   "sendto": "iphone",
   "sendtitle": "新趋势",
   "user": "han",
   "create_at": ISODate("2014-07-14T17: 53: 14.499Z") 
}

文档是这样的要我如何使用聚合函数Aggregation 根据日期来分组啊

请大神指导,指导。谢谢啦。

最后采用方式:

Sendinfo.getallday = function(user, callback) {
	var date = new Date();
	var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
	var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
	var group={
//		key: {user:1,create_at:1},
		keyf: function(sendinfos) {
				var date = new Date(sendinfos.create_at);
				var dateKey = (date.getMonth()+1)+"/"+date.getDate()+"/"+date.getFullYear()+'';
				return {'day':dateKey,'user':sendinfos.user};//返回值
			},//格式化日期
	cond: {'user':user}, //查询条件   		cond: {'user':user, 'create_at': { $gt:firstDay,$lt:lastDay}}, //查询条件
	initial: {count:0}, //初始值
	reduce: function(obj, prev) {prev.count++;},
	finalize:{}
};
SendinfoModel.collection.group(
	group.keyf,
    group.cond, //查询条件
    group.initial, //初始值
   group.reduce,
   group.finalize,
   true,//reduce
   function(err,sendinfos){
   	  if (err) {
            return callback(err);
          }
   	  console.log("new Date(1):"+new Date().setDate(1)+",new Date(31):"+new Date().setDate(31)+","+sendinfos);
   	  callback(null,sendinfos);
   }
);

};


6 回复

当然,我可以帮助你解决这个问题。你需要根据日期对数据进行分组,并且还需要过滤特定用户的数据。这里提供一个更简洁的解决方案,使用Mongoose的聚合框架(aggregation framework)来实现这个功能。

示例代码

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 假设你已经定义了Schema
const SendinfoSchema = new Schema({
    sendfrom: String,
    sendto: String,
    sendtitle: String,
    user: String,
    create_at: { type: Date, default: Date.now }
});

const Sendinfo = mongoose.model('Sendinfo', SendinfoSchema);

// 定义一个方法来获取指定用户的按日分组数据
Sendinfo.getallday = function(user, callback) {
    const date = new Date();
    const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
    const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);

    Sendinfo.aggregate([
        {
            $match: {
                user: user,
                create_at: { $gte: firstDay, $lte: lastDay }
            }
        },
        {
            $project: {
                day: { $dateToString: { format: "%m/%d/%Y", date: "$create_at" } },
                user: 1
            }
        },
        {
            $group: {
                _id: "$day",
                count: { $sum: 1 }
            }
        }
    ]).exec((err, result) => {
        if (err) {
            return callback(err);
        }
        callback(null, result);
    });
};

// 使用示例
Sendinfo.getallday('han', (err, data) => {
    if (err) {
        console.error(err);
    } else {
        console.log(data);
    }
});

解释

  1. $match:首先过滤出特定用户(user: 'han')并且日期在当月范围内的文档。
  2. $project:将日期转换为字符串格式(例如 07/14/2023),并保留用户字段。
  3. $group:根据转换后的日期字段 day 进行分组,并计算每个分组的数量(即计数)。

这种方法利用了Mongoose的聚合框架,更加简洁且易于理解。你可以通过这种方式轻松地对数据进行日期分组和统计。


我觉得是 mapreduce 利用 create_at 字段来做

function map(){

var date = this.create_at; var year = date.getUTCFullYear(); var month = date.getUTCMonth(); month = month + 1; var day = date.getUTCDate();

var dateStr  = year + "-" + month  + "-" + day;
emit(dateStr, this);

} function reduce(key, values){ return {date:key, values:values}; } db.xxx.mapReduce(map, reduce, {out:“xxx_map_reduce”})

我这里要求的好像是每天,每个用户的分组总数,用mapReduce,好像有些问题

根据你的描述,你希望使用Mongoose的聚合框架来根据日期对文档进行分组。在Mongoose中,你可以使用aggregate()方法来进行复杂的查询和聚合操作。下面是针对你提供的数据结构,如何使用聚合框架来按日期分组的例子。

示例代码

Sendinfo.getallday = function(user, callback) {
    SendinfoModel.aggregate([
        // 匹配特定用户
        { $match: { user: user } },
        // 将日期转换为指定格式
        {
            $project: {
                user: 1,
                create_at: {
                    $dateToString: { format: "%m/%d/%Y", date: "$create_at" }
                }
            }
        },
        // 按日期分组,并计算每个日期的数量
        {
            $group: {
                _id: "$create_at",
                count: { $sum: 1 }
            }
        }
    ], function(err, result) {
        if (err) {
            return callback(err);
        }
        callback(null, result);
    });
};

解释

  1. $match: 首先,我们匹配特定的用户。
  2. $project: 使用$dateToStringcreate_at字段转换成MM/DD/YYYY格式的字符串。
  3. $group: 按照转换后的日期字段分组,并使用$sum计算每天的记录数量。

这样,你就可以得到一个结果数组,其中每个元素代表一天,并且包含这一天的记录总数。这种方法更符合现代Mongoose的最佳实践,并且利用了MongoDB的原生聚合功能。

回到顶部