如何在Mongoose虚拟属性中使用asynchronous代码?

我试图在不同的集合(而不是embedded的文档)中关联文档,而在Mongooose中有一个问题 ,我试图通过延迟加载关联的文档, mongoose网站 。

问题是虚拟的getter将函数作为参数,并使用virtual属性的返回值。 当虚拟机不需要任何asynchronous调用来计算它的值时,这是非常好的,但是当我需要进行asynchronous调用来加载其他文档时,虚拟机不起作用。 以下是我正在使用的示例代码:

TransactionSchema.virtual('notebook') .get( function() { // <-- the return value of this function is used as the property value Notebook.findById(this.notebookId, function(err, notebook) { return notebook; // I can't use this value, since the outer function returns before we get to this code }) // undefined is returned here as the properties value }); 

这是行不通的,因为函数在asynchronous调用完成之前返回。 有没有办法我可以使用stream量控制库来使这个工作,或者我可以修改第一个函数,以便我将findById调用传递给getter而不是匿名函数?

您可以定义一个虚拟方法,您可以为其定义callback。

用你的例子:

 TransactionSchema.method('getNotebook', function(cb) { Notebook.findById(this.notebookId, function(err, notebook) { cb(notebook); }) }); 

而唯一的评论者似乎是那些迂腐的types之一,你也不应该害怕embedded文件。 它是我所了解的mongos之一。

一个使用上面的代码是这样的:

 instance.getNotebook(function(nootebook){ // hey man, I have my notebook and stuff }); 

虽然这涉及更广泛的问题,而不是具体的问题,但我仍然认为值得提交:

您可以使用Mongoose的查询填充函数轻松地从另一个集合(与定义虚拟结果几乎相同)加载关联的文档。 使用上面的例子,这需要在Transaction模式中指定ObjectID的引用(指向Notebook集合),然后在构造查询时调用populate(NotebookId) 。 链接的Mongoose文档很好地解决了这个问题。

我不熟悉mongoose的历史,但是我猜这些早期的答案提交后, populate不存在。

乔希的方法很适合单一文件查找,但是我的情况稍微复杂一些。 我需要对整个对象数组进行嵌套属性查找。 例如,我的模型看起来更像这样:

 var TransactionSchema = new Schema({ ... , notebooks: {type: [Notebook]} }); var NotebookSchema = new Schema({ ... , authorName: String // this should not necessarily persist to db because it may get stale , authorId: String }); var AuthorSchema = new Schema({ firstName: String , lastName: String }); 

然后,在我的应用程序代码(我使用Express)中,当我得到一个Transaction时,我想要所有的笔记本都带有作者的姓氏:

 ... TransactionSchema.findById(someTransactionId, function(err, trans) { ... if (trans) { var authorIds = trans.notebooks.map(function(tx) { return notebook.authorId; }); Author.find({_id: {$in: authorIds}, [], function(err2, authors) { for (var a in authors) { for (var n in trans.notebooks { if (authors[a].id == trans.notebooks[n].authorId) { trans.notebooks[n].authorLastName = authors[a].lastName; break; } } } ... }); 

这似乎是非常低效和黑客,但我想不出另一种方法来实现这一点。 最后,我是新的node.js,mongoose,和stackoverflow,所以原谅我,如果这不是最适当的地方来扩大这个讨论。 只是乔希的解决scheme在我最终的“解决scheme”中是最有帮助的。

由于这是一个老问题,我想它可能会使用更新。

要实现asynchronous虚拟字段,可以使用mongoose-fill ,如mongoose的github问题所述: https : //github.com/Automattic/mongoose/issues/1894