Node.js 如何使用mongoDB/mongoose聚合管道使聚合值基于自定义字段?

Node.js 如何使用mongoDB/mongoose聚合管道使聚合值基于自定义字段?,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我正在开发一个购物车,我目前的要求是向店主显示一个仪表板。由于产品名称中可能存在重复,我已根据产品ID对订购的产品进行分组,并执行求和以获得订单总数。现在我还需要可读的名称,但这样做会导致错误 询问 ShoppingCart .aggregate({ $match: { "orderedProducts.registrationDetails.createdByID": LOGGED_IN_ADMIS_ID } }) .project("orderedProducts.produ

我正在开发一个购物车,我目前的要求是向店主显示一个仪表板。由于产品名称中可能存在重复,我已根据产品ID对订购的产品进行分组,并执行求和以获得订单总数。现在我还需要可读的名称,但这样做会导致错误

询问

ShoppingCart
    .aggregate({ $match: { "orderedProducts.registrationDetails.createdByID": LOGGED_IN_ADMIS_ID } })
    .project("orderedProducts.productID orderedProducts.title  orderedProducts.qty -_id")
    .unwind("orderedProducts")
    .group({ _id: "$orderedProducts.productID", counts: { $sum: "$orderedProducts.qty" }, title: "$orderedProducts.title" })
    .exec((err, docs) => {
        if (err) {
            return res.status(503).send(err);
        }
        res.send(docs);
    });
错误消息:

{“name”:“MongoError”,“message”:“字段'title'必须是 累加器对象,“确定”:0,“errmsg:”字段“title”必须是 累加器对象,“代码”:40234,“代码名”:“位置40234”}


这是导致错误标题的部分:“$orderedProducts.title”

我相信问题可能出在您的
操作员身上。具体来说,您正在执行
标题:“$orderedProducts.title”
,这可能会导致分组出现问题。MongoDB可能不理解如何处理这种情况,因为无法确定使用哪个文档中哪个标题的优先级。这就是为什么需要某种形式的累加器,例如在
数量
字段上使用的
$sum

相反,请尝试省略分组的
标题
部分,而使用复合的
\u id

ShoppingCart
    .aggregate({ $match: { "orderedProducts.registrationDetails.createdByID": LOGGED_IN_ADMIS_ID } })
    .project("orderedProducts.productID orderedProducts.title  orderedProducts.qty -_id")
    .unwind("orderedProducts")
    .group({ _id: { productId: "$orderedProducts.productID", title: "$orderedProducts.title" }, counts: { $sum: "$orderedProducts.qty" } })
    .exec((err, docs) => {
        if (err) {
            return res.status(503).send(err);
        }
        res.send(docs);
    });
此解决方案需要注意的是,它假定每个
productID
只有一个标题。它将按
productID
title
进行分组,因此相同
productID
的任何不同标题都将导致此解决方案失败。如果这对您来说是一个问题,并且您希望获取给定
productID
的所有产品标题,您可以执行以下操作:

ShoppingCart
    .aggregate({ $match: { "orderedProducts.registrationDetails.createdByID": LOGGED_IN_ADMIS_ID } })
    .project("orderedProducts.productID orderedProducts.title  orderedProducts.qty -_id")
    .unwind("orderedProducts")
    .group({ _id: "$orderedProducts.productID", counts: { $sum: "$orderedProducts.qty" }, titles: { $addToSet: "$orderedProducts.title" } })
    .exec((err, docs) => {
        if (err) {
            return res.status(503).send(err);
        }
        res.send(docs);
    });

在组管道中使用$last或$first

.group({ 
     _id: "$orderedProducts.productID", 
     counts: { $sum: "$orderedProducts.qty" }, 
     title: { $first:"$orderedProducts.title"} 
})
或者


由于您正在对产品进行分组,因此标题应与类似的产品id保持一致。因此,您可以选择第一个或最后一个与最终分组对象一起附加的标题

亲爱的@imixtron谢谢您的建议。问题是,在我的例子中,产品的名称不是唯一的。用户可能会创建两个或多个名称完全相同的不同产品,这就是为什么我用产品ID而不是名称对产品进行分组。我的查询也会这样做,因为分组基于_ID。因此,所有分组的文档都将具有相同的名称。因此,您可以从起点或终点选择一个。
.group({ 
     _id: "$orderedProducts.productID", 
     counts: { $sum: "$orderedProducts.qty" }, 
     title: { $last:"$orderedProducts.title"} 
})