这是一个架构问题。我有这样的模型:
var foo = new mongoose.Schema({
name: String,
bars: [{type: ObjectId, ref: 'Bar'}]
});
var FooModel = mongoose.model('Foo', foo);
var bar = new mongoose.Schema({
foobar: String
});
var BarModel = mongoose.model('Bar', bar);
然后我想实现这样的便利方法:
BarModel.methods.addFoo = function(foo) {
foo.bars = foo.bars || []; // Side note, is this something I should check here?
foo.bars.push(this.id);
// Here's the line I'm wondering about... Should I include the line below?
foo.save();
}
我看到的最大问题是,如果我确实包含foo.save()
,那么我应该将回调传递给addFoo
,这样我就避免了异步操作的问题。我认为这不是更好。但是我也认为包括因为addFoo
在保存之前没有真正“添加了”...会很好...我是否打破了任何设计最佳实践呢?
答案 0 :(得分:1)
foo.bars = foo.bars || []; //旁注,这是我应该在这里查看的内容吗?
不,猫鼬会为你处理。 foo.bars
最初总是一个空数组。
我认为在其他辅助方法中隐式保存是一个糟糕的设计选择。您的API受众知道他们正在制作数据库记录,他们理解save()
的概念,这很简单。与mongoose的其余部分保持一致,使模型实例上的操作在内存中,直到调用显式save()
为止。
但是,如果您最终在您编写的方法中执行任何I / O,则必须遵守接受回调函数的节点约定并在完成时使用error, results
调用它。否则,你的应用程序会因为脆弱和竞争条件以及各种各样的肮脏而设置。
答案 1 :(得分:1)
如果添加“foo”并保存是一种常见的使用模式(并且它是处理BarModel
的最后一次操作,因此不会不必要地完成多个saves
),我会期望它被恰当地命名,以便它显然具有明显的副作用,如addFooAndSave
。但为了与Node.JS约定保持一致,我还会添加你提到的回调(你可以把它传递给save
):
BarModel.methods.addFooAndSave = function(foo, callback) {
// foo.bars = foo.bars || []; // not needed, auto initialized to empty
foo.bars.push(this.id);
// Here's the line I'm wondering about... Should I include the line below?
foo.save(callback);
}
这样你就可以打电话:
bar.addFooAndSave(function(err, bar, numAffected) {
// response
});
否则,如果保存不常见,我会将其作为一个明确的步骤并将“foo”添加为您拥有的方法,然后在模型实例上显式调用save
。