Spring Data MongoDB:更新文档

在Spring data – MongoDB中,您可以使用以下方法来更新文档。

  1. 保存–更新整个对象,如果存在“ _id”,则执行更新,否则将其插入。
  2. updateFirst –更新与查询匹配的第一个文档。
  3. updateMulti –更新所有与查询匹配的文档。
  4. Upserting –如果没有与查询匹配的文档,则通过组合查询和更新对象来创建新文档。
  5. findAndModify –与updateMulti相同,但是它有一个附加选项可以返回旧的或新更新的文档。

PS所有示例均在mongo-java-driver-2.11.0.jarspring-data-mongodb-1.2.0.RELEASE.jar

1. saveOrUpdate –第1部分示例

假设下面将json数据插入到MongoDB中。

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1001", 
	"name" : "appleA", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T23:17:35.530Z") 
}

查找文档,使用save()方法进行修改和更新。

Query query = new Query();
	query.addCriteria(Criteria.where("name").is("appleA"));

	User userTest1 = mongoOperation.findOne(query, User.class);

	System.out.println("userTest1 - " + userTest1);

	//modify and update with save()
	userTest1.setAge(99);
	mongoOperation.save(userTest1);

	//get the updated object again
	User userTest1_1 = mongoOperation.findOne(query, User.class);

	System.out.println("userTest1_1 - " + userTest1_1);

输出量

userTest1 - User [id=id, ic=1001, name=appleA, age=20, createdDate=Sat Apr 06 23:17:35 MYT 2013]
userTest1_1 - User [id=id, ic=1001, name=appleA, age=99, createdDate=Sat Apr 06 23:17:35 MYT 2013]

注意
参见示例2,它显示了大多数开发人员的常见错误。

2. saveOrUpdate –第2部分示例

这是一个失败的示例,请仔细阅读,这是一个非常常见的错误。

假设下面将json数据插入到MongoDB中。

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1002", 
	"name" : "appleB", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T15:22:34.530Z") 
}

Query ,您仅使用单个“名称”字段值返回的文档,它确实经常保存对象返回的大小。 返回的“用户”对象在age,ic和createdDate字段中具有空值,如果您修改“ age”字段并对其进行更新,它将覆盖所有内容,而不是更新修改后的字段“ age”。

Query query = new Query();
		query.addCriteria(Criteria.where("name").is("appleB"));
		query.fields().include("name");

		User userTest2 = mongoOperation.findOne(query, User.class);
		System.out.println("userTest2 - " + userTest2);

		userTest2.setAge(99);

		mongoOperation.save(userTest2);

		// ooppss, you just override everything, it caused ic=null and
		// createdDate=null

		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").is("appleB"));

		User userTest2_1 = mongoOperation.findOne(query1, User.class);
		System.out.println("userTest2_1 - " + userTest2_1);

输出量

userTest2 - User [id=51603dba3004d7fffc202391, ic=null, name=appleB, age=0, createdDate=null]
userTest2_1 - User [id=51603dba3004d7fffc202391, ic=null, name=appleB, age=99, createdDate=null]

在save()之后,正确地更新了“年龄”字段,但是ic和createdDate都设置为null,整个“用户”对象也被更新。 要更新单个字段/键值,请不要使用save(),而应使用updateFirst()或updateMulti()。

3. updateFirst示例

更新与查询匹配的第一个文档。 在这种情况下,仅更新单个字段“年龄”。

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1003", 
	"name" : "appleC", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T23:22:34.530Z") 
}
//returns only 'name' field
		Query query = new Query();
		query.addCriteria(Criteria.where("name").is("appleC"));
		query.fields().include("name");

		User userTest3 = mongoOperation.findOne(query, User.class);
		System.out.println("userTest3 - " + userTest3);

		Update update = new Update();
		update.set("age", 100);

		mongoOperation.updateFirst(query, update, User.class);

		//returns everything
		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").is("appleC"));

		User userTest3_1 = mongoOperation.findOne(query1, User.class);
		System.out.println("userTest3_1 - " + userTest3_1);

输出量

userTest3 - User [id=id, ic=null, name=appleC, age=0, createdDate=null]
userTest3_1 - User [id=id, ic=1003, name=appleC, age=100, createdDate=Sat Apr 06 23:22:34 MYT 2013]

4. updateMulti示例

更新所有与查询匹配的文档。

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1004", 
	"name" : "appleD", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T15:22:34.530Z") 
}
{ 
	"_id" : ObjectId("id"), 
	"ic" : "1005", 
	"name" : "appleE", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-06T15:22:34.530Z") 
}
//show the use of $or operator
		Query query = new Query();
		query.addCriteria(Criteria
				.where("name").exists(true)
				.orOperator(Criteria.where("name").is("appleD"),
						Criteria.where("name").is("appleE")));
		Update update = new Update();
		
		//update age to 11
		update.set("age", 11);
		
		//remove the createdDate field
		update.unset("createdDate");

		// if use updateFirst, it will update 1004 only.
		// mongoOperation.updateFirst(query4, update4, User.class);

		// update all matched, both 1004 and 1005
		mongoOperation.updateMulti(query, update, User.class);

		System.out.println(query.toString());

		List<User> usersTest4 = mongoOperation.find(query4, User.class);

		for (User userTest4 : usersTest4) {
			System.out.println("userTest4 - " + userTest4);
		}

输出量

Query: { "name" : { "$exists" : true} , 
	"$or" : [ { "name" : "appleD"} , { "name" : "appleE"}]}, Fields: null, Sort: null

userTest4 - User [id=id, ic=1004, name=appleD, age=11, createdDate=null]
userTest4 - User [id=id, ic=1005, name=appleE, age=11, createdDate=null]

5. Upsert示例

如果文档匹配,则对其进行更新,否则通过组合查询和更新对象来创建新文档,其工作方式类似于findAndModifyElseCreate() 🙂

{ 
	//no data
}
//search a document that doesn't exist
		Query query = new Query();
		query.addCriteria(Criteria.where("name").is("appleZ"));

		Update update = new Update();
		update.set("age", 21);

		mongoOperation.upsert(query, update, User.class);

		User userTest5 = mongoOperation.findOne(query, User.class);
		System.out.println("userTest5 - " + userTest5);

输出,通过组合查询和更新对象来创建一个新文档。

userTest5 - User [id=id, ic=null, name=appleZ, age=21, createdDate=null]

6. findAndModify示例

通过单个操作查找和修改并获取新更新的对象。

{ 
	"_id" : ObjectId("id"), 
	"ic" : "1006", 
	"name" : "appleF", 
	"age" : 20, 
	"createdDate" : ISODate("2013-04-07T13:11:34.530Z") 
}
Query query6 = new Query();
		query6.addCriteria(Criteria.where("name").is("appleF"));
		
		Update update6 = new Update();
		update6.set("age", 101);
		update6.set("ic", 1111);
		
		//FindAndModifyOptions().returnNew(true) = newly updated document
		//FindAndModifyOptions().returnNew(false) = old document (not update yet)
		User userTest6 = mongoOperation.findAndModify(
				query6, update6, 
				new FindAndModifyOptions().returnNew(true), User.class);
		System.out.println("userTest6 - " + userTest6);

输出量

userTest6 - User [id=id, ic=1111, name=appleF, age=101, createdDate=Sun Apr 07 13:11:34 MYT 2013]

7.完整的例子

完整的应用程序将示例1到6的所有内容组合在一起。

package com.mkyong.core;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import com.mkyong.config.SpringMongoConfig;
import com.mkyong.model.User;

public class UpdateApp {

	public static void main(String[] args) {
		// For Annotation
		ApplicationContext ctx = 
			new AnnotationConfigApplicationContext(SpringMongoConfig.class);
		MongoOperations mongoOperation = 
			(MongoOperations) ctx.getBean("mongoTemplate");

		// insert 6 users for testing
		List<User> users = new ArrayList<User>();

		User user1 = new User("1001", "appleA", 20, new Date());
		User user2 = new User("1002", "appleB", 20, new Date());
		User user3 = new User("1003", "appleC", 20, new Date());
		User user4 = new User("1004", "appleD", 20, new Date());
		User user5 = new User("1005", "appleE", 20, new Date());
		User user6 = new User("1006", "appleF", 20, new Date());
		users.add(user1);
		users.add(user2);
		users.add(user3);
		users.add(user4);
		users.add(user5);
		users.add(user6);
		mongoOperation.insert(users, User.class);

		// Case 1 ... find and update
		System.out.println("Case 1");

		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").is("appleA"));

		User userTest1 = mongoOperation.findOne(query1, User.class);

		System.out.println("userTest1 - " + userTest1);

		userTest1.setAge(99);
		mongoOperation.save(userTest1);

		User userTest1_1 = mongoOperation.findOne(query1, User.class);

		System.out.println("userTest1_1 - " + userTest1_1);

		// Case 2 ... select single field only
		System.out.println("\nCase 2");

		Query query2 = new Query();
		query2.addCriteria(Criteria.where("name").is("appleB"));
		query2.fields().include("name");

		User userTest2 = mongoOperation.findOne(query2, User.class);
		System.out.println("userTest2 - " + userTest2);

		userTest2.setAge(99);

		mongoOperation.save(userTest2);

		// ooppss, you just override everything, it caused ic=null and
		// createdDate=null

		Query query2_1 = new Query();
		query2_1.addCriteria(Criteria.where("name").is("appleB"));

		User userTest2_1 = mongoOperation.findOne(query2_1, User.class);
		System.out.println("userTest2_1 - " + userTest2_1);

		System.out.println("\nCase 3");
		Query query3 = new Query();
		query3.addCriteria(Criteria.where("name").is("appleC"));
		query3.fields().include("name");

		User userTest3 = mongoOperation.findOne(query3, User.class);
		System.out.println("userTest3 - " + userTest3);

		Update update3 = new Update();
		update3.set("age", 100);

		mongoOperation.updateFirst(query3, update3, User.class);

		Query query3_1 = new Query();
		query3_1.addCriteria(Criteria.where("name").is("appleC"));

		User userTest3_1 = mongoOperation.findOne(query3_1, User.class);
		System.out.println("userTest3_1 - " + userTest3_1);

		System.out.println("\nCase 4");
		Query query4 = new Query();
		query4.addCriteria(Criteria
				.where("name")
				.exists(true)
				.orOperator(Criteria.where("name").is("appleD"),
						Criteria.where("name").is("appleE")));
		Update update4 = new Update();
		update4.set("age", 11);
		update4.unset("createdDate");

		// update 1004 only.
		// mongoOperation.updateFirst(query4, update4, User.class);

		// update all matched
		mongoOperation.updateMulti(query4, update4, User.class);

		System.out.println(query4.toString());

		List<User> usersTest4 = mongoOperation.find(query4, User.class);

		for (User userTest4 : usersTest4) {
			System.out.println("userTest4 - " + userTest4);
		}

		System.out.println("\nCase 5");
		Query query5 = new Query();
		query5.addCriteria(Criteria.where("name").is("appleZ"));

		Update update5 = new Update();
		update5.set("age", 21);

		mongoOperation.upsert(query5, update5, User.class);

		User userTest5 = mongoOperation.findOne(query5, User.class);
		System.out.println("userTest5 - " + userTest5);

		System.out.println("\nCase 6");
		Query query6 = new Query();
		query6.addCriteria(Criteria.where("name").is("appleF"));

		Update update6 = new Update();
		update6.set("age", 101);
		update6.set("ic", 1111);

		User userTest6 = mongoOperation.findAndModify(query6, update6,
				new FindAndModifyOptions().returnNew(true), User.class);
		System.out.println("userTest6 - " + userTest6);

		mongoOperation.dropCollection(User.class);

	}

}

输出量

Case 1
userTest1 - User [id=id, ic=1001, name=appleA, age=20, createdDate=Sun Apr 07 13:22:48 MYT 2013]
userTest1_1 - User [id=id, ic=1001, name=appleA, age=99, createdDate=Sun Apr 07 13:22:48 MYT 2013]

Case 2
userTest2 - User [id=id, ic=null, name=appleB, age=0, createdDate=null]
userTest2_1 - User [id=id, ic=null, name=appleB, age=99, createdDate=null]

Case 3
userTest3 - User [id=id, ic=null, name=appleC, age=0, createdDate=null]
userTest3_1 - User [id=id, ic=1003, name=appleC, age=100, createdDate=Sun Apr 07 13:22:48 MYT 2013]

Case 4
Query: { "name" : { "$exists" : true} , "$or" : [ { "name" : "appleD"} , { "name" : "appleE"}]}, Fields: null, Sort: null
userTest4 - User [id=id, ic=1004, name=appleD, age=11, createdDate=null]
userTest4 - User [id=id, ic=1005, name=appleE, age=11, createdDate=null]

Case 5
userTest5 - User [id=id, ic=null, name=appleZ, age=21, createdDate=null]

Case 6
userTest6 - User [id=id, ic=1006, name=appleF, age=20, createdDate=Sun Apr 07 13:22:48 MYT 2013]

下载源代码

下载它– SpringMongoDB-Update-Example.zip (29 KB)

参考文献

  1. MongoDB模板更新文档
  2. Spring Data MongoDB –保存,更新和删除文档
  3. Java MongoDB更新示例/
  4. MongoDB更新修饰符操作
  5. Spring Data MongoDB Hello World示例

翻译自: https://mkyong.com/mongodb/spring-data-mongodb-update-document/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值