我是MongoDB和mongoose的新手,我希望每天从开始日期到当前日期获得订阅者总数.换句话说,我需要在白天对所有订阅者进行分组,并且每天我需要总结以前的所有订阅者. 以下是我的一些文件
以下是我的一些文件:
{ "_id" : ObjectId("574cef8ee62502d08f34c075"), "userId" : "a7zd609h54wm5kt", "subscribedAt" : ISODate("2016-05-30T18:22:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.098Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c076"), "userId" : "3q2tvd53zcap5mq", "subscribedAt" : ISODate("2016-05-30T19:52:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.113Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c077"), "userId" : "nvx8mnu1xis5jxt", "subscribedAt" : ISODate("2016-05-28T19:52:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.117Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c078"), "userId" : "l7eedg616r0zbdf", "subscribedAt" : ISODate("2016-05-28T16:28:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.122Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c079"), "userId" : "9r1wl8ao8bls7g7", "subscribedAt" : ISODate("2016-05-28T11:05:05Z"), "isSubscribed" : false, "createdAt" : ISODate("2016-05-31T01:57:34.125Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c07a"), "userId" : "ygwve2e47p7fanl", "subscribedAt" : ISODate("2016-05-29T00:28:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.125Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c07b"), "userId" : "1gxspx9jypwc9tu", "subscribedAt" : ISODate("2016-05-29T19:52:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.127Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c07c"), "userId" : "hvy4xjppos8ch2b", "subscribedAt" : ISODate("2016-05-29T01:36:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.127Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c07d"), "userId" : "bmpql2d7wkl0jnw", "subscribedAt" : ISODate("2016-05-29T21:50:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.127Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c07e"), "userId" : "uir99sy6q3p6i0i", "subscribedAt" : ISODate("2016-05-29T08:22:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.131Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c07f"), "userId" : "qmzn3rz308ku017", "subscribedAt" : ISODate("2016-05-29T22:02:05Z"), "isSubscribed" : false, "createdAt" : ISODate("2016-05-31T01:57:34.132Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c080"), "userId" : "ok46sxaf8urrqtj", "subscribedAt" : ISODate("2016-05-29T07:33:05Z"), "isSubscribed" : false, "createdAt" : ISODate("2016-05-31T01:57:34.132Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c081"), "userId" : "ot4nmxqsn4o98vn", "subscribedAt" : ISODate("2016-05-29T23:52:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.138Z"), "__v" : 0 } { "_id" : ObjectId("574cef8ee62502d08f34c082"), "userId" : "2voy5ttkk39i1f0", "subscribedAt" : ISODate("2016-05-30T00:52:05Z"), "isSubscribed" : true, "createdAt" : ISODate("2016-05-31T01:57:34.138Z"), "__v" : 0 }
所以我在2016-05-28有2个用户,2016-05-29有6个用户,2016-05-30有3个用户,
我希望实现的结果是这样的
{ "results" : [ { "date" : ISODate("2016-05-28T00:00:00Z"), "subscribers" : 2 }, { "date" : ISODate("2016-05-29T00:00:00Z"), "subscribers" : 8 }, { "date" : ISODate("2016-05-30T00:00:00Z"), "subscribers" : 11 }, ] }
我用以下代码尝试了Aggregation Framework:
var express = require('express'), router = express.Router(), User = require('../models/user'); router.get('/', function(req, res, next) { User.aggregate([ { $match: { isSubscribed: true, subscribedAt: {$gte: new Date("2016-05-28T00:00:00+01:00"), $lte: new Date()}} }, { $group: { _id: {$dateToString: { format: "%Y-%m-%d", date: "$subscribedAt" }}, count : { $sum : 1 } }, }, { $project: { _id : 0, subscribeDate : "$_id", count : 1 } }, { $sort: {subscribeDate: 1} } ], function(err, result){ if (err) { console.log("This is an error find the user!") } res.render('dashboard', {results: result, title: "Welcome to analytics dashboard!"}); }); }); module.exports = router;
但这只给了我每天的总用户数,而不是以前所有用户的总和.
{ "count" : 2, "subscribeDate" : "2016-05-28" } { "count" : 6, "subscribeDate" : "2016-05-29" } { "count" : 3, "subscribeDate" : "2016-05-30" }
我也尝试使用以下代码建议的here mapReduce:
var express = require('express'), router = express.Router(), User = require('../models/user'), DailySubscriber = require('../models/dailySubscriber'); router.get('/', function(req, res, next) { var userObject = { "query": {isSubscribed: true}, "out": "dailySubscriber" }; userObject.map = function () { var date = new Date(this.subscribedAt.valueOf() - (this.subscribedAt.valueOf() % (1000 * 60 * 60 * 24 ))); emit(date, 1) } userObject.reduce = function (k, vals) { return vals.length } User.mapReduce(userObject, function (err, results) { //console.log(results) }) var subscriberObject = { "scope": { "total": 0 }, "finalize": function(key, value) { total += value; return total; }, "out": "totalSubscriber" }; subscriberObject.map = function () { emit(this._id, this.value) } subscriberObject.reduce = function (k, vals) { return vals.length } DailySubscriber.mapReduce(subscriberObject, function (err, total) { console.log("This is the result" + total) }) res.render('dashboard', {title: "Welcome to analytics dashboard!"}); }); module.exports = router;
当我运行我的节点应用程序并且我收到错误时,这不起作用这是在控制台中未定义的结果,但是它在MongoDB Shell中工作时具有以下结果,这非常接近我想要但仍然不那么理想,它始终显示_id和值作为键和值.
{ "results" : [ { "_id" : ISODate("2016-05-28T00:00:00Z"), "value" : 2 }, { "_id" : ISODate("2016-05-29T00:00:00Z"), "value" : 8 }, { "_id" : ISODate("2016-05-30T00:00:00Z"), "value" : 11 }, ] }
这样做的最佳方式是什么?我正在使用Node.js,Express和Mongoose,如果有帮助的话.
任何帮助将非常感激!提前致谢!
imho – 具有每日总和的聚合框架是我们可以从mongo中挤出的最好的.由于(来自sql world)我们没有CTE,我们不能参考以前的文档,这使得一些分析变得困难.在这种情况下,我将做的只是简单的forEach循环并更新sum值,在这种特殊情况下创建移动Sum.这将要求数据需要从最旧到最新排序.下面的一个sudocode:
var previous = 0; forEach (var r in result) { r.count += previous; previous = r.count; }