【问题标题】:In Mongoose if my child objects have references to the parents how would I populate?在 Mongoose 中,如果我的子对象引用了父对象,我将如何填充?
【发布时间】:2016-05-27 22:43:33
【问题描述】:

我的关系示例:

classroom:{
    id: 0,
    name: "123"
}

children : {
    name: "teddy"
    id: 0,
    classroom_id: 0;
}

//goal
clasroom: {
    id: 0,
    name: "123",
    children: [{
        name: "teddy"
        id: 0,
    }]
}

我会启动哪种猫鼬查询来返回目标对象。我担心我使用 mongoDB 很像 SQL

【问题讨论】:

  • 教室和儿童是两种不同的模式吗?

标签: node.js mongodb mongoose mongoose-populate


【解决方案1】:

如果您为教室和儿童提供不同的收藏,则无法做到这一点。此外,由于教室 -> 孩子是一对多的关系,因此不建议将孩子对象嵌入到数组中的教室文档中。

您在这里唯一能做的就是在 children 集合中查询所有具有指定教室 ID 的文档。

db.children.find({classroom_id: 0}).toArray(function(err, children){
if(err) console.log(err);
   var classroom = {};
   classroom.id = 0;
   classroom.name = "123";
   classroom.children = [];
   classroom.children.push(children);
});

这将从 children 集合中找到所有教室 ID 为 0 的文档,然后将生成的文档添加到教室对象中。这就是在 Node.js 中的实现方式

【讨论】:

    【解决方案2】:

    使用 mongodb 3.2 聚合$lookup 运算符(mongodb 中的左外连接)

    db.classroom.aggregate([
        {
          $lookup : {
            'from' : 'children',
            'localField': '_id',
            'foreignField': 'classroom_id',
            'as': 'children'
          }
        }
    ]);
    

    得到结果:

    { 
        "_id" : ObjectId("56c33ed80a3fba192138e2ac"), 
        "name" : "History", 
        "children" : [
            {
                "_id" : ObjectId("56c33e6b0a3fba192138e2a8"), 
                "name" : "John", 
                "classroom_id" : ObjectId("56c33ed80a3fba192138e2ac")
            }, 
            {
                "_id" : ObjectId("56c33e820a3fba192138e2aa"), 
                "name" : "Bob", 
                "classroom_id" : ObjectId("56c33ed80a3fba192138e2ac")
            }
        ]
    }
    { 
        "_id" : ObjectId("56c33eef0a3fba192138e2ae"), 
        "name" : "English", 
        "children" : [
            {
                "_id" : ObjectId("56c33f350a3fba192138e2b0"), 
                "name" : "Tom", 
                "classroom_id" : ObjectId("56c33eef0a3fba192138e2ae")
            }
        ]
    }
    

    您也可以使用$project 运算符格式化结果

    我的收藏是:

    教室

    { 
        "_id" : ObjectId("56c33ed80a3fba192138e2ac"), 
        "name" : "History"
    }
    { 
        "_id" : ObjectId("56c33eef0a3fba192138e2ae"), 
        "name" : "English"
    }
    

    儿童

    { 
        "_id" : ObjectId("56c33e6b0a3fba192138e2a8"), 
        "name" : "John", 
        "classroom_id" : ObjectId("56c33ed80a3fba192138e2ac")
    }
    { 
        "_id" : ObjectId("56c33e820a3fba192138e2aa"), 
        "name" : "Bob", 
        "classroom_id" : ObjectId("56c33ed80a3fba192138e2ac")
    }
    { 
        "_id" : ObjectId("56c33f350a3fba192138e2b0"), 
        "name" : "Tom", 
        "classroom_id" : ObjectId("56c33eef0a3fba192138e2ae")
    }
    

    【讨论】:

      【解决方案3】:

      您可以这样做来获得一个数组,其中包含所有教室和这些教室中的孩子的列表

      result = [], i=0;
      db.classroom.find().exec(function(err, rooms) {
          rooms.forEach(function(room){
              var classroom = {id:room.id, name:room.name};
              db.children.find({classroom_id:room.id}).exec(function(err, res){
                  classroom["children"] = res;
                  result.push(classroom);
                  i++;
                  if(i == rooms.length) {
                      console.log(result);   // prints an array of objects listing all classrooms and students in them in format you wanted.
                  }
              })
          })
      })
      

      【讨论】:

      • 您可以简单地将教室 ID 映射到字符串数组并使用 $in 查询孩子,而不是使用 forEach 循环。这就是我现在的解决方案,我来这里是为了寻找更好的方法
      猜你喜欢
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多