首页 文章

使用带有Refs和Promises的嵌套Schemata保存和查找Mongoose文档

提问于
浏览
1

我有一个相当简单的问题 . 我正在尝试保存其架构包含嵌套架构引用的文档,并且该架构引用包括另一个架构引用 . 但是,当我去检索该文档时,它不包括(必需的)嵌套字段,除非我在同一查询中填充它 . 但是,即使填充查询,也不会填充第二个嵌套文档 . 我是否误解了关于在猫鼬中使用refs的方式的基本内容?

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
}

1 回答

  • 1

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

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

    如果您不知道要填充其ID的代理,findById并填充作者,则使用范围之外的范围的变量来存储填充的代理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);
    });
    

相关问题