Profer
Profer

Reputation: 643

Compare and add two array inside nested arrays

I have below array of array inside my document

  {
    items: [
      ["Tax", 10, 20, 30],
      ["FX Adjustments", 10, 20, 30],
      ["Tax", 10, 20, 30],
      ["FX Adjustments", 10, 20, 30]
    ]
  }

I need to combine Tax with Tax and FX Adjustments with FX Adjustments.

Output I need

  {
    items: [
      ["Tax", 20, 40, 60],
      ["FX Adjustments", 20, 40, 60]
    ]
  }

I tried but with no luck

db.collection.aggregate([
  {
    $project: {
      items: {
        $reduce: {
          input: "$items",
          initialValue: [],
          in: {
            $cond: [
            ]
          }
        }
      }
    }
  }
])

Kindly help with this

Thank you!!!

Upvotes: 1

Views: 113

Answers (2)

mickl
mickl

Reputation: 49985

You need to start with $unwind and then $group by first array element ($arrayElemAt). Then you can run $reduce like you tried but since your array is multidimensional, you need to wrap it with $map to represent the index. To get back the original data format you can group by null and use $concatArrays to put grouping _id as first array element:

db.collection.aggregate([
    {
        $unwind: "$items"
    },
    {
        $group: {
            _id: { $arrayElemAt: [ "$items", 0 ] },
            values: { $push: { $slice: [ "$items", 1, { $size: "$items" } ] } }
        }
    },
    {
        $project: {
            _id: 1,
            values: {
                $map: {
                    input: { $range: [ 0, { $size: { $arrayElemAt: [ "$values", 0 ] } } ] },
                    as: "index",
                    in: {
                        $reduce: {
                            input: "$values",
                            initialValue: 0,
                            in: { $add: [ "$$value", { $arrayElemAt: [ "$$this", "$$index" ] } ] }
                        }
                    }
                }
            }
        }
    },
    {
        $group: {
            _id: null,
            items: { $push: { $concatArrays: [ [ "$_id" ], "$values" ] } }
        }
    }
])

Mongo Playground

Upvotes: 1

sushant mehta
sushant mehta

Reputation: 1274

Try below aggregate pipeline

collectionName.aggregate([
  {
    $unwind: "$items"
  },
  {
    $group: {
      _id: {
        $arrayElemAt: [
          "$items",
          0
        ]
      },
      sum1: {
        $sum: {
          $arrayElemAt: [
            "$items",
            1
          ]
        }
      },
      sum2: {
        $sum: {
          $arrayElemAt: [
            "$items",
            2
          ]
        }
      },
      sum3: {
        $sum: {
          $arrayElemAt: [
            "$items",
            3
          ]
        }
      }
    }
  },
  {
    $project: {
      _id: null,
      items: {
        $map: {
          input: {
            $objectToArray: "$$ROOT"
          },
          as: "item",
          in: "$$item.v"
        }
      }
    }
  },
  {
    $group: {
      _id: null,
      items: {
        $push: "$items"
      }
    }
  }
])
  1. unwind the items array
  2. group according to Tax(first position element of item using $arrayElemAt)
  3. In project stage use map on objectToArray to get value of keys pushed into array
  4. push the array using $group giving desired output

Output:

[
  {
    "_id": null,
    "items": [
      [
        "Tax",
        20,
        40,
        60
      ],
      [
        "FX Adjustments",
        20,
        40,
        60
      ]
    ]
  }
]

Upvotes: 0

Related Questions