skip to Main Content

I want to pull the whole nested array object if the object contains a specified string for a specific key. I’m using mongoose with nodejs:

DB before deletion:

{ _id : 1234
   fallBackData: {
      nestedKey: [ { arrayKey: "theValue" }, { arrayKey: "anotherValue" } ]
   }
 }

DB after deletion:

{ _id : 1234
   fallBackData: {
      nestedKey: [ { arrayKey: "anotherValue" } ]
   }
 }

I took a look at How can I pull nested object value in mongodb and $pullAll Mongo DB docs ,tried the following, but none worked:

 const ad = await Ad.updateOne(
     { _id: 1234 },
     {
         $pullAll: {
             fallbackData: { nestedKey: [{ arrayKey: "theValue"}] },
         },
     }
 );

 const ad = await Ad.updateOne(
     { _id: 1234 },
     {
         $pullAll: {
             "fallbackData.$.nestedKey" : { arrayKey: "theValue" },
         },
     }
  );

  const ad = await Ad.updateOne(
      { _id: 1234 },
      {
          $pullAll: {
              "fallbackData.$.nestedKey" : [{ arrayKey: "theValue"}],
          },
      }
  );

The query return value is the following, but the object in the array is not deleted:

 {
   acknowledged: true,
   modifiedCount: 1,
   upsertedId: null,
   upsertedCount: 0,
   matchedCount: 1
 }

3

Answers


  1. You can achieve this by changing a little

    playground

    db.collection.update({
      _id: 1234,
      "fallBackData.nestedKey": {
        $elemMatch: {
          "arrayKey": "theValue"
        }
      }
    },
    {
      "$unset": {
        "fallBackData": "nestedKey"
      }
    })
    

    You cannot add matching conditions with $pullAll related to Array

    $pullAll expects an array of matching values to be removed

    You can do $pull instead of $unset but $pull results empty array

    Login or Signup to reply.
  2. The answer from @Gibbs removes the array completely, while you asked only to pull the specific object from it.

    Here is the simple solution with $pull command:

    db.collection.update({
      _id: 1234,
      "fallBackData.nestedKey": {
        $elemMatch: {
          "arrayKey": "theValue"
        }
      }
    },
    {
      $pull: {
        "fallBackData.nestedKey": {
          arrayKey: "theValue"
        }
      }
    })
    

    Mongo Playground link

    Login or Signup to reply.
  3. pullAll matches the entire object (or objects) to be pulled. In other words, if the input was:

    [
      {
        _id: 1234,
        fallBackData: {
          nestedKey: [
            {
              arrayKey: "theValue",
              foo: "bar"
            },
            {
              arrayKey: "anotherValue",
              foo: "baz"
            }
          ]
        }
      }
    ]
    

    Then you need to do:

    db.collection.update({
      _id: 1234
    },
    {
      $pullAll: {
        "fallBackData.nestedKey": [
          {
            arrayKey: "theValue",
            foo: "bar"
          }
        ]
      }
    })
    

    See https://mongoplayground.net/p/iJkfqIWK0JO.

    On the other hand, $pull can match objects based on a condition, so you can pull from the array based on the specific key you want to match. So, given the same input as above, you would simply do:

    db.collection.update({
      _id: 1234
    },
    {
      $pull: {
        "fallBackData.nestedKey": {
          arrayKey: "theValue"
        }
      }
    })
    

    See https://mongoplayground.net/p/MOuSmh7Ir7b.

    The conditions can be more complex than a simple field value match. For example to match and pull multiple keys:

    db.collection.update({
      _id: 1234
    },
    {
      $pull: {
        "fallBackData.nestedKey": {
          "arrayKey": {
            $in: [
              "theValue",
              "anotherValue"
            ]
          }
        }
      }
    })
    

    See https://mongoplayground.net/p/iSMVxp7a9TX.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search