前面章节介绍了如何保存/插入对象到 MongoDB 中,本章节将介绍怎样去更新已经存在的文档。
Spring Data MongoDB 中,对于更新,你可以通过使用 MongoOperation.updateFirst() 来更新找到的第一个文档,或者你可以通过使用 MongoOperation.updateMulti() 方法来更新所有找到的符合查询条件的文档。
下面的例子显示了对所有储蓄账户的更新,我们通过使用 $inc 操作符在余额中添加一次性的 50 美元奖金:
import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query; import static org.springframework.data.mongodb.core.query.Update; ... WriteResult wr = mongoTemplate.updateMulti( new Query(where("accounts.accountType").is(Account.Type.SAVINGS)), new Update().inc("accounts.$.balance", 50.00), Account.class);
除了前面讨论的查询之外,我们还通过使用 Update 对象来提供更新定义,即我们的更新条件。org.springframework.data.mongodb.core.query.Update 类拥有与 MongoDB 可用的更新修改器相匹配的方法。
它的大多数方法都返回 Update 对象,以便为 API 提供一种链式调用的风格(如:new Update().inc("age", 10).set("name", "Tom"))。
updateFirst() 用更新后的文档更新第一个符合查询文档标准的文档。
updateMulti() 用更新后的文档更新所有符合查询文档条件的对象。
注意:updateFirst() 不支持排序,请使用 findAndModify() 应用排序。
你可以在 Update 类中使用一点 “语法糖”,因为它的方法是被链接在一起的。另外,你可以通过使用 public static Update update(String key, Object value) 方法和静态导入来创建一个新的 Update 实例。
Update 类包含以下方法:
Update addToSet(String key, Object value) 用来添加值到一个数组中去,如果数组中已经存在该值那么将不会有任何的操作。即使用 $addToSet 修饰符。
Update currentDate(String key) 用来设置字段的值为当前时间,值为 Date 类型或者 Timestamp 时间戳类型,默认是 Date 类型。即使用 $currentDate 修饰符,$currentDate操作符是只用在 update 操作上,不可以用在 insert 操作上。
Update currentTimestamp(String key) 使用 $currentDate 更新修饰符和 $type timeestamp 更新
Update inc(String key, Number inc) 用来对字段的值进行增加和减少指定的值,即使用 $inc 修饰符。
Update max(String key, Object max) 用来判断字段的值是否比指定的值小,如果是,则将指定的值设置给字段。即使用 $max 修饰符,取字段值和指定值两者间最大的值。
Update min(String key, Object min) 用来判断字段的值是否比指定的值大,如果是,则将指定的值设置给字段。即使用 $min 修饰符,取字段值和指定值两者间最小的值。
Update multiply(String key, Number multiplier) 用来对字段的值乘以一个数字,即使用 $mul 修饰符。
Update pop(String key, Update.Position pos) 用来从字段数组中的头部和尾部删除一个元素,即使用 $pop 修饰符。
Update pull(String key, Object value) 用来从字段数组值中删除所有指定的值,即使用 $pull 修饰符。
Update pullAll(String key, Object[] values) 用来从字段数组值中删除所有指定的值,即使用 $pullAll 修饰符。
Update push(String key, Object value) 用来向已有的数组末尾加入一个元素,要是元素不存在,就会创建一个新的元素。如果元素已存在,就会再添加一个一模一样的元素,会造成元素的重复。所以在使用的时候,要确保该元素不存在。即使用 $push 修饰符。
Update rename(String oldName, String newName) 用来对字段进行重命名,即使用 $rename 修饰符。
Update set(String key, Object value) 使用 $set 更新修改器来更新,$set 操作符将字段的值设置为指定的值,如果该字段不存在,$set 将添加一个具有指定值的新字段。
Update setOnInsert(String key, Object value) 如果 upsert 设为 true。当满足查询条件的记录存在,则不执行 $setOnInsert 中的操作,当满足条件的记录不存在则执行$setOnInsert 操作。与 $set 指令配合使用,可以作为 $set 指令的补充。当满足查询条件的记录存在,则执行 $set 操作,当满足查询条件的记录不存在,则新增一条记录。即使用 $setOnInsert 修饰符。
Update unset(String key) 用来删除指定的字段,即使用 $unset 修饰符。
一些更新修饰符,如 $push 和 $addToSet,允许嵌套其他运算符。
// { $push : { "category" : { "$each" : [ "spring" , "data" ] } } } new Update().push("category").each("spring", "data") // { $push : { "key" : { "$position" : 0 , "$each" : [ "Arya" , "Arry" , "Weasel" ] } } } new Update().push("key").atPosition(Position.FIRST).each(Arrays.asList("Arya", "Arry", "Weasel")); // { $push : { "key" : { "$slice" : 5 , "$each" : [ "Arya" , "Arry" , "Weasel" ] } } } new Update().push("key").slice(5).each(Arrays.asList("Arya", "Arry", "Weasel")); // { $addToSet : { "values" : { "$each" : [ "spring" , "data" , "mongodb" ] } } } new Update().addToSet("values").each("spring", "data", "mongodb");
(1)Student 实体代码
package com.hxstrive.springdata.mongodb.entity; import lombok.Builder; import lombok.Data; import lombok.ToString; import java.sql.Timestamp; import java.util.Date; import java.util.List; /** * 学生 * @author hxstrive.com */ @Data @Builder @ToString public class Student { /** ID,自动映射到 MongoDB 的 _id 字段 */ private String id; /** 姓名 */ private String name; /** 年龄 */ private int age; /** 学号 */ private int studentId; /** 成绩 */ private float score; /** 排名 */ private int ranking; /** 兴趣爱好 */ private List<String> interestList; /** 入学日期 */ private Date startSchoolDate; private Timestamp timestamp; }
(2)客户端代码
package com.hxstrive.springdata.mongodb; import com.hxstrive.springdata.mongodb.entity.Person; import com.hxstrive.springdata.mongodb.entity.Student; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Update; import java.util.Collections; import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; @SpringBootTest public class UpdateTest2 { @Autowired private MongoTemplate mongoTemplate; @BeforeEach public void init() { // 删除集合 mongoTemplate.dropCollection(Person.class); Student s = Student.builder().id("ID10000").name("Tom").age(34) .studentId(1000).score(634.5f).ranking(10) .interestList(Collections.singletonList("basketball")) .build(); // 将对象插入到数据库中 mongoTemplate.save(s); System.out.println("Save: " + s); } @Test public void set() { // 将 id 为 ID10000 的学生的名字和成绩分别修改为 Helen 和 610 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().set("name", "Helen").set("score", 610), Student.class); } @Test public void addToSet() { // 向 id 为 ID10000 的学生的兴趣中添加 “football” mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().addToSet("interestList", "football"), Student.class); } @Test public void currentDate() { // 将 id 为 ID10000 的学生的入学时间设置为当前日期 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().currentDate("startSchoolDate"), Student.class); } @Test public void inc() { // 将 id 为 ID10000 的学生的成绩添加 5.5 分 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().inc("score", 5.5), Student.class); } @Test public void max() { // 如果 id 为 ID10000 的学生的成绩小于 650,则将 650 设置为他的新成绩 // 即 score = max(634.5, 650) mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().max("score", 650), Student.class); } @Test public void min() { // 如果 id 为 ID10000 的学生的成绩大于 600,则将 600 设置为他的新成绩 // 即 score = min(634.5, 600) mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().min("score", 600), Student.class); } @Test public void multiply() { // 将 id 为 ID10000 的学生成绩乘以 2 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().multiply("score", 2), Student.class); } @Test public void rename() { // rename() // 将 id 为 ID10000 的学生的 score 字段名称改为 new-score mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().rename("score", "new-score"), Student.class); } @Test public void unset() { // 将 id 为 ID10000 的学生的 score 字段删除 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().unset("score"), Student.class); } @Test public void push() { // 向 id 为 ID10000 的学生的兴趣中添加 football,football mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); } @Test public void popFirst() { // 向 id 为 ID10000 的学生的兴趣中添加 football mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); // 从 id 为 ID10000 的学生的兴趣的头部删除一个元素 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().pop("interestList", Update.Position.FIRST), Student.class); } @Test public void popLast() { // 向 id 为 ID10000 的学生的兴趣中添加 football mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); // 从 id 为 ID10000 的学生的兴趣的尾部删除一个元素 mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().pop("interestList", Update.Position.LAST), Student.class); } @Test public void pull() { // 向 id 为 ID10000 的学生的兴趣中添加 football,football mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); // 删除 id 为 ID10000 的学生的兴趣中所有 “football” mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().pull("interestList", "football"), Student.class); } @Test public void pullAll() { // 向 id 为 ID10000 的学生的兴趣中添加 football,football mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().push("interestList", "football"), Student.class); // 从 id 为 ID10000 的学生的兴趣中删除所有的 “basketball” 和 “football” mongoTemplate.updateMulti(query(where("id").is("ID10000")), new Update().pullAll("interestList", new Object[]{"basketball", "football"}), Student.class); } @Test public void setOnInsert() { // 由于 id 为 ID10000 的学生已经存在,不修改 score 为 590 mongoTemplate.upsert(query(where("id").is("ID10000")), new Update().setOnInsert("score", 590), Student.class); // 由于 id 为 ID20000 的学生已经不存在,新增一条记录,score 为 590 mongoTemplate.upsert(query(where("id").is("ID20000")), new Update().setOnInsert("score", 590), Student.class); } }