MongoDB聚合包括伪数据

时间:2015-10-27 15:12:34

标签: 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 个答案:

答案 0 :(得分:1)

使用以下管道,其中 $project 阶段的管道使用 {{创建具有仅由月 - 日 - 年组成的新属性的文档3}} date aggregation operators string operators $concat 运营商字符串操作。然后,您可以使用前面 $subtr 管道步骤中的新属性作为组密钥,并使用 $group 运算符获取相应的状态计数评估状态类型并将值分配给 $cond 。结束 $sum 管道阶段然后重新整形最终文档,以在子文档中提供所需的字段:

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"
            }
        }
    }
])