Mongoose 猫鼬一对多

Mongoose 猫鼬一对多,mongoose,one-to-many,Mongoose,One To Many,我想在我的学生模型和我的队形模型之间定义一个一对多的关系:1个学生属于1个队形,一个队形可以由N个学生组成 我的需要是: 能够用学员填充形成文档 轻松找回学生的队形 于是我写道: let student = new Schema({ firstName: { type: String }, lastName: { type: String }, formation : { type: Schema.Typ

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

我的需要是:

  • 能够用学员填充形成文档
  • 轻松找回学生的队形
于是我写道:

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,并将其重新添加到新队形的学生字段中?

这对我来说似乎有点多余。我遗漏了什么吗?

学生
参与编队模型是一种糟糕的做法,也是多余的。潜在的无限数组是一种糟糕的设计,因为它们可能会导致达到文档大小限制。关于冗余,在这种情况下,您只有两个查询:

1) 您的内存中有一个
学生
,您希望找到他们的构成:

Formation.findOne({_id: student.formation},callback);
Student.find({formation: formation._id}, callback);
2) 您在内存中有一个
编队
,希望找到该编队中的所有学生:

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

这两种方法都不需要让学生参与形成模式。

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

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);
  }  
});
二,。检索具有给定ID的学生的队形:

formations.findOne({"students" : { $elemMatch: {_id: id}}}, function (err, doc) {})
  • 甚至移动学生也相对简单

    formNew.students.push(

  • formOld.students.pop(formOld.students.indexOf(formOld.students.findOne(
    //elemMatch如上所述
    )))


    很抱歉设置了奇怪的格式。

    这是可行的,但搜索每个学生的学生集合时使用给定的队形ID要比搜索给定的队形并返回学生数组慢得多,假设学生比队形多。如果对队形进行了索引,您实际上只是在进行微优化与正确的设计。这确实只与大型数据库相关。你能证明你所说的“正确的设计”是正确的吗?由于对多个文档的操作不是原子操作,因此在两个位置更新信息可能会导致数据不一致。因此,如果在两个位置存储相同的信息,并且在更新过程中出现中断,则数据不匹配。您需要间歇运行任务以生成数据“最终一致”。哦,我相信我们有一个误会。我的意思是,学生作为一个属性的形成,或反之亦然。显然,两者兼有是不好的做法。