使用嵌套模式保存并查找带有参考和承诺的Mongoose文档

我有一个相当简单的问题。 我试图保存一个文档,其模式包括一个嵌套模式引用,该模式引用包括另一个模式引用。 但是,当我去检索该文档时,它不包含(必填)嵌套字段,除非将其填充到相同的查询中。 即使填充查询,但是,第二个嵌套的文档不填充。 我在这里误解了mongoose的工作方式吗?

下面的JavaScript和LiveScript示例代码和输出。


JavaScript的:

(function(){ var mongoose, bookSchemaObj, authorSchemaObj, agentSchemaObj, bookSchema, authorSchema, agentSchema, Book, Author, Agent, testBookObj, testAuthorObj, testAgentObj, testAgent, testAuthor, testBook; mongoose = require("mongoose-bird")(require("mongoose")); mongoose.connect("mongodb://test:test@localhost:27017/test"); bookSchemaObj = { author: { type: mongoose.Schema.Types.ObjectId, ref: "Author", required: true }, pubYear: { type: Number } }; authorSchemaObj = { name: { type: String, required: true }, agent: { type: mongoose.Schema.Types.ObjectId, ref: "Agent", required: true } }; agentSchemaObj = { name: { type: String, required: true } }; bookSchema = new mongoose.Schema(bookSchemaObj); authorSchema = new mongoose.Schema(authorSchemaObj); agentSchema = new mongoose.Schema(agentSchemaObj); Book = mongoose.model("Book", bookSchema); Author = mongoose.model("Author", authorSchema); Agent = mongoose.model("Agent", agentSchema); testBookObj = { pubYear: 2001 }; testAuthorObj = { name: "John P. Doe" }; testAgentObj = { name: "Alfred O. Thompson" }; testAgent = new Agent(testAgentObj); testAuthor = new Author(testAuthorObj); testBook = new Book(testBookObj); testAuthor.agent = testAgent._id; testBook.author = testAuthor._id; testAgent.saveAsync().then(function(){ return testAuthor.saveAsync(); }).then(function(){ return testBook.saveAsync(); }).then(function(){ console.log("book after saving agent, author, and book:"); console.log(JSON.stringify(testBook, undefined, 2)); console.log(""); return Author.findById(testAuthor._id).populate("agent").execAsync(); }).then(function(queriedAuthor){ console.log("author after finding and populating author"); console.log(JSON.stringify(queriedAuthor, undefined, 2)); console.log(""); return Book.findById(testBook._id).populate("author author.agent").execAsync(); }).then(function(queriedBook){ console.log("book after finding and populating book: "); console.log(JSON.stringify(queriedBook, undefined, 2)); console.log(""); return Book.findByIdAsync(testBook._id); }).then(function(foundBooks){ console.log("book after finding book:"); console.log(JSON.stringify(foundBooks, undefined, 2)); console.log(""); return foundBooks.populateAsync("author"); }).then(function(populatedBook){ console.log("book after populating book: "); console.log(JSON.stringify(populatedBook, undefined, 2)); process.exit(); })['catch'](function(err){ console.log(err); }); }).call(this); 

为LiveScript:

 mongoose = require("mongoose-bird")(require("mongoose")) mongoose.connect "mongodb://test:test@localhost:27017/test" bookSchemaObj = author: type: mongoose.Schema.Types.ObjectId ref: "Author" required: true pubYear: type: Number authorSchemaObj = name: type: String required: true agent: type: mongoose.Schema.Types.ObjectId ref: "Agent" required: true agentSchemaObj = name: type: String required: true bookSchema = new mongoose.Schema bookSchemaObj authorSchema = new mongoose.Schema authorSchemaObj agentSchema = new mongoose.Schema agentSchemaObj Book = mongoose.model "Book", bookSchema Author = mongoose.model "Author", authorSchema Agent = mongoose.model "Agent", agentSchema testBookObj = pubYear: 2001 testAuthorObj = name: "John P. Doe" testAgentObj = name: "Alfred O. Thompson" testAgent = new Agent testAgentObj testAuthor = new Author testAuthorObj testBook = new Book testBookObj testAuthor.agent = testAgent._id testBook.author = testAuthor._id testAgent.saveAsync! .then -> return testAuthor.saveAsync! .then -> return testBook.saveAsync! .then -> console.log "book after saving agent, author, and book:" console.log JSON.stringify testBook, undefined, 2 console.log "" return Author.findById(testAuthor._id).populate("agent").execAsync! .then (queriedAuthor) -> console.log "author after finding and populating author" console.log JSON.stringify queriedAuthor, undefined, 2 console.log "" return Book.findById(testBook._id).populate("author author.agent") .execAsync! .then (queriedBook) -> console.log "book after finding and populating book: " console.log JSON.stringify queriedBook, undefined, 2 console.log "" return Book.findByIdAsync testBook._id .then (foundBooks) -> console.log "book after finding book:" console.log JSON.stringify foundBooks, undefined, 2 console.log "" return foundBooks.populateAsync "author" .then (populatedBook) !-> console.log "book after populating book: " console.log JSON.stringify populatedBook, undefined, 2 process.exit! .catch (err) !-> console.log err 

输出:

 book after saving agent, author, and book: { "__v": 0, "author": "553a52d4cd8d2a4f5a5c4185", "pubYear": 2001, "_id": "553a52d4cd8d2a4f5a5c4186" } author after finding and populating author { "_id": "553a52d4cd8d2a4f5a5c4185", "agent": { "_id": "553a52d4cd8d2a4f5a5c4184", "name": "Alfred O. Thompson", "__v": 0 }, "name": "John P. Doe", "__v": 0 } book after finding and populating book: { "_id": "553a52d4cd8d2a4f5a5c4186", "author": { "_id": "553a52d4cd8d2a4f5a5c4185", "name": "John P. Doe", "__v": 0 }, "pubYear": 2001, "__v": 0 } book after finding book: { "_id": "553a52d4cd8d2a4f5a5c4186", "pubYear": 2001, "__v": 0 } book after populating book: { "_id": "553a52d4cd8d2a4f5a5c4186", "pubYear": 2001, "__v": 0 } 

通过调用Model.populate ad infinitum来填充跨多于2个集合的结构,可以实现多级深度的recursion填充。

在多级深度参考的情况下,多个填充, populate("author author.agent")不起作用。 您必须首先填充author ,然后在Agent上填充author.agent

如果您不知道要填充其ID的代理程序,请使用findById并填充作者,然后使用一个范围以外的variables来存储填充的代理程序ID,然后重新添加它,然后填充Agent.populate。

 var agentId = null; testAgent.saveAsync().then(function(){ return testAuthor.saveAsync(); }).then(function(){ return testBook.saveAsync(); }).then(function(){ return Author.findById(testAuthor._id).populate("agent").execAsync! }).then(function(populatedAuthor){ console.log("book after saving agent, author, and book:"); console.log(JSON.stringify(testBook, undefined, 2)); console.log(""); agentId = populatedAuthor.agent._id; return Book.findById(testBook._id).populate("author").execAsync(); }).then(function(partiallyPopulatedBook){ console.log("author after finding and populating author:"); console.log(JSON.stringify(partiallyPopulatedBook, undefined, 2)); console.log(""); partiallyPopulatedBook.author.agent = agentId; return Agent.populate(partiallyPopulatedBook, {path:"author.agent"}); }).then(function(populatedBook){ console.log("author after finding and populating author and autho.agent:"); console.log(JSON.stringify(populatedBook, undefined, 2)); process.exit(); })['catch'](function(err){ console.log(err); });