我试图避免数据库回调查询。
假设您有两个类似的模式:
1st) 用户架构
username : {type: String, unique: true},
age : {type: Number}
2) 活动架构
owner: [{type: Schema.Types.ObjectId, ref: 'User'}],
city: {type: String},
date: {type: Date}
到目前为止一切顺利。
现在假设你有一条前往/user/:id
的路线,你期望的是获得username
和age
,但是如果我还希望返回该路线怎么办? 最新活动?
编辑:请注意latest activity
不是数据库中的值。它会像activity.find({owner: ObjectId(id)}).sort({date: -1}).limit(1)
现在做了什么:
User.findOne({username:req.params.username}).lean().exec(function(err,userDoc)
{
if(err) return errHandler(err);
Activity.findOne({owner:userDoc.username}).sort({date:-1}).exec(function(err,EventDoc){
if(err) return errHandler(err);
userDoc.latest_activity = EventDoc._id;
res.json(userDoc);
res.end();
})
})
以上代码段的问题是难以维护, 如果我们想要为此API功能添加更多内容,该怎么办?除非我们实施Q,否则我们最终会回调查询。
我们试图看看虚拟,但问题在于你无法做到 真的在mongoose Virtual里面查询,因为它返回一个 竞争条件,你很可能没准时得到那份文件。
我们也尝试查看populate,但我们无法做到这一点,因为有关populate的文档非常差。
问题: 无论如何使这更加模块化?
有没有办法避免地狱的数据库查询回调?
例如,这种事情可能吗?
User.findOne({username:req.params.username}).lean().populate(
{path:'Event',sort:{Date:-1}, limit(1)}
).exec(function(req,res))...
谢谢!
答案 0 :(得分:4)
在这种情况下,处理它的最佳方法是在Activity
架构中添加一个帖子保存挂钩,以便将最新的_id
存储在latest_activity
的{{1}}路径中{1}}架构。这样,您无需进行额外查询即可始终访问ID。
User
答案 1 :(得分:4)
受@ BrianShambien的回答启发,您可以使用帖子保存,但不是仅将_id
存储在用户上,而是存储仅包含最后一个活动的子文档。然后,当你抓住那个用户时,它就有了最后一个活动。
用户模型
username : {type: String, unique: true},
age : {type: Number},
last_activity: ActivitySchema
然后在ActivitySchema
ActivitySchema.post('save', function(doc) {
UserSchema.findOne({username: doc.owner}).exec(function(err, user){
if (err) errHandler(err);
user.last_activity = doc;
user.save(function(err) {
if (err) errHandler(err);
});
});
});
********** UPDATE ************
如果用户不是所有者,而是该活动的参与者,则包括对用户的更新。
ActivitySchema.post('save', function(doc) {
findAndUpdateUser(doc.owner, doc);
if (doc.participants) {
for (var i in doc.participants) {
findAndUpdateUser(doc.participants[i], doc);
}
}
});
var findAndUpdateUser = function (username, doc) {
UserSchema.findOne({username: username}).exec(function (err, user) {
if (err) errHandler(err);
user.last_activity = doc;
user.save(function (err) {
if (err) errHandler(err);
});
});
});