MongoDB: output 'id' instead of '_id'

Mongodbnode.jsMongoose

Mongodb Problem Overview


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

Mongodb Solutions


Solution 1 - Mongodb

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:

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.

Solution 2 - Mongodb

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
});

Solution 3 - Mongodb

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;
});

Solution 4 - Mongodb

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.

Solution 5 - Mongodb

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;
     }
}); 

Solution 6 - Mongodb

//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.

Solution 7 - Mongodb

If you want to use id instead of _id globally then you can set toJSON config on mongoose object(starting from v5.3):

mongoose.set('toJSON', {
  virtuals: true,
  transform: (doc, converted) => {
    delete converted._id;
  }
});

Solution 8 - Mongodb

There is also normalize-mongoose a simple package that removes _id and __v for you.

From something like this:

import mongoose from 'mongoose';
import normalize from 'normalize-mongoose';

const personSchema = mongoose.Schema({ name: String });

personSchema.plugin(normalize);

const Person = mongoose.model('Person', personSchema);
const someone = new Person({ name: 'Abraham' });
const result = someone.toJSON();

console.log(result);

So let's say you have something like this:

{
  "_id": "5dff03d3218b91425b9d6fab",
  "name": "Abraham",
  "__v": 0
}

You will get this output:

{
  "id": "5dff03d3218b91425b9d6fab",
  "name": "Abraham"
}

Solution 9 - Mongodb

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.

Solution 10 - Mongodb

Overwrite default method toJSON by new one:

schema.method('toJSON', function () {
   const { __v, _id, ...object } = this.toObject();
   object.id = _id;
   return object;
});

Solution 11 - Mongodb

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) => {
 // 
})

Solution 12 - Mongodb

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']
  );

Solution 13 - Mongodb

Override toJSONmethod for specific model schema. https://mongoosejs.com/docs/api.html#schema_Schema-method

YourSchema.methods.toJSON = function () {
  return {
    id: this._id,
    some_field: this.some_field,
    created_at: this.createdAt
  }
}

Solution 14 - Mongodb

Create a base schema

import { Schema } from "mongoose";

    export class BaseSchema extends Schema {
        constructor(sche: any) {
            super(sche);
            this.set('toJSON', {
        virtuals: true,
        transform: (doc, converted) => {
            delete converted._id;
        }
    });
        }
    
    }

Now in your mongoose model, use BaseSchema instead of Schema

import mongoose, { Document} from 'mongoose';
import { BaseSchema } from '../../helpers/mongoose';

const UserSchema = new BaseSchema({
    name: String,
    age: Number,

});

export interface IUser {
    name: String,
    age: Number,

}

interface IPlanModel extends IUser, Document { }

export const PlanDoc = mongoose.model<IPlanModel>('User', UserSchema);

Typescript implementation of @Pascal Zajac answer

Solution 15 - Mongodb

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.

Solution 16 - Mongodb

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.

https://mongoosejs.com/docs/guide.html

Solution 17 - Mongodb

You can also use pre 'save' hook:

TouSchema.pre('save', function () {      
  if (this.isNew) {
    this._doc.id = this._id;      
  } 
}

Solution 18 - Mongodb

JSON.parse(JSON.stringify(doc.toJSON()))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohnnyView Question on Stackoverflow
Solution 1 - MongodbPascal ZajacView Answer on Stackoverflow
Solution 2 - MongodbxaviertView Answer on Stackoverflow
Solution 3 - MongodbevilceleryView Answer on Stackoverflow
Solution 4 - MongodbBenamarView Answer on Stackoverflow
Solution 5 - MongodbTom MakinView Answer on Stackoverflow
Solution 6 - Mongodbuser3087827View Answer on Stackoverflow
Solution 7 - MongodbMurat ÇorluView Answer on Stackoverflow
Solution 8 - MongodbabranheView Answer on Stackoverflow
Solution 9 - MongodbAdam ReisView Answer on Stackoverflow
Solution 10 - MongodbStan FadView Answer on Stackoverflow
Solution 11 - Mongodbuser2062241View Answer on Stackoverflow
Solution 12 - MongodbIvor ScottView Answer on Stackoverflow
Solution 13 - MongodbSen SokhaView Answer on Stackoverflow
Solution 14 - Mongodbd-feverxView Answer on Stackoverflow
Solution 15 - MongodbAlex CraftView Answer on Stackoverflow
Solution 16 - MongodbMcNiddayView Answer on Stackoverflow
Solution 17 - MongodbGeorgi PopovView Answer on Stackoverflow
Solution 18 - MongodbCyberT33NView Answer on Stackoverflow