MongoDB聚合:按不同字段分组_id

5

我有收藏账户:

{
  "_id": ObjectId("571a0e145d29024733793cfe"),
  "name": "Cash",
  "user": ObjectId("571a0e145d29024733793cfc")
}

以及交易。交易可以有不同的字段:

{
  "_id": ObjectId("571a0e145d29024733793d06"),
  "amount": 100,
  "type": "earned",
  "account": ObjectId("571a0e145d29024733793cfe"),
  "user": ObjectId("571a0e145d29024733793cfc"),

},
{
  "_id": ObjectId("571a0e145d29024733793d04"),
  "amount": 300,
  "type": "spent",
  "account": ObjectId("571a0e145d29024733793cfe"),
  "user": ObjectId("571a0e145d29024733793cfc")
},
{
  "_id": ObjectId("571a0e145d29024733793d07"),
  "amount": 100,
  "type": "transfer",
  "sourceAccount": ObjectId("571a0e145d29024733793cfd"),
  "destinationAccount": ObjectId("571a0e145d29024733793cfe"),
  "user": ObjectId("571a0e145d29024733793cfc"),
}

我希望按每个账户创建一个统计组。 我向数据库编写了一个聚合框架查询:

db.transactions.aggregate([

  { $match: { user: user._id } },

  {
    $group: {
      _id: '$account',

      earned: {
        $sum: {
          $cond: [{ $eq: ['$type', 'earned'] }, '$amount', 0]
        }
      },

      spent: {
        $sum: {
          $cond: [{ $eq: ['$type', 'spent'] }, '$amount', 0]
        }
      },

      deposits: {
        $sum: {
          $cond: [{ $eq: ['$type', 'transfer'] }, '$amount', 0]
        }
      },

      withdrawal: {
        $sum: {
          $cond: [{ $eq: ['$type', 'transfer'] }, '$amount', 0]
        }
      },

      maxEarned: {
        $max: {
          $cond: [{ $eq: ['$type', 'earned'] }, '$amount', 0]
        }
      },

      maxSpent: {
        $max: {
          $cond: [{ $eq: ['$type', 'spent'] }, '$amount', 0]
        }
      },

      count: { $sum: 1 }

    }
  }
]);

但它不能正常工作。它只适用于带有账户字段的交易。我想按账户、源账户或目标账户分组。
我还尝试在"_id"字段中编写:
_id: { account: '$account', sourceAccount: '$sourceAccount', destinationAccount: '$destinationAccount' }

或者

_id: {$or: ['$account', '$sourceAccount', '$destinationAccount']}

或者

_id: {$in: ['$account', '$sourceAccount', '$destinationAccount']}

但它可能会分错组或无法正常工作。

我如何从不同的字段进行分组?

1个回答

2
使用$cond运算符作为_id表达式,根据您指定的条件评估分组键。 $cond运算符使用比较运算符$gt来评估布尔表达式,该表达式确定字段是否存在并使用此比较顺序。因此,您可以按照以下示例重新构建您的管道:
db.transactions.aggregate([
    {
        "$group": {
            "_id": { 
                "$cond": [
                    { "$gt": [ "$account", null ] }, 
                    "$account", 
                    { 
                        "$cond": [
                            { "$gt": [ "$sourceAccount", null ] }, 
                            "$sourceAccount", 
                            "$destinationAccount" 
                        ] 
                    } 
                ] 
            },
            "count": { "$sum": 1 }
        }
    }
])

样例输出
{ "_id" : ObjectId("571a0e145d29024733793cfd"), "count" : 1 }
{ "_id" : ObjectId("571a0e145d29024733793cfe"), "count" : 2 }

1
谢谢!它运行得很好!我想做类似的事情,但我无法想象如何实现。 - iehaeRoos4ie
@dimonnwc3 你为什么取消了这个答案?有什么特别的原因吗? - chridam
是的,那不是正确的决定。它在“转账”交易的统计数据中只计算源账户或目标账户一次。但是我需要它既作为转账,又从一个账户减去并加到另一个账户上。我已经重写了正确的决定,并稍后发布它。 - iehaeRoos4ie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接