【问题标题】:one to many with mongoose一对多与猫鼬
【发布时间】:2015-10-27 23:28:21
【问题描述】:

我想在我的 Student 模型和我的 Formation 模型之间定义一对多的关系:1 个学生属于 1 个编队,一个编队可以由 N 个学生组成。

我的需求是:

  • 能够使用其学生填充 Formation 文档
  • 轻松检索学生队形

所以我写了:

let student = new Schema({
    firstName: {
        type: String
    },
    lastName: {
        type: String
    },
    formation : {
        type: Schema.Types.ObjectId,
        ref: 'Formation'
    }
});

let formation = new Schema({
    title: {
        type: String
    },
    students: [{ type: Schema.Types.ObjectId, ref: 'Student' }]
}

当我在搜索有关与 mongodb/mongoose 的一对多关系的文档时,我很惊讶地发现,当我想创建一个学生文档(并将其添加到一个结构中)时,我不能只需将其“编队”字段设置为编队ID,并将其推送到编队文档“学生”字段。
这是否意味着当我想用另一个队形替换一个学生的队形时,我需要 1/ 更新其队形字段 2/ 从队形“学生”字段中删除自己的学生 ID 并将其重新添加到学生领域的新阵型?
这对我来说似乎有点多余。我错过了什么吗?

【问题讨论】:

    标签: mongoose one-to-many


    【解决方案1】:

    在 Formation 模型上使用 students 既不好又是多余的。潜在的无限数组是一个糟糕的设计,因为它们可能导致达到文档大小限制。关于冗余,在这种情况下您只有两个查询:

    1) 你在内存中有一个student,你想找到他们的编队:

    Formation.findOne({_id: student.formation},callback);
    

    2) 你在内存中有一个formation,并且想要查找该格式中的所有学生:

    Student.find({formation: formation._id}, callback);
    

    这两者都不需要在 Formation 架构上具有 students

    【讨论】:

    • 这行得通,但是在学生集合中搜索具有给定编队 ID 的每个学生比搜索给定编队并返回学生数组要慢得多,假设学生多于编队。跨度>
    • 如果编队被编入索引,那么您实际上只是在进行微优化与适当的设计。
    • 确实这仅与大型数据库相关。你能证明你所说的“适当的设计”吗?
    • 由于对多个文档的操作不是原子的,在两个地方更新信息有可能使您的数据不一致。因此,如果您将相同的信息存储在两个地方并且在更新过程中出现问题,那么您的数据将不匹配。您需要有间歇性运行的任务,以使您的数据“最终保持一致”。
    • 哦,我相信我们有误会。我的意思是让学生成为编队的属性,反之亦然。显然两者兼有是不好的做法。
    【解决方案2】:

    实际上是多余的,因为您定义架构的方式是多余的。学生数组应该是队形的一个属性,而不是相反。可以像普通集合一样搜索子文档。如果您将架构更改为:

    let student = new Schema({
        firstName: {
            type: String
        },
        lastName: {
            type: String
        }
    });
    
    let formation = new Schema({
        title: {
            type: String
        },
        students: [{ type: Schema.Types.ObjectId, ref: 'Student' }]
    }
    

    您应该能够使用相当短的命令来完成您的需求。假设编队和学生是您的收藏名称:

    1:生成一个学生并同时保存队形和学生文档。

    var stud = new student({name: "Sally"}); //Assuming you modeled to student
    stud.save(function (err, student) {
      formations.findOne({}, function (err, form) { //Dont know how you find formations, I assume you know
        form.students.push(stud._id);
        form.save(callback);
      }  
    });
    

    2。检索具有给定 ID 的学生的队形:

    formations.findOne({"students" : { $elemMatch: {_id: id}}}, function (err, doc) {})
    
    1. 即使是搬学生也相对简单。

      formNew.students.push (

    formOld.students.pop(formOld.students.indexOf(formOld.students.findOne( //elemMatch like above )))

    对奇怪的格式表示抱歉。

    【讨论】:

      猜你喜欢
      • 2019-02-13
      • 2021-06-22
      • 2018-01-22
      • 2018-08-23
      • 2018-06-11
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      相关资源
      最近更新 更多