Как использовать $ subtract вместе с условиями для использования значения по умолчанию из массива, если null? - PullRequest
2 голосов
/ 09 июля 2020

Я пытаюсь вычесть значения из массива final и массива start в моем конвейере агрегации. Но в некоторых исключительных случаях перед вычитанием требуется дополнительное c logi.

Ожидаемый результат:

  1. Мне нужно вычесть n-е значение массива start из n-е значение final array
  2. И затем получить общую сумму вычтенных значений

Исключительные случаи:

  1. Если n-е значение массива start равно NULL, используйте значение start_default (из запроса)
  2. Если n-е значение массива final равно NULL, используйте значение из final_default array

После некоторых этапов агрегации мой документ MongoDB имеет следующий формат:

Предполагая, что значение start_default = 1

У меня есть прокомментировал способ, которым я ожидаю выполнять вычитания в каждой группе

{
  "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 value = 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]
        }
      ]
    }
  ]
}

Как достичь этот вариант использования?

1 Ответ

1 голос
/ 09 июля 2020

Вы можете начать с двойной $ map , чтобы переписать ваш вложенный массив. Вам также понадобится $ reduce , поскольку вы будете преобразовывать массив в скалярное значение. Поскольку вам нужно «соединить» два массива, существует идеальный оператор $ zip , который можно использовать, даже если массивы имеют разную длину. Сопряжение final и start для первого поддокумента вернет:

[ [ 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 ] }
                                                        ]
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
])

Пн go Детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...