MongoDB聚合管道组

MongoDB聚合管道组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我正在尝试构建一个管道,它将根据某些条件搜索文档,并将某些字段分组以提供所需的输出。交易的文档结构是 { "_id":"123", "status":"New", "deal_amount":"5200", "deal_date":"2018-03-05", "data_source":"API", "deal_type":"New Business", "account_id":"A1" }, { "_id":"456", "status"

我正在尝试构建一个管道,它将根据某些条件搜索文档,并将某些字段分组以提供所需的输出。
交易的文档结构是

{
   "_id":"123",
   "status":"New",
   "deal_amount":"5200",
   "deal_date":"2018-03-05",
   "data_source":"API",
   "deal_type":"New Business",
   "account_id":"A1"
},
{
   "_id":"456",
   "status":"New",
   "deal_amount":"770",
   "deal_date":"2018-02-11",
   "data_source":"API",
   "deal_type":"New Business",
   "account_id":"A2"
},
{
   "_id":"885",
   "status":"Old",
   "deal_amount":"4070",
   "deal_date":"2017-09-22",
   "data_source":"API",
   "deal_type":"New Business",
   "account_id":"A2"
},
“帐户名”字段被引用。帐户文档如下所示:

{
   "_id":"A1",
   "name":"Sarah",
},
{
   "_id":"A2",
   "name":"Amber",
},
管道应搜索“状态”为“新”且“交易金额”大于2000的文档,并应按“账户名称”分组。我用过的管道是这样的

db.deal.aggregate([{
        $match: {
            status: New,
            deal_amount: {
                $gte: 2000,
            }
        }
    }, {
        $group: {
            _id: "$account_name",
        }
    },{
        $lookup:{
            from:"accounts",
            localField:"account_id",
            foreignField:"_id",
            as:"acc",
        }
    }
])
我只想在结果中显示交易金额、交易类型、交易日期和账户名称字段

预期结果:

{
    "_id": "123",
    "deal_amount": "5200",
    "deal_date": "2018-03-05",
    "deal_type": "New Business",
    "account_name": "Sarah"
}, {
    "_id": "885",
    "deal_amount": "4070",
    "deal_date": "2017-09-22",
    "deal_type": "New Business",
    "account_name": "Amber"
},

我是否必须在“分组”阶段包含所有这些字段、交易金额、交易类型、交易日期和账户名称,以便在结果中显示,或者是否有其他方法来显示。非常感谢您的帮助。

首先,您的
$gte
运算符无法处理字符串字段
交易金额
,因此您可能需要将该字段更改为整数或类似的内容:

// Convert String to Integer
db.deals.find().forEach(function(data) {
    db.deals.update(
            {_id:data._id},
            {$set:{deal_amount:parseInt(data.deal_amount)}});
然后,要仅获取所需的字段,请使用
$project
重塑文档:

db.deals.aggregate([{
        $match: {
            "status": "New",
            "deal_amount" : {
                "$gte" : 2000 
            }
        }
    },     
     {
         $lookup:{
            from:"accounts",
            localField:"account_id",
            foreignField:"_id",
            as:"acc",
        }
    },
     {
        $project: {
            _id: 1, 
            deal_amount: 1, 
            deal_type: 1, 
            deal_date: 1, 
            "account_name": {"$let":{"vars":{"accl":{"$arrayElemAt":["$acc", 0]}}, in:"$$accl.name"}}
        }
    }    
]);
对我来说,这产生了:

{ 
    "_id" : "123", 
    "deal_amount" : 5200.0, 
    "deal_date" : "2018-03-05", 
    "deal_type" : "New Business", 
    "account_name" : "Sarah"
}
请使用此查询

aggregate([{
        $match: {
            status: "New",
            deal_amount: {
                $gte: 2000,
            }
        }
    },
    {
        $lookup:{
            from:"accounts",
            localField:"account_id",
            foreignField:"_id",
            as:"acc",
        }
    },
    {
        $unwind: {
          path: '$acc',
          preserveNullAndEmptyArrays: true,
        },
      },
      {
      $group: {
            _id: "$acc._id",
            deal_amount: { $first: '$deal_amount' },
            deal_date: { $first: '$deal_date' },
            deal_type: { $first: '$deal_type' },

        }
    }
])
您可以通过以下方式完成:

1) 使用$$ROOT 参考:

2) 通过指定单个参数

{
        $group: {
            _id: "$account_name",
            deal_amount: { $first: '$deal_amount' },
            deal_date: { $first: '$deal_date' },
            .
            .
        }
    }

不确定为什么需要
$group
阶段。您只需添加
$project
阶段即可从引用的集合中输出帐户名

{
  "$project": {
    "deal_amount": 1, 
    "deal_type": 1, 
    "deal_date": 1, 
    "account_name": {"$let":{"vars":{"accl":{"$arrayElemAt":["$acc", 0]}}, in:"$$accl.name}}
   }
}

您建议在管道中按顺序进行匹配、项目和查找阶段。谢谢Veeram,但选择order.Np的原因是什么。比赛总是第一位的。项目引用查找字段,以便在项目之前进行查找。假设在我的情况下,如果要进行分组,则顺序是$match、$group,然后是$lookup。这取决于组中使用的字段。如果不使用外部集合中的字段,则可以在查找之前进行,也可以在查找之后进行。
{
  "$project": {
    "deal_amount": 1, 
    "deal_type": 1, 
    "deal_date": 1, 
    "account_name": {"$let":{"vars":{"accl":{"$arrayElemAt":["$acc", 0]}}, in:"$$accl.name}}
   }
}