按多个字段对集合数据进行分组 mongodb

Abh*_*rma 0 database mongoose mongodb mongodb-query aggregation-framework

馆藏结构

Order = new Schema
    index:          { type: Number, unique: true }
    number:         Date
    status:         { type: String, enum: ['success', 'failure'] }
    created_at:     { type: Date, default: Date.now }
    updated_at:     { type: Date, default: Date.now }
Run Code Online (Sandbox Code Playgroud)

我需要有关查询的帮助,该查询返回一组对象,这些对象的数据为按日期分组的成功计数和失败计数。前任-

orders = {
              28-10-2016:{
               success_count: 10, 
               failure_count: 10
              },
              29-10-2016: {
               success_count: 10, 
               failure_count: 10
              }
          }
Run Code Online (Sandbox Code Playgroud)

chr*_*dam 6

使用聚合框架,结果将与您的“期望”输出略有不同,因为您将获得一个对象数组,其_id键的值代表您按字段分组。例如,代替

{
    "28-10-2016":{
        "success_count": 10, 
        "failure_count": 10
    },
    "29-10-2016": {
        "success_count": 10, 
        "failure_count": 10
    }
}
Run Code Online (Sandbox Code Playgroud)

你会有一个更好的结构,比如

[
    {
        "_id": "28-10-2016",
        "success_count": 10, 
        "failure_count": 10
    },
        "_id": "29-10-2016",
        "success_count": 10, 
        "failure_count": 10
    }
]
Run Code Online (Sandbox Code Playgroud)

实现上述结果需要$cond$sum累加器运算符中使用运算符。该$cond运营商将评估基于其第一个参数(如果)的逻辑条件,然后返回,其中评价是真实的(当时)的第二个参数或第三个参数,其中假(否则)。这将真/假逻辑转换为 1 和 0 数值,$sum分别输入:

"success_count": {
    "$sum": {
        "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
    }
}
Run Code Online (Sandbox Code Playgroud)

作为结果管道,需要运行聚合操作,该$dateToString操作在管道的_id键表达式中使用运算符$group

Orders.aggregate([
    {
        "$group": {
            "_id": {
                "$dateToString": { 
                    "format": "%Y-%m-%d", 
                    "date": "$created_at" 
                }
            },
            "success_count": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
                }
            },
            "failure_count": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$status", "failure" ] }, 1, 0 ]
                }
            }
        }
    }
], function (err, orders){
    if (err) throw err;
    console.log(orders);
})
Run Code Online (Sandbox Code Playgroud)

但是,有一种更灵活、性能更好的方法,它的执行速度比上述方法快得多,聚合结果的最有效数据结构遵循以下模式,例如:

orders = [
    {
        "_id": "28-10-2016",
        "counts": [
            { "status": "success", "count": 10 },
            { "status": "failure", "count": 10 }
        ]
    },
    {
        "_id": "29-10-2016",
        "counts": [
            { "status": "success", "count": 10 },
            { "status": "failure", "count": 10 }
        ]
    }
]
Run Code Online (Sandbox Code Playgroud)

然后考虑按如下方式运行替代管道

Orders.aggregate([
    { 
        "$group": {
            "_id": { 
                "date":  {
                    "$dateToString": { 
                        "format": "%Y-%m-%d", 
                        "date": "$created_at" 
                    }
                },
                "status": { "$toLower": "$status" }
            },
            "count": { "$sum": 1 }
        }
    },
    { 
        "$group": {
            "_id": "$_id.date",
            "counts": {
                "$push": {
                    "status": "$_id.status",
                    "count": "$count"
                }
            }
        }
    }
], function (err, orders){
    if (err) throw err;
    console.log(orders);
})
Run Code Online (Sandbox Code Playgroud)