MongoDB:输出'id'而不是'_id'

时间:2011-08-12 01:46:37

标签: mongodb node.js mongoose

我正在使用mongoose(节点),输出id而不是_id的最佳方式是什么?

16 个答案:

答案 0 :(得分:82)

鉴于您使用的是Mongoose,您可以使用'virtuals',它们基本上是Mongoose创建的假字段。它们不存储在数据库中,只是在运行时填充:

// Duplicate the ID field.
Schema.virtual('id').get(function(){
    return this._id.toHexString();
});

// Ensure virtual fields are serialised.
Schema.set('toJSON', {
    virtuals: true
});

在您从此Schema创建的模型上调用toJSON时,它将包含一个与ido生成的_id字段匹配的“id”字段。同样,您可以以相同的方式设置toObject的行为。

见:

您可以将其抽象为BaseSchema,然后扩展/调用所有模型以将逻辑保存在一个位置。我在创建Ember / Node / Mongoose应用程序时编写了上述内容,因为Ember真的更喜欢使用“id”字段。

答案 1 :(得分:29)

我在我的模型上创建了一个toClient()方法。它也是重命名/删除您不想发送给客户端的其他属性的好地方:

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

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

    return obj;
});

答案 2 :(得分:23)

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

有一个“Schema.options.toObject.transform”属性可以反向执行,或者您可以将其设置为虚拟ID。

答案 3 :(得分:22)

截至Mongoose v4.0 此功能的一部分支持开箱即用。如@Pascal Zajac所解释的那样,不再需要手动添加虚拟id字段。

  

Mongoose默认为每个模式分配一个id虚拟getter   它返回文件_id字段强制转换为字符串,或者在这种情况下   ObjectIds,其hexString。如果您不想添加id getter   您的架构,您可以禁用它在架构上传递此选项   施工时间。 Source

但是,要导出此字段为 JSON ,仍然需要启用虚拟字段的序列化:

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

答案 4 :(得分:20)

以下是@ user3087827提供的答案的替代版本。如果您发现schema.options.toJSON未定义,则可以使用:

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

答案 5 :(得分:8)

我用过这个:

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

我认为如果虚拟为真,它们会自动抑制_id会很棒。

答案 6 :(得分:5)

如果要全局使用id而不是_id ,则可以在猫鼬对象(starting from v5.3)上设置toJSON配置:< / p>

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

答案 7 :(得分:4)

我为此目的创建了一个易于使用的plugin,我可以全局申请所有项目和所有架构。它会将_id转换为id并同时删除__v参数。

所以它转换:

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

更简单,更清洁:

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

用作全局插件:

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

或者对于特定架构:

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

希望这有助于某人。

答案 8 :(得分:1)

如果您使用lodash来选择所需的元素,这将为您工作。

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

答案 9 :(得分:0)

有另一个驱动程序执行http://alexeypetrushin.github.com/mongo-liteconvertId选项设置为true。有关详细信息,请参阅“默认值和设置”部分。

答案 10 :(得分:0)

您还可以在搜索要返回的项目时使用聚合函数。 $ project将允许您创建字段,您可以将其分配给_id。

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

答案 11 :(得分:0)

用新的方法覆盖默认方法toJSON

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

答案 12 :(得分:0)

还有normalize-mongoose个简单的软件包,可为您删除_id__v

从类似这样的东西:

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

因此,假设您有类似这样的内容:

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

您将获得以下输出:

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

答案 13 :(得分:0)

覆盖特定模型模式的toJSON方法。 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
  }
}

答案 14 :(得分:0)

创建基本架构

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

现在在猫鼬模型中,使用BaseSchema代替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);

@Pascal Zajac答案的打字稿实现

答案 15 :(得分:0)

你也可以使用 pre 'save' 钩子:

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