Matt Lee
Matt Lee

Reputation: 571

MongoDB - Error: document must have an _id before saving

I've been struggling so much with this project. I am following a tutorial that is out of date in some areas, for instance their version of Jquery used a totally different format for some functions and I had to do a lot of changing around. But I think I am down to one last major problem that I can't seem to find a fix for. In my Schema variable I've got the _id, username, and password types

var UserSchema = new mongoose.Schema({
    _id: mongoose.Schema.ObjectId,
    username: String,
    password: String
}); 

but when I go to try to add a new user to my app, instead of getting the alert I am supposed to get, it pops up as [object Object] and nothing gets added to the database. Then this error pops up in the mongo cmd

"Error: document must have an _id before saving".

I've tried commenting out the _id line and I get the right message but still nothing shows up in my database.

Upvotes: 40

Views: 59455

Answers (10)

Rithesh Reddy Pothu
Rithesh Reddy Pothu

Reputation: 1

To make both create and update work without an error. Your schema should have

_id: mongoose.Schema.ObjectId

var UserSchema = new mongoose.Schema({
    _id: mongoose.Schema.ObjectId,
    username: String,
    password: String
}); 

and the object of this schema should have

_id: new mongoose.Types.ObjectId()

This creates an id before saving.

const user = new UserSchema({ 
    _id: new mongoose.Types.ObjectId(), 
    username: '...', 
    password : '...' 
});

Now this can be saved without an error.

return user.save();

Upvotes: 0

Nivethan
Nivethan

Reputation: 3609

NestJS with mongoose (@nestjs/mongoose) solution

I fixed the error by

  1. Removing @Prop() above _id
  2. Add mongoose.Types.ObjectId as type to _id
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import mongoose from 'mongoose';
import { Document } from 'mongoose';

export type CompanyDocument = Company & Document;

@Schema()
export class Company {
  _id: mongoose.Types.ObjectId;

  @Prop({ unique: true })
  name: string;
}

export const CompanySchema = SchemaFactory.createForClass(Company);

Upvotes: 27

Andrea Girardi
Andrea Girardi

Reputation: 4427

_id is added automatically by MongoDb.

If you want to keep _id on your data structure be sure to initialize correctly:

import { Types } from "mongoose";

const obj = new UserSchema({ 
  "_id": new Types.ObjectId(), 
  "username": "Bill", 
  "password" : "...." 
});

Upvotes: 2

majidshakeelshawl
majidshakeelshawl

Reputation: 174

Look the way i fixed was i put just id in json post request and not _id.

Upvotes: 0

Vinci
Vinci

Reputation: 1286

If you are using mongoose with nest js and GraphQL, I have fixed it by changing the id to _id and removing the @prop above it even the null value of the id problem has vanished. example on github

import { ObjectType, Field, Int, ID } from '@nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import { User } from 'src/user/entities/user.entity';
import * as mongoose from 'mongoose';

export type SchoolDocument = School & Document;
@ObjectType()
@Schema()
export class School {
  @Prop()//remove this
  @Field(() => ID,{ nullable: true })
  _id: string;
  @Prop()
  @Field(() => String,{ nullable: true })
  name: string;
  @Field(()=>[User],{nullable:true})
  users:User[];
}
export const SchoolSchema= SchemaFactory.createForClass(School);

Upvotes: 4

Sandip Subedi
Sandip Subedi

Reputation: 1077

In my case, I accidentally had the following at the end of my Schema. Removing that worked:

{ _id: false }

Upvotes: 1

rootfuchs
rootfuchs

Reputation: 93

You can write your model without _id so it will be autogenerated

or

you can use .init() to initialize the document in your DB.

Like:

const mongoose = require('mongoose');

const UserSchema = mongoose.Schema({
  _id: mongoose.Schema.Types.ObjectId,
  username: String,
  password: String
})

module.exports = mongoose.model('User', UserSchema);

and then

const User = require('../models/user');

router.post('/addUser',function(req,res,next){

  User.init() // <- document gets generated

  const user = new User({
    username: req.body.username,
    password: req.body.password
  })

  user.save().then((data)=>{
    console.log('save data: ',data)
   // what you want to do after saving like res.render
  })
}

Upvotes: 8

koque
koque

Reputation: 2256

No need to specify the document _id in your model. The system generates the id automatically if you leave out the _id like so:

var UserSchema = new mongoose.Schema({    
    username: String,
    password: String
}); 

That being said, if you still want to generate the _id yourself, see the answers above.

Upvotes: -2

Sandeep Gupta
Sandeep Gupta

Reputation: 7250

Its pretty simple:

  1. If you have declared _id field explicitly in schema, you must initialize it explicitly
  2. If you have not declared it in schema, MongoDB will declare and initialize it.

What you can't do, is to have it in the schema but not initialize it. It will throw the error you are talking about

Upvotes: 87

user3172272
user3172272

Reputation: 31

Try below snippet I wanted to name _id as userId you can do without it as well.

var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;

var UserSchema = new Schema({
    username: String,
    password: String
});
UserSchema.virtual('userId').get(function(){
    return this._id;
});

Upvotes: 2

Related Questions