如何在Mongoose / Mongodb中创build一个查询来获取这个json?

我试图从我的MongoDB中获得这样的对象,每月计算操作系统:

{January: {Android: 30, iOS: 10, winPhone: 5}, February: {Android: 4, iOS: 40}, etc}.

这是我的mongoose模式:

 var MySchema = new Schema({ date: {type: Date, default: Date.now}, os: String }); 

可以给我一个人的想法? 有没有办法创build一个单一的查询返回给我整个对象,或者我应该一块一块地构build它,统一多个查询?

谢谢!

你可能最好使用一个输出结构,这对于MongoDB来说更自然,其中键是静态的,而且值包含数据。 那么你可以使用一个聚合pipe道来做到这一点:

 MyModel.aggregate([ // Group the docs by month & os {$group: {_id: {month: {$month: '$date'}, os: '$os'}, count: {$sum: 1}}}, // Group again by just month {$group: {_id: '$_id.month', counts: {$push: {os: '$_id.os', count: '$count'}}}}, // Rename _id to month {$project: {month: '$_id', counts: 1, _id: 0}} ], callback); 

其中产生如下输出:

 { "result" : [ { "counts" : [ { "os" : "winPhone", "count" : 2 }, { "os" : "iOS", "count" : 1 }, { "os" : "Android", "count" : 2 } ], "month" : 1 }, { "counts" : [ { "os" : "iOS", "count" : 2 }, { "os" : "Android", "count" : 1 } ], "month" : 2 } ], "ok" : 1 } 

如果你真的想要原始的格式,然后可以后处理的结果重塑它,但是你想要的。

既然你想要在输出中把键值作为键值 ,你不能通过聚合pipe道来实现。 没有一个pipe道操作员接受值作为关键字。 你需要写地图缩小function。 根据年份对logging进行分组的mapfunction。 所以year是关键。 价值是每个os名称和它被卖的“月”。

mapfunction:

 var map = function(){ emit(this.date.getFullYear(), {"month":this.date.getMonth(),"os":this.os}); } 

现在每个组的reduce函数现在汇总了当年在一个月内销售的不同types oscount

 var reduce = function(id,osArr){ var result = {}; var osCount = {}; var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; for(var i=0;i<osArr.length;i++) { var mon = monthNames[(osArr[i].month)-1]; if(!osCount.hasOwnProperty(mon)) { osCount[mon] = {}; } if(osCount[mon].hasOwnProperty(osArr[i].os)) { osCount[mon][osArr[i].os]++; } else { osCount[mon][osArr[i].os] = 1; } } result[id] = osCount; return result; } 

调用集合上的map reduce函数并将其转储到名为“temp”的新集合。

 var o = {}; o.map = map; o.reduce = reduce; o.out = { replace: 'temp' } o.verbose = true; ModelName.mapReduce(o, function (err, results) { console.log(results) }) 

这会产生以下样本结果:

 > db.temp.find({},{"value":1,"_id":0}) { "value" : { "2013" : { "November" : { "Android" : 2, "ios" : 2, "blackberry" : 1 } } } } { "value" : { "2014" : { "October" : { "Android" : 3, "ios" : 2 } } } }