乐闻世界logo
搜索文章和话题

Why mongodb output _id instead of id?

1个答案

1

Given you're using Mongoose, you can use 'virtuals', which are essentially fake fields that Mongoose creates. They're not stored in the DB, they just get populated at run time:

javascript
// Duplicate the ID field. Schema.virtual('id').get(function(){ return this._id.toHexString(); }); // Ensure virtual fields are serialised. Schema.set('toJSON', { virtuals: true });

Any time toJSON is called on the Model you create from this Schema, it will include an id field that matches the _id field Mongo generates. Likewise, you can set the behavior for toObject in the same way.

See:

You can abstract this into a BaseSchema for all your models, then extend/invoke to keep the logic in one place. I wrote the above while creating an Ember/Node/Mongoose app, since Ember really prefers to have an id field to work with.

As of Mongoose v4.0, part of this functionality is supported out of the box. It's no longer required to manually add a virtual id field as explained by @Pascal Zajac.

Mongoose assigns each of your schemas an id virtual getter by default, which returns the document's _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it by passing this option at schema construction time. Source

However, to export this field to JSON, it's still required to enable serialization of virtual fields:

javascript
Schema.set('toJSON', { virtuals: true });

I used this:

javascript
schema.set('toJSON', { virtuals: true, versionKey: false, transform: function (doc, ret) { delete ret._id } });

I think it would be great if they automatically suppress _id when virtuals is true.

I create a toClient() method on my models where I do this. It's also a good place to rename/remove other attributes you don't want to send to the client:

javascript
Schema.method('toClient', function() { var obj = this.toObject(); // Rename fields obj.id = obj._id; delete obj._id; return obj; });

Here is an alternative version of the answer provided by @user3087827. If you find that schema.options.toJSON is undefined, then you can use:

javascript
schema.set('toJSON', { transform: function (doc, ret, options) { ret.id = ret._id; delete ret._id; delete ret.__v; } });

MongoDB uses _id as the default field to store the unique identifier of documents (primary key). There are several reasons behind this decision:

  1. Uniqueness: MongoDB designs the _id field to ensure that each document in a collection can be uniquely identified. MongoDB automatically generates an ObjectId type _id value for each new document, which is globally unique—meaning that two documents will not have the same _id even across different servers or clusters.

  2. Consistency: Using _id as the standard field name for all documents provides a consistent interface for developers to reference the primary key. This consistency simplifies data model design and allows developers to write more generic code for handling different documents.

  3. Indexing: In MongoDB, each collection automatically creates a unique index on the _id field. This design ensures fast lookup and efficient data integrity checks. Without this default index, developers would need to manually create indexes for their chosen primary key fields, increasing development complexity.

For example, consider a user collection (collection) containing many user documents (document). Each document will automatically have an _id field, as follows:

json
{ "_id": ObjectId("507f191e810c19729de860ea"), "name": "John Doe", "email": "john.doe@example.com" }

Even if developers choose to use a custom field (such as id) as the document identifier, it is generally recommended to use the default _id field to maintain consistency and leverage MongoDB's built-in indexing. In cases where specific needs arise, developers can map _id to id or any other field they prefer at the application layer. In such cases, developers are responsible for maintaining the uniqueness and indexing of the additional fields.

2024年6月29日 12:07 回复

你的答案