Home > database >  How to $pull in mongodb if you have a weird data inside an array?
How to $pull in mongodb if you have a weird data inside an array?

Time:10-20

So basically I have this data

{
  company: {
    subscriptions: [
      {
        "name": "test1",
        "updatedAt": ISODate("2021-10-19T06:40:33.583Z")
      },
      {
        "name": "test2",
        "updatedAt": ISODate("2021-10-19T06:40:33.583Z")
      },
      {
        "services": {
          "1": {
            "createdAt": ISODate("2021-10-19T06:40:33.583Z"),
            "updatedAt": ISODate("2021-10-19T06:40:33.583Z")
          }
        },
        "updatedAt": ISODate("2021-10-19T06:40:33.583Z")
      }
    ]
  }
}

Currently I don't know how this data is inserted on the collection.

The weird data is this one.

{
        "services": {
          "1": {
            "createdAt": ISODate("2021-10-19T06:40:33.583Z"),
            "updatedAt": ISODate("2021-10-19T06:40:33.583Z")
          }
        },
        "updatedAt": ISODate("2021-10-19T06:40:33.583Z")
      }

How can I use mongodb $pull to remove this inside subscriptions array?

CodePudding user response:

Base on @Takis_ answer I found a solution. Here is what I did

const cursor = await Company.find({
    $and: [
      {
        "subscriptions": { $exists: true, $ne: [] }
      }
    ]
  }).cursor();


  await cursor.eachAsync(async company => {
    let isUpdate = false;

    const found = find(company.subscriptions, subscription => subscription.name === undefined);

    if (!found) return

    try {
      const res = await Company.updateOne(
        {
          "_id": mongoose.Types.ObjectId(company._id),
        },
        {
          $pull: { subscriptions: { name: { $exists: false } } }
        }
      );
    } catch(err) {
      log(`ERROR removing subscription entry for company ${company.name} - ${company._id}`);
    }
  })

CodePudding user response:

Query1

  • $pull, if member doesnt have a field called name, it gets removed

Test code here

db.collection.updateMany({},
{
  $pull: {
    "company.subscriptions": {
      name: {
        "$exists": false
      }
    }
  }
})

Query2

  • alternative way with pipeline
  • this removes a member of the array, if doesnt have a field name (or name is false/null)
  • services that you dont want to remove doesnt have a name so it will be filtered out

pipeline update requires MongoDB >= 4.2

Test code here

db.collection.updateMany({},
[
  {
    "$set": {
      "company.subscriptions": {
        "$filter": {
          "input": "$company.subscriptions",
          "cond": "$$this.name"
        }
      }
    }
  }
])

If your updateMany method doesnt accept pipeline you can run it like as command

db.runCommand(
   {
      update: "yourCollection",
      updates: [
         {
           q: { },
           u: [
               {
                 "$set": {
                  "company.subscriptions": {
                    "$filter": {
                      "input": "$company.subscriptions",
                       "cond": "$$this.name"
                   }
              }}}
           ],
           multi: true
         }
      ],
      ordered: false
   }
)
  • Related