一对多与猫鼬

时间:2015-10-27 13:46:47

标签: mongoose one-to-many

我想在我的学生模型和我的编队模型之间定义一对多的关系: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并将其重新添加到学生领域的新阵型?
这对我来说似乎有点多余。我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

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

1)你的内存中有一个student,你想找到它们的形成:

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

2)你的记忆中有formation,想找到那个阵型中的所有学生:

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

这两者都不需要在构造架构上使用students

答案 1 :(得分:1)

实际上它是多余的,因为您定义模式的方式是多余的。学生阵容应该是阵型的属性,但不是相反的。子文档可以像普通集合一样进行搜索。如果您将架构更改为:

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 (

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

    抱歉奇怪的格式化。