From the documentation:
Mongoose assigns each of your schemas an
idvirtual getter by default, which returns the document's_idfield cast to a string, or in the case ofObjectIds, itshexString.
So, basically, the id getter returns a string representation of the document's _id (which is added to all MongoDB documents by default and has a default type of ObjectId).
Regarding what is better for referencing, it depends entirely on the context (i.e., whether you want an ObjectId or a string). For example, when comparing id values, the string is generally better because ObjectId instances won't pass an equality test unless they are the same instance (regardless of their actual values).
In Mongoose, _id is the default primary key for a document, while id is a virtual getter for the _id field of type ObjectId.
Detailed explanation follows:
_id
-
Each document created in MongoDB has a unique
_idfield, which is automatically generated when the document is created. -
The
_idfield defaults to anObjectIdobject, which is a 12-byte unique value, and MongoDB uses this field as the primary key. -
An
ObjectIdincludes a timestamp (the time the document was created), machine identifier, MongoDB process ID, and sequence number, which ensure the uniqueness of_idin distributed systems.
id
-
The
idproperty is a virtual getter provided by Mongoose for the_idfield, which is essentially the string representation of_id. -
When accessing the
idproperty, Mongoose calls the.toString()method on the_idfield to convert it into a 24-character hexadecimal string. -
Since
idis virtual, it does not actually exist in the MongoDB database; it is merely a convenience provided at the Mongoose level.
Use Cases
When you need to use the document's primary key in your program, you can directly use the _id field. If you need to send the document's primary key as a string to the frontend or as part of a URL, such as in RESTful APIs where string-formatted IDs are typically used, you can use the id property.
Example
Assume you have a user document with _id field as ObjectId('507f191e810c19729de860ea'), you can access the document's ID as follows:
javascriptconst user = await User.findById('507f191e810c19729de860ea'); console.log(user._id); // prints ObjectId('507f191e810c19729de860ea') console.log(user.id); // prints the string form of '507f191e810c19729de860ea'
In the above code, user._id returns an ObjectId object, while user.id returns the corresponding string form. When you need to pass or display this ID in plain text, the id property is very useful.
In summary, _id is the actual primary key of the document in the database, while id is a convenient virtual property.