Search code examples
mongodbmongoose

Object disappearing from mongoose data


programmers. I am currently attempting to delete an Object from inside an Object in my data. My schema is as follows:

const Schema = new mongoose.Schema({
    userId: { type: String, required: true, unique: true },
    currentEmployment: { type: Object },
    employmentHistory: [
        {
            department: { type: String },
            lastPosition: { type: String },
            joinDate: { type: Number },
            leaveDate: { type: Number },
            punishmentHistory: [
                {
                    type: { type: String },
                    reason: { type: String },
                    date: { type: Number }
                }
            ]
        }
    ],
});

Now, I am currently trying to delete the 'Police' Object from inside the "currentEmployment" object. My current data is the following:

{
  _id: new ObjectId('65e1be295d4d201b8aa902d4'),
  userId: '1',
  employmentHistory: [],
  currentEmployment: {
    'Police': {
      position: 'Captain',
      joinDate: 1709306734,
      punishmentHistory: []
    }
  }
  __v: 0
}

I attempted to use the following code to accomplish this:

data.currentEmployment['Police'] = undefined;
console.log(data);
await data.save();

The console.log(data); statement printed this:

{
  _id: new ObjectId('65e1f36e4317612bf1266787'),
  userId: '1',
  employmentHistory: [],
  __v: 0
}

Why is the entire "currentEmployment" object getting deleted from my data?


Solution

  • Couple of things to note here. Firstly, it is better to handle this in one query using $unset like so:

    const data = await Employee.findOneAndUpdate({
        userId: '1',
    },{
        $unset: {
            "currentEmployment.Police": ""
        }
    },{new: true});
    

    This will set currentEmployment to an empty object.

    Secondly however, you will notice that currentEmployment does not show up as an empty object when you query that document. You would need to use mongosh or Compass and query the collection, then you will see it.

    With mongoose an empty object is not normally saved to a document due to the minimize: true default settings so when you return the document from a query currentEmployment won't show.

    To work around that you need to add the toJSON: { minimize: false } option to your schema which tells mongoose not to minimize those empty objects when you convert to JSON. You would add this option like so:

    const Schema = new mongoose.Schema({
        userId: { type: String, required: true, unique: true },
        //...
        //...
    }, { 
        toJSON: { minimize: false } 
    });