skip to Main Content

I am trying to create a user document through this way:

// create the document ---------------
const id = mongoose.Types.ObjectId()
let userDoc = await Admin.create({ ...req.body, _id: id, by: id })

Schema:

adminSchema = new mongoose.Schema({
   // some other fields, firstName, lastName ... etc
   by: {
     type: mongoose.Schema.ObjectId,
     ref: 'Admin',
     required: [true, "the 'by' field is required"],
     immutable: true,
   }
}, { _id: false })

Model:

const Admin = mongoose.model('Admin', adminSchema, 'users')
  • My schema doesn’t have an _id property.

Now I want to have the _id field and the by field has the same value, which is a server-side generated id.

Mongoose is throwing this error:

Error: MongooseError: document must have an _id before saving at
…/node_modules/mongoose/lib/model.js:291:18

update:

I updated my question, I added the schema options, and now I know the reason why this error is happening. it’s because of the _id: false schema option that I have set. But I need this option because I don’t want to see _ids in the responses that I send to the clients. is there a workaround? because this option looks like its doing two unrelated things

2

Answers


  1. Chosen as BEST ANSWER

    Using Mongoose 6.4

    I solved this by removing the _id: false schema type option.

    and to remove the _id from the responses without having to pollute the routes with _.omit()s or deletes everywhere, I added the following schema type options to the schema:

    toObject: {
        virtuals: true,
        transform(doc, ret) { 
            delete ret._id
        },
    },
    

    Now the real question is, why does simply adding the option _id: false results in the Mongoose error when you're generating the id on the server-side without the help of Mongoose?

    Error: MongooseError: document must have an _id before saving at .../node_modules/mongoose/lib/model.js:291:18

    I partially answered my own question, but for this one... I really don't know.


  2. Based on your comment, if you want the response the user receives to not contain the _id you can:

    • Get the document
    • Remove the _id property and return this object without the _id (Or create a new object to avoid problems).

    A brief example could be:

    let responseDoc = await Admin.findOne({ _id: id });
    delete responseDoc["_id"]
    // responseDoc is now ready for use. Note that if I am not mistaken it is still a document.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search