我有一个mongodb文档,假设有模式
class: String,
class_teacher: String,
students: [
{
student: String,
marks: number
}
]
在上面的例子中,如果我将一个新学生推送到该集合,它将为每个学生生成一个_id
,我通过使用整个文档的更新查询来完成它。
这是正确的方法吗?
如果是,我如何在推送学生对象后立即获得每个学生的_id?
过了一段时间,如果我想更新单个学生的分数,最好的方法是什么?
答案 0 :(得分:2)
在不错的模式下,我会回答所有你的问题",这里有一些演示代码:
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var classSchema = new Schema({
class: String,
teacher: String,
students: [{ student: String, marks: Number }]
});
var Class = mongoose.model("Class", classSchema);
var myclass = new Class();
myclass.students.push(
{ student: "bill", marks: 10 },
{ student: "ted", marks: 5 }
);
console.log("Whole:\n %s\n",myclass);
console.log("Last added _id: %s\n",myclass.students.slice(-1)[0]._id);
myclass.save(function(err,myclass) {
if (err) throw err;
Class.findOneAndUpdate(
{ "students.student": "ted" },
{ "$set": { "students.$.marks": 7 } },
function(err,doc) {
if (err) throw err;
console.log(doc);
}
);
});
总的来说:
确定没问题,即使您可能会发现为#34; Student"定义您的架构。从长远来看,单独来说可以更容易维护:
var studenSchema = new Schema({
student: String,
marks: Number
});
var classSchema = new Schema({
class: String,
teacher: String,
students: [studentSchema]
});
当您修改此方式时,数组中最后添加的元素可以通过.slice()
拉出,然后您可以获得最后_id
值。
console.log("Last added _id: %s\n",myclass.students.slice(-1)[0]._id);
使用.findOneAndUpdate()
或类似操作最好更新标记。在这里,您查询匹配文档和数组元素,并使用positional $
运算符更新正确的元素:
Class.findOneAndUpdate(
{ "students.student": "ted" },
{ "$set": { "students.$.marks": 7 } },
function(err,doc) {
if (err) throw err;
console.log(doc);
}
);
这也会返回已修改的文档,以便您可以查看更改。对于"批量"您将使用.update()
方法以及" multi"选项。
你也可以"添加"使用$push
运算符将新学生添加到数组中,就像使用显示的方法返回文档之前一样,这样您也可以通过这种方式应用获取新的_id
值:
Class.findOneAndUpdate(
{ "students.student": "ted" },
{ "$push": { "students": { "student": "sally", "marks": 4 }} },
function(err,doc) {
if (err) throw err;
console.log("Whole:\n %s", doc);
console.log("Last added _id: %s\n",doc.students.slice(-1)[0]._id);
}
);
这会产生如下结果:
Whole:
{ _id: 53bc9844c1cbd4d24eac8db6,
__v: 0,
students:
[ { student: 'bill', marks: 10, _id: 53bc9844c1cbd4d24eac8db7 },
{ student: 'ted', marks: 7, _id: 53bc9844c1cbd4d24eac8db8 },
{ student: 'sally', marks: 4, _id: 53bca6c346d93b32624e5af4 } ] }
Last added id: 53bca6c346d93b32624e5af4
如果您需要其他模式验证功能或字段值的其他挂钩,则需要单独.find()
个文档,在代码中修改,然后.save()
。但这些是替代方法,通常会创造更少的线路流量#34;而不是处理整个文件。