3

I have below data. I want to find value=v2 (remove others value which not equals to v2) in the inner array which belongs to name=name2. How to write aggregation for this? The hard part for me is filtering the nestedArray which only belongs to name=name2.

{
  "_id": 1,
  "array": [
    {
      "name": "name1",
      "nestedArray": [
        {
          "value": "v1"
        },
        {
          "value": "v2"
        }
      ]
    },
    {
      "name": "name2",
      "nestedArray": [
        {
          "value": "v1"
        },
        {
          "value": "v2"
        }
      ]
    }
  ]
}

And the desired output is below. Please note the value=v1 remains under name=name1 while value=v1 under name=name2 is removed.

{
  "_id": 1,
  "array": [
    {
      "name": "name1",
      "nestedArray": [
        {
          "value": "v1"
        },
        {
          "value": "v2"
        }
      ]
    },
    {
      "name": "name2",
      "nestedArray": [
        {
          "value": "v2"
        }
      ]
    }
  ]
}
turivishal
  • 34,368
  • 7
  • 36
  • 59
harryk
  • 123
  • 1
  • 10
  • 1
    It's not verty clear what's exactly do you want: Get documents with ```value=v1``` and ```name=name1``` or remove a value given ```value``` and ```name```? – J.F. Nov 05 '20 at 09:13
  • @chridam. Edited the question. For example, input is name="name2", value="v2". Meaning I want to look into the outer "array", and look for an entry which name="name2", then I want to look into the "nestedArray" of it and remove the entry which value !="v2". If there isn't a entry in the outer "array" which name="name2" then nothing will be removed. – harryk Nov 05 '20 at 10:01
  • @J.F. Edited the question. I meant to remove a value given value and name – harryk Nov 05 '20 at 10:03

2 Answers2

1

You can use the following aggregation query:

db.collection.aggregate([
  {
    $project: {
      "array": {
        "$concatArrays": [
          {
            "$filter": {
              "input": "$array",
              "as": "array",
              "cond": {
                "$ne": [
                  "$$array.name",
                  "name2"
                ]
              }
            }
          },
          {
            "$filter": {
              "input": {
                "$map": {
                  "input": "$array",
                  "as": "array",
                  "in": {
                    "name": "$$array.name",
                    "nestedArray": {
                      "$filter": {
                        "input": "$$array.nestedArray",
                        "as": "nestedArray",
                        "cond": {
                          "$eq": [
                            "$$nestedArray.value",
                            "v2"
                          ]
                        }
                      }
                    }
                  }
                }
              },
              "as": "array",
              "cond": {
                "$eq": [
                  "$$array.name",
                  "name2"
                ]
              }
            }
          }
        ]
      }
    }
  }
])

MongoDB Playground

Tiya Jose
  • 1,359
  • 14
  • 24
1

You can try,

  • $set to update array field, $map to iterate loop of array field, check condition if name is name2 then $filter to get matching value v2 documents from nestedArray field and $mergeObject merge objects with available objects
let name = "name2", value = "v2";
db.collection.aggregate([
  {
    $set: {
      array: {
        $map: {
          input: "$array",
          in: {
            $mergeObjects: [
              "$$this",
              {
                $cond: [
                  { $eq: ["$$this.name", name] }, //name add here
                  {
                    nestedArray: {
                      $filter: {
                        input: "$$this.nestedArray",
                        cond: { $eq: ["$$this.value", value] } //value add here
                      }
                    }
                  },
                  {}
                ]
              }
            ]
          }
        }
      }
    }
  }
])

Playground

turivishal
  • 34,368
  • 7
  • 36
  • 59