如果为空,如何使用 $subtract 和条件来使用数组中的默认值?

How to use $subtract along with conditions to use a default value from an array, if null?

我正在尝试从聚合管道中的 final 数组和 start 数组中减去值。但也有一些特殊情况需要在减法之前添加一些额外的逻辑。

预期输出:

  1. I need to subtract nth value of startarray from nth value of final array
  2. And then, get the total sum of subtracted values

特殊情况:

  1. If nth value of start array is NULL, use a start_default value(from the query)
  2. If nth value of final array is NULL, use value from the final_default array

经过一些聚合阶段后,我的 MongoDB 文档具有以下格式:

Assuming that start_default value = 1

I have commented the way I expect to perform subtractions in each of the group

{
  "data": [
    {
      "key": "TP-1",
      "status_map": [
        {
          "status": "Closed",
          "final": [
            6,
            3
          ],                               // Expected Output
          "start": [                       // sum:6 [(6-2)+(3-1(start_default))=4+2]
            2
          ],
          "final_default": [
            4
          ]
        },
        {
          "status": "Done",
          "final": [
            4
          ],                              // Expected Output
          "start": [                     // sum:2 [(4-3)+(2(final_default)-1)=1+1]
            3,
            1                            
          ],
          "final_default": [
            2
          ]
        }
      ]
    },
    {
      "key": "TP-2",
      "status_map": [
        {
          "status": "Closed",
          "final": [
            1,
            5
          ],                             // Expected Output
          "start": [],                   //sum:4 [(1-1(start_default))+(5-1(start_default))=0+4]
          "final_default": [
            3
          ]
        },
        {
          "status": "Done",
          "final": [],                    // Expected Output
          "start": [                     //sum:3 [(5(final_default)-3)+(5(final_default)-4)=2+1]
            3,
            4
          ],
          "final_default": [
            5
          ]
        }
      ]
    }
  ]
}

假设 start_default 值 = 1

,这是我的预期输出
{
  "data": [
    {
      "key": "TP-1",
      "status_map": [
        {
          "status": "Closed",
          "sum": 6  //[(6-2)+(3-1(start_default))=4+2]
        {
          "status": "Done",
          "sum": 2 //[(4-3)+(2(final_default)-1)=1+1]
        }
      ]
    },
    {
      "key": "TP-2",
      "status_map": [
        {
          "status": "Closed",
          "sum": 4  //[(1-1(start_default))+(5-1(start_default))=0+4]
        },
        {
          "status": "Done",
          "sum": 3 //[(5(final_default)-3)+(5(final_default)-4)=2+1]
        }
      ]
    }
  ]
}

如何实现这个用例?

您可以从双 $map to rewrite your nested array. You'll also need $reduce since you'll be converting an array into scalar value. Since you need to "pair" two arrays, there's a perfect operator called $zip 开始,即使数组长度不同也可以使用。为第一个子文档配对 finalstart 将 return:

[ [ 6,2 ], [ 3, null ] ]

这很棒,因为您可以使用 $ifNull 提供默认值。

您的汇总如下所示:

db.collection.aggregate([
    {
        $project: {
            data: {
                $map: {
                    input: "$data",
                    as: "d",
                    in: {
                        key: "$$d.key",
                        status_map: {
                            $map: {
                                input: "$$d.status_map",
                                as: "sm",
                                in: {
                                    status: "$$sm.status",
                                    sum: {
                                        $reduce: {
                                            input: {
                                                $zip: {
                                                    inputs: [ "$$sm.final", "$$sm.start" ],
                                                    useLongestLength: true
                                                }
                                            },
                                            initialValue: 0,
                                            in: {
                                                $add: [
                                                    "$$value",
                                                    {
                                                        $subtract: [
                                                            { $ifNull: [ { $arrayElemAt: [ "$$this", 0 ] }, { $arrayElemAt: [ "$$sm.final_default" , 0] } ] },
                                                            { $ifNull: [ { $arrayElemAt: [ "$$this", 1 ] }, 1 ] }
                                                        ]
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
])

Mongo Playground