1. 概述
$push
是MongoDB中的一个更新运算符,用于在数组中添加值。相比之下,$set
运算符用于更新文档中现有字段的值。
在这篇简短教程中,我们将介绍如何在一个更新查询中同时使用 $push
和 $set
操作。
2. 数据库初始化
在进行多字段更新操作(/mongodb-update-multiple-fields)之前,我们首先需要设置一个名为 baeldung
的数据库和一个样本集合 marks
:
use baeldung;
db.createCollection(marks);
使用MongoDB的 insertMany
方法向 marks
集合中插入一些文档:
db.marks.insertMany([
{
"studentId": 1023,
"studentName":"James Broad",
"joiningYear":"2018",
"totalMarks":100,
"subjectDetails":[
{
"subjectId":123,
"subjectName":"Operating Systems Concepts",
"marks":40
},
{
"subjectId":124,
"subjectName":"Numerical Analysis",
"marks":60
}
]
},
{
"studentId": 1024,
"studentName":"Chris Overton",
"joiningYear":"2018",
"totalMarks":110,
"subjectDetails":[
{
"subjectId":123,
"subjectName":"Operating Systems Concepts",
"marks":50
},
{
"subjectId":124,
"subjectName":"Numerical Analysis",
"marks":60
}
]
}
]);
成功插入后,上述查询将返回以下响应:
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("622300cc85e943405d04b567"),
ObjectId("622300cc85e943405d04b568")
]
}
至此,我们已成功将几个示例文档插入到 marks
集合中。
3. 理解问题
为了理解问题,让我们先看看刚刚插入的文档。它包含了学生信息以及他们在不同科目中的成绩。totalMarks
是不同科目得分的总和。
假设我们希望在 subjectDetails
数组中添加一个新的科目。为了保持数据一致性,我们也需要更新 totalMarks
字段。
在MongoDB中,首先使用 $push
运算符将新科目添加到数组中,然后使用 $set
运算符设置 totalMarks
字段为特定值。
这些操作可以分别使用 $push
和 $set
运算符单独完成。但我们可以编写MongoDB查询来同时执行这两个操作。
4. 使用MongoDB命令行查询
在MongoDB中,我们可以使用不同的更新运算符来更新文档的多个字段。这里,我们将一起在 updateOne
查询中使用 $push
和 $set
运算符。
让我们查看包含两个运算符的示例查询:
db.marks.updateOne(
{
"studentId": 1023
},
{
$set: {
totalMarks: 170
},
$push: {
"subjectDetails":{
"subjectId": 126,
"subjectName": "Java Programming",
"marks": 70
}
}
}
);
在这个查询中,我们基于 studentId
过滤文档。一旦获取到过滤后的文档,我们就可以使用 $set
运算符更新 totalMarks
。此外,我们还使用 $push
运算符将新的科目数据插入到 subjectDetails
数组中。
因此,上述查询将返回以下输出:
{
"acknowledged":true,
"matchedCount":1,
"modifiedCount":1
}
在这里,matchedCount
包含匹配过滤条件的文档数量,而 modifiedCount
包含被修改的文档数量。
5. Java驱动代码
到目前为止,我们讨论了在MongoDB命令行查询中一起使用 $push
和 $set
运算符的方法。接下来,我们将学习如何使用Java驱动程序实现相同的操作。
在继续之前,我们先连接到数据库和所需的集合:
MongoClient mongoClient = new MongoClient(new MongoClientURI("localhost", 27017);
MongoDatabase database = mongoClient.getDatabase("baeldung");
MongoCollection<Document> collection = database.getCollection("marks");
这里,我们连接到本地主机默认端口27017运行的MongoDB。
现在让我们看看Java驱动程序代码:
Document subjectData = new Document()
.append("subjectId", 126)
.append("subjectName", "Java Programming")
.append("marks", 70);
UpdateResult updateQueryResult = collection.updateOne(Filters.eq("studentId", 1023),
Updates.combine(Updates.set("totalMarks", 170),
Updates.push("subjectDetails", subjectData)));
在这个代码片段中,我们使用了 updateOne
方法,根据 studentId
1023应用过滤器来更新单个文档。然后,我们使用 Updates.combine
在一次调用中执行多个操作。totalMarks
字段将被更新为170,而新的文档 subjectData
将被推送到 “subjectDetails”
数组字段中。
6. 总结
在本文中,我们理解了在一个MongoDB查询中同时应用多个操作的用例,并通过MongoDB命令行查询和Java驱动程序代码进行了实践。
如往常一样,所有示例的源代码和代码片段可在GitHub上找到。