MongoDB聚合管道组

时间:2018-03-06 13:32:00

标签: mongodb mongodb-query aggregation-framework

我正在尝试构建一个管道,它将根据某些条件搜索文档,并将某些字段分组以提供所需的输出。 new Button(new ContextThemeWrapper(context, R.style.my_theme))的文档结构是

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

管道应搜索“状态”为“新”且“交易金额”超过2000的文档,并且应按“帐户名”分组。我用过的管道是这样的

{
   "_id":"A1",
   "name":"Sarah",
},
{
   "_id":"A2",
   "name":"Amber",
},

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

预期结果:

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&帐户名称,在“群组”阶段,以便在结果中显示,或者是否有其他方法可以执行此操作。任何帮助都非常感谢。

3 个答案:

答案 0 :(得分:1)

请使用此查询。

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' },
            .
            .
        }
    }

答案 1 :(得分:0)

首先,您的$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"
}

答案 2 :(得分:0)

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

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