MongoDB: output 'id' instead of '_id&#

2019-01-10 06:48发布

问题:

I am using mongoose (node), what is the best way to output id instead of _id?

回答1:

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:

Schema.method('toClient', function() {
    var obj = this.toObject();

    //Rename fields
    obj.id = obj._id;
    delete obj._id;

    return obj;
});


回答2:

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:

// 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 behaviour for toObject in the same way.

See:

  • http://mongoosejs.com/docs/api.html
  • http://mongoosejs.com/docs/guide.html#toJSON
  • http://mongoosejs.com/docs/guide.html#toObject

You can abstract this into a BaseSchema 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.



回答3:

//Transform
Schema.options.toJSON.transform = function (doc, ret, options) {
  // remove the _id of every document before returning the result
  ret.id = ret._id;
  delete ret._id;
  delete ret.__v;
}

there is a "Schema.options.toObject.transform" property to do the reverse or you could just setup as a virtual id.



回答4:

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 documents _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 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:

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


回答5:

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

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


回答6:

I used this :

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.



回答7:

I created an easy to use plugin for this purpose that I apply for all my projects and to all schema's globally. It converts _id to id and strips the __v parameter as well.

So it converts:

{
  "_id": "400e8324a71d4410b9dc3980b5f8cdea",
  "__v": 2,
  "name": "Item A"
}

To a simpler and cleaner:

{
  "id": "400e8324a71d4410b9dc3980b5f8cdea",
  "name": "Item A"
}

Usage as a global plugin:

const mongoose = require('mongoose');
mongoose.plugin(require('meanie-mongoose-to-json'));

Or for a specific schema:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const MySchema = new Schema({});
MySchema.plugin(require('meanie-mongoose-to-json'));

Hope this helps someone.



回答8:

There's another driver that does that http://alexeypetrushin.github.com/mongo-lite set convertId option to true. See "Defaults & Setting" section for more details.



回答9:

You can also use the aggregate function when searching for items to return. $project will allow you to create fields, which you can do and assign it to _id.

<model>.aggregate([{$project: {_id: 0, id: '$_id'}], (err, res) => {
 // 
})


回答10:

If you are using lodash to pick the elements you want, this will work for you.

UserSchema.virtual('id').get(function(){
  return this._id.toHexString();
});

UserSchema.set('toObject', { virtuals: true })

UserSchema.methods.toJSON = function() {
  return _.pick( 
    this.toObject(), 
    ['id','email','firstName','lastName','username']
  );