29
votes

is there a way to declare a Model schema in mongoose so that when the model is new'ed the _id field would auto-generate?

for example:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectIdSchema = Schema.ObjectId;
var ObjectId = mongoose.Types.ObjectId;

var PersonSchema = new Schema({
    _id:            ObjectIdSchema,
    firstName:      {type: String, default: 'N/A'},
    lastName:       {type: String, default: 'N/A'},
    age:            {type: Number, min: 1}
});

var Person = mongoose.model('Person', PersonSchema);

at first, i thought great!, i'll just do

_id:    {type:ObjectIdSchema, default: new ObjectId()}

but of course that doesn't work, because new ObjectId() is only called on initialize of schema. so calling new Persion() twice creates two objects with the same _id value.

so is there a way to do it so that every time i do "new Person()" that a new ObjectId() is generated?

the reason why i'm trying to do this is because i need to know the value of the new person's _id value for further processing.

i also tried:

var person = new Person({firstName: "Joe", lastName: "Baz"});
person.save(function(err, doc, num){
    console.log(doc._id);
});

even then, doc doesn't contain the ObjectId. but if i look in the database, it does contain it.

p.s. i'm using mongoose 2.7.1

p.p.s. i know i can manually create the ObjectId when creating the person as such:

var person = new Person({_id: new ObjectId(), firstName: "Joe", lastName: "Baz"});

but i rather not have to import ObjectId and have to new it every time i want to new a Person. guess i'm used to using the java driver for mongodb, where i can just create the value for the _id field in the Model constructor.

5

5 Answers

30
votes

the moment you call var person = new Person(); person._id should give you the id (even if it hasn't been saved yet). Just instantiating it is enough to give it an id. You can still save it after, and that will store the id as well as the rest of the person object

27
votes

Add the auto flag:

_id: {
    type: mongoose.Schema.Types.ObjectId,
    index: true,
    required: true,
    auto: true,
  }

source

14
votes

Instead of:

_id:    {type:ObjectIdSchema, default: new ObjectId()}

You should do:

_id:    {type:ObjectIdSchema, default: function () { return new ObjectId()} }
9
votes

Taken from the official MongoDB Manual and Docs:

_id

A field required in every MongoDB document. The _id field must have a unique value. You can think of the _id field as the document’s primary key. If you create a new document without an _id field, MongoDB automatically creates the field and assigns a unique BSON ObjectId.
Source


ObjectID

ObjectIds are small, likely unique, fast to generate, and ordered. ObjectId values consist of 12 bytes, where the first four bytes are a timestamp that reflect the ObjectId’s creation. Specifically:

a 4-byte value representing the seconds since the Unix epoch, a 5-byte random value, and a 3-byte counter, starting with a random value. In MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key. If an inserted document omits the _id field, the MongoDB driver automatically generates an ObjectId for the _id field.

This also applies to documents inserted through update operations with upsert: true.

MongoDB clients should add an _id field with a unique ObjectId. Using ObjectIds for the _id field provides the following additional benefits: in the mongo shell, you can access the creation time of the ObjectId, using the ObjectId.getTimestamp() method. sorting on an _id field that stores ObjectId values is roughly equivalent to sorting by creation time.

IMPORTANT
While ObjectId values should increase over time, they are not necessarily monotonic. This is because they:

Only contain one second of temporal resolution, so ObjectId values created within the same second do not have a guaranteed ordering, and Are generated by clients, which may have differing system clocks.
Source

Explicitly declaring _id:

When explicitly declaring the _id field, specify the auto option:

new Schema({ _id: { type: Schema.ObjectId, auto: true }})

ObjectId only - Adds an auto-generated ObjectId default if turnOn is true.
Source


TL;DR

If you create a new document without an _id field, MongoDB automatically creates the field and assigns a unique BSON ObjectId.

0
votes

This is good way to do this

in model:

const schema = new Schema({ userCurrencyId:{type: mongoose.Schema.Types.ObjectId,
        index: true,
        required: true,
        auto: true});