mongoDB的管道是个好东西,它能够将不少操做批处理实现,即将多个命令放入一个管道,而后去顺序的执行它们,今天我要说的是,利用管道中的分组来实现实现中的ditinct+group的效果,即先对一个元素去重,而后即一个字段进行分组,如你的userinfoID,它对应多个planID,而咱们在planID在表中确定是重复的,这时,咱们须要统计userinfo对应多个种planID,这时问题就来了,尤于planID是重复的,因此分组的结果多是错误的,它并非真正意思上的(planID种类),正确的做法应该是先对planID去重复,而后再根据userinfoID去做分组,而这个在大多数的数据库里,是经过多重分组实现的,即选对userinfoID和planID进行分组,而后对结果进行userinfoID的分组,这种就把多于的planID去掉了。数据库
具体做法:数组
//多分组(group+distinct) db.M_User_Footprints.aggregate([ { $group: { _id: { UserInfoID: "$UserInfoID", ObjID: "$PlayVideo.ObjID" } } }, { $group: { _id: "$_id.UserInfoID", count: { $sum: 1 } } }, { $sort: { "_id": 1 } } ]);
注意,这里的第二个分组用的是第一个分组的_id,因此加上了$_id,这表示使用上面group的数据源来做为第二个分组的键。ide
而若是只是单个分组,就很容易实现了,也看一下代码this
//单分组 db.M_User_Footprints.aggregate([ { $group: { _id: "$UserInfoID", result: { $sum: 1 } } } ])
从上面两段代码咱们能够看到,分组键必须用_id,分组的结果名称能够本身定义,{$sum:1}每次自加1。it
下面使用map...reduce也能够实现分组的功能io
db.runCommand({ mapreduce: "M_User_Footprints", map: function Map() { emit( { "UserInfoID": this.UserInfoID, "ObjID": this.PlayVideo.ObjID } , { count: 1 } ); }, reduce: function Reduce(key, values) { total = 0;//定义一个变量total , values是一个数组 for (var i in values) { total += values[i].count } return { "count": total }; }, finalize: function Finalize(key, reduced) { return reduced; }, out: { inline: 1 } });