How to 'pull' update in aggregation pipeline - remove a sub-document from an embedded array?

{
  id,
  name,
  subjects:
  [ 
    { name : 'Maths', marks : '100'},
    { name : 'Science', marks : '90'}
  ]
}

I want to delete entry corresponding to Math in embedded array using aggregation pipeline, How can I do so?

Hi
It worked for me

db.collection.aggregate([
  {
    "$addFields": {
      subjects: {
        "$filter": {
          "input": "$subjects",
          "as": "subject",
          "cond": {
            $ne: [
              "$$subject.name",
              "Maths"
            ]
          }
        }
      }
    }
  }
])

Thanks for replying Imad. I was hoping to get rid of only single occurrence, can this be tweaked to accomplish that?

@Pavel_Duchovny Hey Pavel, need your 2 cents here if possible please. Is it possible to locate an embedded document and delete it using aggregation pipeline? Apologies for the random tag.

It would be best to publish a couple sample documents from the input set and the exact result set that you wish.

1 Like

Correct me if I’m wrong. you want to remove one matching document in each subjects array. if it’s so, try:

db.collection.aggregate([
  {
    "$addFields": {
      subjects: {
        "$let": {
          "vars": {
            "firstMatchedIndex": {
              "$arrayElemAt": [
                {
                  "$arrayElemAt": [
                    {
                      "$filter": {
                        "input": {
                          "$zip": {
                            "inputs": [
                              "$subjects",
                              {
                                "$range": [
                                  0,
                                  {
                                    "$size": "$subjects"
                                  }
                                ]
                              }
                            ]
                          }
                        },
                        "cond": {
                          "$eq": [
                            {
                              "$arrayElemAt": [
                                "$$this.name",
                                0
                              ]
                            },
                            "Maths"
                          ]
                        }
                      }
                    },
                    0
                  ]
                },
                1
              ]
            }
          },
          in: {
            "$ifNull": [
              {
                "$concatArrays": [
                  {
                    "$slice": [
                      "$subjects",
                      "$$firstMatchedIndex"
                    ]
                  },
                  {
                    "$slice": [
                      "$subjects",
                      {
                        "$subtract": [
                          {
                            "$add": [
                              "$$firstMatchedIndex",
                              1
                            ]
                          },
                          {
                            "$size": "$subjects"
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              "$subjects"
            ]
          }
        }
      }
    }
  }
])

Hello @Abhishek_Kumar_Singh,

The following aggregation will work with MongoDB v4.4 or higher.

db.collection.aggregate([
  { 
    $addFields: {
        subjects: {
            $function: {
                body: 
                    function(subjects) {
                        let flag = false;
                        let fn = function(acc, curr) {
                            if (curr.name === "maths" && flag === false) {
                                flag = true;
                                return acc.concat([ ])
                            }
                            return acc.concat([curr])
                        }
                        return subjects.reduce(fn, [ ])
                    },
                  args: [ "$subjects"],
                  lang: "js"
            }
        }
    }
  }
])
1 Like