【发布时间】:2011-10-25 11:28:53
【问题描述】:
我正在使用猫鼬(节点),输出id而不是_id的最佳方法是什么?
【问题讨论】:
-
对于新读者:下面您将看到多种不同方法。在选择之前阅读它们是明智的,而不是盲目地去接受或大多数选票。干杯!
我正在使用猫鼬(节点),输出id而不是_id的最佳方法是什么?
【问题讨论】:
鉴于您使用的是 Mongoose,您可以使用“虚拟”,它们本质上是 Mongoose 创建的假字段。它们不存储在数据库中,只是在运行时填充:
// Duplicate the ID field.
Schema.virtual('id').get(function(){
return this._id.toHexString();
});
// Ensure virtual fields are serialised.
Schema.set('toJSON', {
virtuals: true
});
任何时候在你从这个模式创建的模型上调用 toJSON 时,它都会包含一个与 Mongo 生成的 _id 字段匹配的“id”字段。同样,您可以以相同的方式设置 toObject 的行为。
见:
您可以将所有模型抽象为 BaseSchema,然后扩展/调用以将逻辑保存在一个位置。我在创建 Ember/Node/Mongoose 应用程序时编写了上述内容,因为 Ember 确实更喜欢使用“id”字段。
【讨论】:
Schema.set('toObject', { virtuals: true }) 以便在使用console.log(obj) 时能够在输出中看到虚拟。
toObject。 mongoosejs.com/docs/guide.html#toObject
const companyCollection = mongoose.Schema({}); 下
id getter。 mongoosejs.com/docs/guide.html#id
从 Mongoose v4.0 开始,此功能的一部分是开箱即用支持。正如@Pascal Zajac 所述,不再需要手动添加虚拟id 字段。
默认情况下,Mongoose 会为您的每个模式分配一个 id virtual getter 它将文档 _id 字段转换为字符串,或者在这种情况下 ObjectIds,它的 hexString。如果您不想将 id getter 添加到 您的架构,您可以在架构处通过此选项禁用它 施工时间。 Source
但是,要将这个字段导出到JSON,仍然需要启用虚拟字段的序列化:
Schema.set('toJSON', {
virtuals: true
});
【讨论】:
我在执行此操作的模型上创建了一个 toClient() 方法。这也是重命名/删除您不想发送给客户端的其他属性的好地方:
Schema.method('toClient', function() {
var obj = this.toObject();
//Rename fields
obj.id = obj._id;
delete obj._id;
return obj;
});
【讨论】:
我用过这个:
schema.set('toJSON', {
virtuals: true,
versionKey:false,
transform: function (doc, ret) { delete ret._id }
});
我认为如果它们在 virtuals 为 true 时自动抑制 _id 会很棒。
【讨论】:
const UserSchema = new Schema({ stuff }); UserSchema.set("toJSON", { virtuals: true, versionKey: false, transform: function(doc, ret) { delete ret._id; } }); const User = model("user", UserSchema);
lean: true 选项。
这是@user3087827 提供的答案的替代版本。如果您发现 schema.options.toJSON 未定义,则可以使用:
schema.set('toJSON', {
transform: function (doc, ret, options) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
}
});
【讨论】:
//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。
【讨论】:
如果你想使用id 而不是_id 全局 那么你可以在猫鼬对象上设置toJSON 配置(starting from v5.3):
mongoose.set('toJSON', {
virtuals: true,
transform: (doc, converted) => {
delete converted._id;
}
});
【讨论】:
还有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"
}
【讨论】:
为此,我创建了一个易于使用的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'));
希望这对某人有所帮助。
【讨论】:
用新方法覆盖默认方法toJSON:
schema.method('toJSON', function () {
const { __v, _id, ...object } = this.toObject();
object.id = _id;
return object;
});
【讨论】:
您还可以在搜索要返回的项目时使用聚合函数。 $project 将允许您创建字段,您可以执行此操作并将其分配给 _id。
<model>.aggregate([{$project: {_id: 0, id: '$_id'}], (err, res) => {
//
})
【讨论】:
如果你使用 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']
);
【讨论】:
覆盖特定模型架构的 toJSONmethod。
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
}
}
【讨论】:
创建基本架构
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 答案的打字稿实现
【讨论】:
还有另一个驱动程序可以做到这一点 http://alexeypetrushin.github.com/mongo-lite 将 convertId 选项设置为 true。有关详细信息,请参阅“默认值和设置”部分。
【讨论】:
你也可以使用 pre 'save' 钩子:
TouSchema.pre('save', function () {
if (this.isNew) {
this._doc.id = this._id;
}
}
【讨论】:
JSON.parse(JSON.stringify(doc.toJSON()))
【讨论】: