让我将示例from the docs扩展为:
{
_id: 4,
tags: ['good', 'great', 'nice'],
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 90, mean: 85, std: 3 }
]
}
现在,我想更新所有grade=85
,其中还有good
标记。我会尝试使用:
db.students.update(
{ tags: "good", "grades.grade": 85 },
{ $set: { "grades.$.std" : 6 } }
)
但是,mongo会将$
设置为0
,因为标记good
是标记列表中的第一个。这会导致数据更改为:
{
_id: 4,
tags: ['good', 'great', 'nice'],
grades: [
{ grade: 80, mean: 75, std: 6 }, //←wrong
{ grade: 85, mean: 90, std: 5 },
{ grade: 90, mean: 85, std: 3 }
]
}
问题:有没有办法告诉mongo和/或猫鼬使用成绩中的职位来参考成绩?
答案 0 :(得分:4)
之所以发生这种情况是因为您在单个查询文档中使用了两个数组。但不幸的是,MongoDB不支持它。
查询文档应该只包含数组上的单个条件 正在投射的领域。多个条件可能会互相覆盖 内部并导致未定义的行为。
根据这些要求,以下查询不正确:
db.collection.find( { <array>: <value>, <someOtherArray>: <value2> }, { "<array>.$": 1 } )
您可以尝试编写类似的内容:
db.test.find({tags: "good", "grades.grade": 85 }).forEach(function(doc){ db.test.update(
{_id: doc._id, "grades.grade": 85 },
{ $set: { "grades.$.std" : 88 }},
{multi: true})})
答案 1 :(得分:0)
使用mongoose
,您应该创建两个单独的模型。一个用于Students
,另一个用于Grades
。然后,让Students
包含对Grades
的引用。
这样可以轻松更新单个Grades
。
类似的东西:
var studentSchema = mongoose.Schema({
tags: [String],
grades: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Grade'
}
});
var Student = mongoose.model('Student', studentSchema);
var gradeSchema = mongoose.Schema({
grade: Number,
mean: Number,
std: Number
});
var Grade = mongoose.model('Grade', studentSchema);
您的更新代码可能如下所示:
Student.find({tags: { $in: ['good'] }}).populate('grades', { grade: 85 }).exec(function(err, students) {
students.grades.forEach(function(grade) {
grade.update(null, { std: 6 }, function(err, numAffected) {
});
});
});