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"
        }
      ]
    }
  ]
}
3
  • 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? Commented Nov 5, 2020 at 9: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. Commented Nov 5, 2020 at 10:01
  • @J.F. Edited the question. I meant to remove a value given value and name Commented Nov 5, 2020 at 10:03

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.