Mongoose模式/模型中的自定义构造函数

14
问候大家!
我定义了一个Mongoose模式,如下所示,并注册了一个模型(InventoryItemModel)。是否有办法为该模式创建自定义构造函数,以便在我从模型实例化对象时,将调用该函数(例如,从数据库加载对象的值)?
var mongoose = require('mongoose')
  , Schema = mongoose.Schema

var InventoryItemSchema = new Schema({
    Sku : String
  , Quanity : Number
  , Description : String
  , Carted : []
  , CreatedDate  : {type : Date, default : Date.now}
  , ModifiedDate  : {type : Date, default : Date.now}
});

mongoose.model('InventoryItem', InventoryItemSchema);

var item = new InventoryItem();

我可以添加自定义构造函数,以便在实例化时从数据库中填充该项吗?


你能给一个具体的例子来说明你想做什么吗? - JohnnyHK
嗨,我想创建一个库存管理系统。上述对象表示一个物品。某些API将把物品推送到数据库中,在我的程序中,当我实例化一个对象时,希望模型从数据库中加载一个物品。 - Gary
1
请查看Mongoose对于向模型添加静态构造函数方法的支持 - JohnnyHK
5个回答

15

根据您想要采取的方向,您可以:

1) 使用Hooks

Hooks在模型初始化、验证、保存和删除时会自动触发。这是一种“内部解决方案”。您可以在此处查看文档:

2) 为架构编写静态创建函数。

Statics位于您的模型对象上,可用于替换创建新模型等功能。如果您有额外的逻辑需要处理create步骤,可以在静态函数中自己编写。这是一种“外部解决方案”:


2
你如何准确地执行#2(静态创建函数)?在Mongoose指南中似乎没有任何示例,只是添加一个myschema.static.create函数似乎没有任何作用。 - ragulka
那个链接 (#statics) 展示了如何编写静态方法。只需编写您自己的静态方法(例如 createNew),在创建时通过任何逻辑即可。 - hunterloftis
抱歉,我把方法和静态属性搞混了。 - ragulka
2
我也做了2),但我认为这个方法不应该被命名为create,因为它会与Model.create发生冲突。不确定覆盖该方法是否有害,但使用另一个名称更安全,比如makeinitialize等。 - zaboco

6
这是对@hunterloftis的答案中第二个选项的实现。

2) 为您的模式编写一个静态创建函数。

someSchema.statics.addItem = function addItem(item, callback){
//Do stuff (parse item)
 (new this(parsedItem)).save(callback);
}

当你想要从一些模式(someSchema)创建一个新的模型时,不要

var item = new ItemModel(itemObj);
item.save(function (err, model) { /* etc */ });

做这个

ItemModel.addItem(itemObj, function (err, model) { /* etc */ });

2
我遇到过这个问题,编写了一个mongoose插件来帮助解决你的问题。
var mongoose = require('mongoose')
  , Schema = mongoose.Schema
  , construct = require('mongoose-construct')

var user = new Schema({})
user.plugin(construct)

user.pre('construct', function(next){
    console.log('Constructor called...')
    next()
})

var User = mongoose.model('User', user)
var myUser = new User(); // construct hook will be called

这里是代码库(也可在npm上获取):https://github.com/IlskenLabs/mongoose-construct

这是一个很棒的想法。但它能捕获传递给模式构造函数的参数吗?例如,如果我想调用 var myUser = new User({foo:'bar'}) 来在创建时配置用户的某个属性,那么有没有办法从你的预构造函数中访问那个 'foo' 呢? - VictorB
@Victorb,说实话,我甚至不记得这是如何工作的了,而且我严重怀疑它是否适用于最新版本的mongoose。抱歉! - Christopher Tarquini
1
@Victorb 看了一下,很抱歉似乎没有任何钩子可以实现这个功能而不会破坏其他东西。我会创建一个包装类,接受参数并在内部初始化一个 mongoose 模型。 - Christopher Tarquini

0

@hunterloftis 给了我需要的答案。现在,将近6年后,这是我为其他人提供的解决方案。

InventoryItemSchema.static( 'new', function( that )
{
    let instance = new InventoryItemSchema();
    Object.assign( instance, that );
    return instance;
});

或者使用一行代码(这种方式不太便于调试)

InventoryItemSchema.static( 'new', function( that )
{return Object.assign( new InventoryItemSchema(), that );});

无论如何,您想要的地方
let inventoryItem = new InventoryItemSchema({...});

你将会有

let inventoryItem = InventoryItemSchema.new({...});

-5

你需要进行导出。这里有一个例子:

import mongoose from "mongoose";

let  Schema = mongoose.Schema;


let restaurentSchema = new Schema({
  name : String
})

//export

module.exports = mongoose.model("Restaurent", restaurentSchema)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接