Home > Back-end >  Remove Embedded Documents in an Array in MongoDB with mongoose (updateOne - $pull) not work
Remove Embedded Documents in an Array in MongoDB with mongoose (updateOne - $pull) not work

Time:11-03

I have an app with MongoDB (Mongoose) in NodeJs.

In a collection I have this type of documents, defined by weeks:

{
"_id":
{"$oid":"617f3f51f883fab2de3e7260"},
"endDate":{"$date":"2021-11-07T23:59:59.000Z"},
"startDate":{"$date":"2021-11-01T00:00:00.000Z"},
"wastes":[
{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":780},
{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":1140},
{"timestamp":{"$date":"2021-11-01T03:00:58.000Z"},"duration":540},
{"timestamp":{"$date":"2021-11-01T07:00:58.000Z"},"duration":540},
{"timestamp":{"$date":"2021-11-01T09:00:58.000Z"},"duration":960},
{"timestamp":{"$date":"2021-11-01T09:00:58.000Z"},"duration":1140},
{"timestamp":{"$date":"2021-11-01T15:00:58.000Z"},"duration":180},
{"timestamp":{"$date":"2021-11-01T15:00:58.000Z"},"duration":540}
...
]}

I have a function that finds wastes with the same timestamp, for example "2021-11-01T01:00:58.000Z", gives the longest duration for this timestamp.

I want to delete all entries with that timestamp:

{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":780},
{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":1140}

And insert only the one with the highest duration:

{"timestamp":{"$date":"2021-11-01T01:00:58.000Z"},"duration":1140}

I'm using updateOne with $pull and $push, but it doesn't work.

let query = {
        startDate: new Date(startDayWeek),
      };

let deleteProjection = {
        $pull: {
          wastes: { timestamp: new Date(timestampDeleteInsertion) },
        },
      };

let insertProjection = {
        $push: { wastes: insertRegisterForTimestamp },
      };

//Delete
await coleccion.updateOne(query, deleteProjection);

//Insertion
await coleccion.updateOne(query, insertProjection);

I have also tried with {upsert: false}, {multi: true}.

If I use the same commands in the MongoDB Compass shell, it works without problems:

//Delete
db.coleccion.updateOne({startDate: ISODate('2021-11-01T00:00:00')}, {$pull: {'wastes': {timestamp: ISODate('2021-11-01T01:00:58.000Z')}}})

//Insertion
db.coleccion.updateOne({startDate: ISODate('2021-11-01T00:00:00')}, {$push: {'wastes': {'timestamp':ISODate('2021-11-01T01:00:58.000Z'), 'duration': 1140}}})

CodePudding user response:

You can achieve expected behaviour with Updates with Aggregation Pipeline

The aggregation will consists of 3 steps:

  1. find out the max duration using $reduce; stored the result into a field
  2. $filter the wastes array by keeping only elements not equal to the selected timestamp or the duration is not the max duration
  3. $unset the helper field created in step 1
db.collection.update({},
[
  {
    $addFields: {
      maxDuration: {
        "$reduce": {
          "input": "$wastes",
          "initialValue": null,
          "in": {
            "$cond": {
              "if": {
                $and: [
                  {
                    $eq: [
                      "$$this.timestamp",
                      {
                        "$date": "2021-11-01T01:00:58.000Z"
                      }
                    ]
                  },
                  {
                    $gt: [
                      "$$this.duration",
                      "$$value"
                    ]
                  }
                ]
              },
              "then": "$$this.duration",
              "else": "$$value"
            }
          }
        }
      }
    }
  },
  {
    $set: {
      wastes: {
        $filter: {
          input: "$wastes",
          as: "w",
          cond: {
            $or: [
              {
                $ne: [
                  "$$w.timestamp",
                  {
                    "$date": "2021-11-01T01:00:58.000Z"
                  }
                ]
              },
              {
                $eq: [
                  "$$w.duration",
                  "$maxDuration"
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    "$unset": "maxDuration"
  }
])

Here is the Mongo playground for your reference.

  • Related