MongoDB聚合管道组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB聚合管道组相关的知识,希望对你有一定的参考价值。

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

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

我想仅在结果中显示字段deal_amount,deal_type,deal_date和帐户名称。

预期结果:

{
    "_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"
},

我是否必须在“组”阶段中包含所有这些字段,deal_amount,deal_type,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}}
   }
}
另一答案

请使用此查询。

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参考:link

 { $group : {
            _id : "$author",
            data: { $push : "$$ROOT" }
        }}

2)通过分配单个参数

{
        $group: {
            _id: "$account_name",
            deal_amount: { $first: '$deal_amount' },
            deal_date: { $first: '$deal_date' },
            .
            .
        }
    }
另一答案

首先,你的$gte运算符不适用于字符串字段deal_amount,所以你可能想要将字段更改为整数或类似的东西:

// 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"
}

以上是关于MongoDB聚合管道组的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB聚合,如何在组管道中addToSet数组的每个元素

使用聚合管道聚合 MongoDB 中的时间戳集合

MongoDB——聚合操作

MongoDB——聚合操作

MongoDB - 聚合查询

mongodb Aggregation聚合操作之$facet