如何在使用聚合和组

时间:2016-07-26 05:49:40

标签: mongodb aggregation-framework

我有一个交易模型,其中我有交易的描述和状态字段。如下所示

[
  {
    "_id": "5795e3f4f4a0fb8c1dff20ad",
    "description": "This is a transcation",
    "invoice_id": "5795db00bfa9d366194a454d",
    "amount": 50
  },
  {
    "_id": "5795e3faf4a0fb8c1dff20ae",
    "description": "This is a transcation",
    "invoice_id": "5795db00bfa9d366194a454d",
    "amount": 100
  }
]

我正在使用聚合和分组这些记录来查找匹配对象的totalAmount。所以为此我正在使用这个查询:

Transaction.aggregate([{
        $match: {
            invoice: ObjectId("5795db00bfa9d366194a454d")
        }
    }, {
        $group: {
            _id: {
                _id: "$_id"
            },
            count: {
                $sum: 1
            },
            totalAmount: {
                $sum: "$amount"
            },
        }
    }
])

当我运行时,我得到以下结果

/* 1 */
{
    "_id": {
        "_id": ObjectId("5796031e07bad1d21f3af823")
    },
    "count": 1.0,
    "totalAmount": 100
}

/* 2 */
{
    "_id": {
        "_id": ObjectId("5795e3f4f4a0fb8c1dff20ad")
    },
    "count": 1.0,
    "totalAmount": 50
}

但我希望获得具有特定invoice_idtotalAMount以及description等其他字段的所有匹配对象。应该是这样的事情

[{
    "_id": {
        "_id": ObjectId("5795e3f4f4a0fb8c1dff20ad")
    },
    "description": "description of first object",
    "count": 5.0,
    "totalAmount": 350
}, {
    "_id": {
        "_id": ObjectId("5795e3f4f4a0fb8c1dff20ad")
    },
    "description": "description of second object",
    "count": 5.0,
    "totalAmount": 350
}]

如何实现此解决方案?

2 个答案:

答案 0 :(得分:4)

经过几次澄清(如果你真的感兴趣,请检查this code)我写了下一个查询。

db.invoices.aggregate([{
    $match: {
        "invoice_id": ObjectId("5795db00bfa9d366194a454d")
    }
}, {

    $group: {
        _id: {
            _id: "$invoice_id"
        },
        count: {
            $sum: 1
        },
        info: {
            $push: {
                id: "$_id",
                amount: "$amount",
                description: "$description"

            }
        },
        totalAmount: {
            $sum: "$amount"
        }
    }
}, {
    $unwind: "$info"
}, {
    $project: {
        _id: "$info.id",
        count: "$count",
        invoice_id: "$_id",
        totalAmount: "$totalAmount",
        amount: "$info.amount",
        description: "$info.description"
    }
}])

这里发生了什么?

  1. 我们收到所有具有所选ID的发票。
  2. 我们按此ID对其进行分组以计算totalAmount,但同时将所有其他信息推送到info字段。之后我们有单个文档,如下所示:

    {
        "_id" : {
            "_id" : "5795db00bfa9d366194a454d"
        },
        "count" : 2,
        "info" : [ 
            {
                "id" : ObjectId("5795e3f4f4a0fb8c1dff20ad"),
                "amount" : 50,
                "description" : "This is a transcation"
            }, 
            {
                "id" : ObjectId("5796031e07bad1d21f3af823"),
                "amount" : 100,
                "description" : "FSC evening class"
            }
        ],
        "totalAmount" : 150
    }
    
  3. 我们在此文档上执行$unwind,创建了两个具有下一个结构的文档

    {
        "_id" : {
            "_id" : "5795db00bfa9d366194a454d"
        },
        "count" : 2,
        "info" :  {
            "id" : ObjectId("5795e3f4f4a0fb8c1dff20ad"),
            "amount" : 50,
            "description" : "This is a transcation"
        },
        "totalAmount" : 150
    }
    
  4. 最后一部分是将我们的结构投射到所需的结构。这很简单,无需另外解释。

  5. 现在您将能够以这种形式获得结果:

        /* 1 */
        {
            "_id" : ObjectId("5795e3f4f4a0fb8c1dff20ad"),
            "count" : 2.0,
            "totalAmount" : 150,
            "invoice_id" : {
                "_id" : ObjectId("5795db00bfa9d366194a454d")
            },
            "amount" : 50,
            "description" : "This is a transcation"
        }
    
        /* 2 */
        {
            "_id" : ObjectId("5796031e07bad1d21f3af823"),
            "count" : 2.0,
            "totalAmount" : 150,
            "invoice_id" : {
                "_id" : ObjectId("5795db00bfa9d366194a454d")
            },
            "amount" : 100,
            "description" : "FSC evening class"
        }
    

答案 1 :(得分:0)

在代码中更改group by的顺序: -

   db.invoices.aggregate([{


     $match: {
        "invoice_id": `ObjectId("5795db00bfa9d366194a454d")`
        }
       }, {
        $group: {
            _id: {
                _id: "$invoice_id"
            },
             description: {
                $first: "$description"
            }
            count: {
                $sum: 1
            },
            totalAmount: {
                $sum: "$amount"
            }       
        }
    }])