【问题标题】:Saving and Finding Mongoose Documents with Nested Schemata with Refs and Promises使用带有 Refs 和 Promise 的嵌套模式保存和查找 Mongoose 文档
【发布时间】:2015-07-02 06:22:45
【问题描述】:

我有一个相当简单的问题。我正在尝试保存其架构包含嵌套架构引用的文档,并且该架构引用包含另一个架构引用。但是,当我去检索该文档时,它不包括(必需的)嵌套字段,除非我在同一个查询中填充它。然而,即使我填充了查询,第二个嵌套文档也没有填充。我是否误解了关于 refs 在 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
}

【问题讨论】:

    标签: javascript node.js mongodb mongoose bluebird


    【解决方案1】:

    可以通过调用Model.populate ad infinitum 来实现多层深度引用的递归填充,以填充跨越超过 2 个集合的结构。

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

    如果您不知道要填充其 ID 的代理,请 findById 并填充作者,然后使用范围超出承诺的变量来存储填充的代理 ID,然后重新添加它,然后使用 Agent 填充。填充。

    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);
    });
    

    【讨论】:

    • 任何普通的猫鼬函数都可以通过在名称后面附加Async来与promise一起使用。我进行了更改并更新了问题以显示我遇到的真正问题。
    • 你遇到了军事深度参考的问题。希望我编辑的答案对您有所帮助。
    • 这似乎非常接近,所以已经非常感谢你了。但是,当我运行它时,我得到“未定义不是函数”。我也试过Author.populate,但也没有用。
    • Model.populate 返回 Promise,因此应该在 Agent.populate 之后删除 execAsync。请用我编辑的代码再试一次。
    • 这一切都非常丑陋和丑陋,我不确定是猫鼬的错还是猫鼬鸟或蓝鸟的错,但我终于弄明白了。您的代码几乎可以正常工作,唯一的微小(并且非常hacky)更改是我需要在填充之前实际重新添加代理ID。然而,这太糟糕了,所以如果你能告诉我应该在哪里打开错误报告或查看哪个 repo 的源,那将不胜感激。我将编辑您的答案并添加适当的代码更改。
    猜你喜欢
    • 2016-03-17
    • 2021-02-21
    • 2014-03-02
    • 2018-06-30
    • 2015-07-03
    • 2015-07-31
    • 2012-02-23
    • 2018-02-02
    • 2014-01-29
    相关资源
    最近更新 更多