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

Joh*_*nny 50 mongoose mongodb node.js

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

Pas*_*jac 91

鉴于你使用的是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
});
Run Code Online (Sandbox Code Playgroud)

任何时候在你从这个Schema创建的模型上调用toJSON,它将包含一个'id'字段,它匹配Mongo生成的_id字段.同样,您可以以相同的方式设置toObject的行为.

看到:

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

  • 非常好的解决方案(+1).我还要添加`Schema.set('toObject',{virtuals:true})`,以便在使用`console.log(obj)`时能够看到输出中的虚拟内容. (5认同)
  • 这会保留_id字段.我更喜欢变换解决方案,shakinfree提供的解决方案为我工作. (4认同)
  • 'toJson'仅在转换为JSON时使用.更一般的方法是使用`toObject`.http://mongoosejs.com/docs/guide.html#toObject (2认同)

evi*_*ery 30

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

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

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

    return obj;
});
Run Code Online (Sandbox Code Playgroud)

  • 虚拟可能就是你想要的. (3认同)
  • 我对猫鼬真的很陌生,这似乎正是我想要的。你怎么称呼这个 toClient?通常我会执行 find() 并获取一个 docs 对象,然后执行 res.send(docs)。那么在这种情况下,我是否在每个文档上调用 res.write(docs[1].toClient()) ?谢谢 (2认同)
  • 这现在似乎对我不起作用 - Mongoose 中执行此操作的方法是否已更改? (2认同)

xav*_*ert 28

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

Mongoose默认情况下为每个模式分配一个id虚拟getter,它返回文件_id字段强制转换为字符串,或者对于ObjectIds,返回其hexString.如果您不希望将ID getter添加到架构中,则可以在架构构建时禁用它以传递此选项.资源

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

Schema.set('toJSON', {
    virtuals: true
});
Run Code Online (Sandbox Code Playgroud)

  • 这在v4.0之前就已经存在了,但OP想要的是*just*id(而不是_id)被返回.只是告诉mongoose包含虚拟id返回两者. (3认同)
  • 如果您想排除其他虚拟机怎么办? (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;
}
Run Code Online (Sandbox Code Playgroud)

有一个"Schema.options.toObject.transform"属性来执行相反的操作,或者您可以将其设置为虚拟ID.


Tom*_*kin 21

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

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


小智 14

我用过这个:

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

我认为如果它们在virtuals为true时自动抑制_id会很棒.

  • 这对我有用。其中 schema 是您创建的每个模型。例如:`const UserSchema = new Schema({ stuff }); UserSchema.set("toJSON", { virtuals: true, versionKey: false, transform: function(doc, ret) { 删除 ret._id; } }); const User = model("用户", UserSchema);` (2认同)

Mur*_*rlu 10

如果要使用id而不是_id 全局使用,则可以toJSONmongoose对象上设置配置(从 v5.3 开始):

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


Sta*_*Fad 7

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

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


Abr*_*dez 7

还有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);
Run Code Online (Sandbox Code Playgroud)

所以假设你有这样的事情:

{
  "_id": "5dff03d3218b91425b9d6fab",
  "name": "Abraham",
  "__v": 0
}
Run Code Online (Sandbox Code Playgroud)

你会得到这个输出:

{
  "id": "5dff03d3218b91425b9d6fab",
  "name": "Abraham"
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*eis 5

为此,我创建了一个易于使用的插件,将其应用于所有项目以及全球所有架构。它将转换_id为参数id并剥离__v

因此它转换为:

{
  "_id": "400e8324a71d4410b9dc3980b5f8cdea",
  "__v": 2,
  "name": "Item A"
}
Run Code Online (Sandbox Code Playgroud)

为了更简单,更清洁:

{
  "id": "400e8324a71d4410b9dc3980b5f8cdea",
  "name": "Item A"
}
Run Code Online (Sandbox Code Playgroud)

用作全局插件:

const mongoose = require('mongoose');
mongoose.plugin(require('meanie-mongoose-to-json'));
Run Code Online (Sandbox Code Playgroud)

或针对特定架构:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const MySchema = new Schema({});
MySchema.plugin(require('meanie-mongoose-to-json'));
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助。


use*_*241 5

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

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