2015-10-27 44 views
1

我有一个简单集合,仅仅通过状态返回一定时间帧之间的用户的总和。MongoDB的骨料包括伪数据

User.aggregate([ 
    { 
    $match: { 
     "created" : { 
      $gt: startDate, 
      $lt: endDate 
     } 
    } 
    }, 
    { 
    $group: { 
     "_id": "$status", 
     "count" : { 
     $sum: 1 
     } 
    } 
    } 
]) 

我想要做的是在日期范围内显示每天的数据,即使没有数据。

因此,举例来说,结果可能最终会是这样的:

[{ 
'_id' : '01-15-2015', 
    status_counts: { 
    'active': 15, 
    'inactive': 25, 
    'removed': 2 
    } 
}, 
{ 
'_id' : '01-16-2015', 
    status_counts: { 
    'active': 0, 
    'inactive': 0, 
    'removed': 0 
    } 
}, 
{ 
'_id' : '01-17-2015', 
    status_counts: { 
    'active': 25, 
    'inactive': 5, 
    'removed': 1 
    } 
}] 

任何想法我怎么会去这样做?基本上总结所有状态并按天分组,但如果没有数据存在,请将默认数据清零?

示例数据:

[{ 
    "_id" : ObjectId("55413bc29d41675785bf7ed2"), 
    "status" : "active", 
    "created" : ISODate("2015-10-11T17:25:46.843Z") 
}, 
{ 
    "_id" : ObjectId("55413bc29d41675785bf7ed2"), 
    "status" : "inactive", 
    "created" : ISODate("2015-10-12T17:25:46.843Z") 
}, 
{ 
    "_id" : ObjectId("55413bc29d41675785bf7ed2"), 
    "status" : "removed", 
    "created" : ISODate("2015-10-12T17:25:46.843Z") 
}, 
{ 
    "_id" : ObjectId("55413bc29d41675785bf7ed2"), 
    "status" : "active", 
    "created" : ISODate("2015-10-14T17:25:46.843Z") 
}, 
{ 
    "_id" : ObjectId("55413bc29d41675785bf7ed2"), 
    "status" : "active", 
    "created" : ISODate("2015-10-14T17:25:46.843Z") 
}, 
{ 
    "_id" : ObjectId("55413bc29d41675785bf7ed2"), 
    "status" : "active", 
    "created" : ISODate("2015-10-17T17:25:46.843Z") 
}] 

结果举例:

[{ 
    "_id":"10-11-2015", 
    "status_counts": { 
     "active":1, 
     "inactive":0, 
     "removed":0 
    } 
}, 
{ 
    "_id":"10-12-2015", 
    "status_counts": { 
     "active":0, 
     "inactive":1, 
     "removed":1 
    } 
}, 
{ 
    "_id":"10-13-2015", 
    "status_counts": { 
     "active":0, 
     "inactive":0, 
     "removed":0 
    } 
}, 
{ 
    "_id":"10-14-2015", 
    "status_counts": { 
     "active":2, 
     "inactive":0, 
     "removed":0 
    } 
}, 
{ 
    "_id":"10-15-2015", 
    "status_counts": { 
     "active":0, 
     "inactive":0, 
     "removed":0 
    } 
}, 
{ 
    "_id":"10-16-2015", 
    "status_counts": { 
     "active":0, 
     "inactive":0, 
     "removed":0 
    } 
}, 
{ 
    "_id":"10-17-2015", 
    "status_counts": { 
     "active":1, 
     "inactive":0, 
     "removed":0 
    } 
}] 

回答

1

使用下面的管道,其中管道在$project阶段,即由每月仅由一个新的属性创建一个文档天的年使用date aggregation operatorsstring operators$concat$subtr运营商做的字符串操作。然后,您可以使用新的属性在前面$group流水线工序组密钥,并通过使用$cond运营商能够评估状态的类型和值分配给$sum获得相应的状态计数。闭幕$project流水线阶段则重塑的最后文件的子文档内提供所需的字段:

User.aggregate([ 
    { 
     "$match": { 
      "created": { "$gt": startDate, "$lt": endDate } 
     } 
    }, 
    { 
     "$project": { 
      "_id": 0, "status": 1, 
      "dayPart": { 
       "$concat" : [ 
        { 
         "$substr": [ {"$month" : "$created"}, 0, 2 ] 
        }, "-", 
        { 
         "$substr": [ {"$dayOfMonth" : "$created"}, 0, 2 ] 
        }, "-", 
        { 
         "$substr": [ {"$year" : "$created"}, 0, 4 ] 
        } 
       ] 
      } 
     } 
    }, 
    { 
     "$group": { 
      "_id": "$dayPart",    
      "active_count": { 
       "$sum": { 
        "$cond": [ { "$eq": [ "$status", "active" ] }, 1, 0 ] 
       } 
      }, 
      "inactive_count": { 
       "$sum": { 
        "$cond": [ { "$eq": [ "$status", "inactive" ] }, 1, 0 ] 
       } 
      }, 
      "removed_count": { 
       "$sum": { 
        "$cond": [ { "$eq": [ "$status", "removed" ] }, 1, 0 ] 
       } 
      }    
     } 
    }, 
    { 
     "$project": {    
      "status_counts": { 
       "active": "$active_count", 
       "inactive": "$inactive_count", 
       "removed": "$removed_count" 
      } 
     } 
    } 
]) 
+0

这是真棒!有一件事,如果它没有提供任何一天的记录,它不会返回任何内容。无论如何,包括没有任何数据的一天? – dzm

+0

谢谢,只是添加了一些示例数据和示例结果 – dzm