更新的两种方法
1替换更新:会覆盖原数据
2操作符更新:不会覆盖原数据 性能更好 原子性操作
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
参数说明:
query : update的查询条件,类似sql update查询内where后面的;
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern :可选,写安全配置。
更新选择器
新增数据拿不到ObjectID?
使用insert增加数据返回值是什么?
var insert = db.users.insert({"username":"ruolan"})
使用upsert属性,让update变成insert
db.users.update({"":""},{"username":"leilei"},{"upsert":true})
建议:
不要用objectID作为系统中检索数据的条件
update中的query加在有索引的字段
更新示例
删除字段示例
db.users.updateMany({"username":"lison"},{"$unset":{"country":"","age":""}})
更新字段名称示例
db.users.updateMany({"username":"jack"},{"$rename":{"country":"guojia","age":"nianling"}})
$each作用示例 无each会被当成一个整体插入
db.users.updateMany({ "username" : "jack"}, { "$addToSet" : { "favorites.movies" : { "$each" : [ "小电影2 " , "小电影3"]}}})
db.users.updateMany({ "username" : "jack"}, { "$addToSet" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}})
删除字符串数组中元素示例
db.users.updateMany({ "username" : "jack"}, { "$pull" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}})
db.users.updateMany({ "username" : "jack"}, { "$pullAll" : { "favorites.movies" : [ "小电影2 " , "小电影3"]}})
向对象数组中插入元素
给jack老师增加一条评论($push)
db.users.updateOne({"username":"jack"},{"$push":{"comments":{"author":"lison23","content":"ydddyyytttt"}}})
给jack老师批量新增两条评论($push,$each)
db.users.updateOne({"username":"jack"},
{"$push":{"comments":
{"$each":[{"author":"lison22","content":"yyyytttt"},
{"author":"lison23","content":"ydddyyytttt"} ] }}})
给jack老师批量新增两条评论并对数组进行排序($push,$eachm,$sort)
db.users.updateOne({"username":"jack"},
{"$push": {"comments":
{"$each":[ {"author":"lison22","content":"yyyytttt"},
{"author":"lison23","content":"ydddyyytttt"} ],
$sort: {"author":1}
}
}
})
删除对象数组中元素示
删除lison1对jack的所有评论 (批量删除)
db.users.update({"username":"jack"}, {"$pull":{"comments":{"author":"lison22"}}})
删除lison5对lison评语为“lison是苍老师的小迷弟”的评论
db.users.update({"username":"lison"}, {"$pull":{"comments":{"author":"lison5", "content":"lison是苍老师的小迷弟"}}})
更新对象数组中元素,$符号示例
db.users.updateMany({"username":"jack","comments.author":"lison1"},
{"$set":{"comments.$.content":"xxoo",
"comments.$.author":"lison10"}
})
含义:精确修改某人某一条精确的评论,如果有多个符合条件的数据,则修改最后一条数据。无法批量修改数组元素
更新的原子性
1.mongodb的更新都是原子的,mongodb所有的写操作都是有锁的。mongoDB 2.2之前锁级别为实例级别,mongoDB 2.2以后版本锁级别为数据库级别,mongoDB 3.0中,WiredTiger的锁级别是文档级别;
2.findAndModify命令:在同一往返过程中原子更新文档并返回它;
示例
常规的update的方法不能返回更新后的数据
db.num.update({"_id":ObjectId("5a5b4c285731a2a7cd01c5ae")},{"$inc":{"order":1}})
使用findandModify方法在修改数据同时返回更新前的数据或更新后的数据
db.num.findAndModify({
"query":{"_id":ObjectId("5a58cef99506c50abaeb4384")},
"update":{"$inc":{"saleOrder":1}},
"new" : true
})
3.$isolated命令:mongoDB对写锁进行了优化,对长时间的写操作会为其他的读写操作让路,使用$isolated可以避免这种让路,隔离其他操作,不允许其他操作交叉更新,不能再分片中使用;
例如:db.users.update(
{"$isolated”:true},
{"username":"lison"},
{"$pull":{"comments":{"author":"lison5","content":"lison是苍老师的小迷弟"}}
})
原生Document代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JavaUpdateObjArray {
private static final Logger logger = LoggerFactory.getLogger(JavaUpdateObjArray.class);
private MongoDatabase db;
private MongoCollection<Document> collection;
@Resource
private MongoClient client;
@Before
public void init(){
db = client.getDatabase("lison");
collection=db.getCollection("users");
}
//--------------------------------------insert demo--------------------------------------------------------------
//给jack老师增加一条评论($push)
//db.users.updateOne({"username":"jack"},
// {"$push":{"comments":{"author":"lison23","content":"ydddyyytttt"}}})
@Test
public void addOneComment(){
Document comment = new Document().append("author", "lison23")
.append("content", "ydddyyytttt");
Bson filter = eq("username","jack");
Bson update = push("comments",comment);
UpdateResult updateOne = collection.updateOne(filter, update);
System.out.println(updateOne.getModifiedCount());
}
// 给jack老师批量新增两条评论($push,$each)
// db.users.updateOne({"username":"jack"},
// {"$push":{"comments":
// {"$each":[{"author":"lison33","content":"lison33lison33"},
// {"author":"lison44","content":"lison44lison44"}]}}})
@Test
public void addManyComment(){
Document comment1 = new Document().append("author", "lison33")
.append("content", "lison33lison33");
Document comment2 = new Document().append("author", "lison44")
.append("content", "lison44lison44");
Bson filter = eq("username","jack");
Bson pushEach = pushEach("comments",Arrays.asList(comment1,comment2));
UpdateResult updateOne = collection.updateOne(filter, pushEach);
System.out.println(updateOne.getModifiedCount());
}
// 给jack老师批量新增两条评论并对数组进行排序($push,$eachm,$sort)
// db.users.updateOne({"username":"jack"},
// {"$push": {"comments":
// {"$each":[ {"author":"lison22","content":"yyyytttt"},
// {"author":"lison23","content":"ydddyyytttt"} ],
// $sort: {"author":1} } } })
@Test
public void addManySortComment(){
Document comment1 = new Document().append("author", "lison00")
.append("content", "lison00lison00");
Document comment2 = new Document().append("author", "lison01")
.append("content", "lison01lison01");
Bson filter = eq("username","jack");
Document sortDoc = new Document().append("author", 1);
PushOptions pushOption = new PushOptions().sortDocument(sortDoc);
Bson pushEach = pushEach("comments",Arrays.asList(comment1,comment2),pushOption);
UpdateResult updateOne = collection.updateOne(filter, pushEach);
System.out.println(updateOne.getModifiedCount());
}
//--------------------------------------delete demo--------------------------------------------------------------
// 删除lison1对jack的所有评论 (批量删除)
// db.users.update({"username":“jack"},
// {"$pull":{"comments":{"author":"lison23"}}})
@Test
public void deleteByAuthorComment(){
Document comment = new Document().append("author", "lison23");
Bson filter = eq("username","jack");
Bson update = pull("comments",comment);
UpdateResult updateOne = collection.updateOne(filter, update);
System.out.println(updateOne.getModifiedCount());
}
// 删除lison5对lison评语为“lison是苍老师的小迷弟”的评论(精确删除)
// db.users.update({"username":"lison"},
// {"$pull":{"comments":{"author":"lison5",
// "content":"lison是苍老师的小迷弟"}}})
@Test
public void deleteByAuthorContentComment(){
Document comment = new Document().append("author", "lison5")
.append("content", "lison是苍老师的小迷弟");
Bson filter = eq("username","lison");
Bson update = pull("comments",comment);
UpdateResult updateOne = collection.updateOne(filter, update);
System.out.println(updateOne.getModifiedCount());
}
//--------------------------------------update demo--------------------------------------------------------------
// db.users.updateMany({"username":"jack","comments.author":"lison1"},
// {"$set":{"comments.$.content":"xxoo",
// "comments.$.author":"lison10" }})
// 含义:精确修改某人某一条精确的评论,如果有多个符合条件的数据,则修改最后一条数据。无法批量修改数组元素
@Test
public void updateOneComment(){
Bson filter = and(eq("username","jack"),eq("comments.author","lison01"));
Bson updateContent = set("comments.$.content","xxoo");
Bson updateAuthor = set("comments.$.author","lison10");
Bson update = combine(updateContent,updateAuthor);
UpdateResult updateOne = collection.updateOne(filter, update);
System.out.println(updateOne.getModifiedCount());
}
//--------------------------------------findandModify demo--------------------------------------------------------------
// 使用findandModify方法在修改数据同时返回更新前的数据或更新后的数据
// db.num.findAndModify({
// "query":{"_id":ObjectId("5a58cef99506c50abaeb4384")},
// "update":{"$inc":{"saleOrder":1}},
// "new":true
// })
@Test
public void findAndModifyTest(){
Bson filter = eq("_id",new ObjectId("5a5a3a87d7598152855d758e"));
Bson update = inc("saleOrder",1);
// //实例化findAndModify的配置选项
FindOneAndUpdateOptions fauo = new FindOneAndUpdateOptions();
// //配置"new":true
fauo.returnDocument(ReturnDocument.AFTER);//
MongoCollection<Document> numCollection = db.getCollection("myOrder");
Document ret = numCollection.findOneAndUpdate(filter, update,fauo);
System.out.println(ret.toJson());
}
}
Spring实现代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringUpdateObjArray {
private static final Logger logger = LoggerFactory.getLogger(SpringUpdateObjArray.class);
@Resource
private MongoOperations tempelate;
//--------------------------------------insert demo--------------------------------------------------------------
//给jack老师增加一条评论($push)
//db.users.updateOne({"username":"jack"},
// {"$push":{"comments":{"author":"lison23","content":"ydddyyytttt"}}})
@Test
public void addOneComment(){
Query query = query(Criteria.where("username").is("jack"));
Comment comment = new Comment();
comment.setAuthor("lison23");
comment.setContent("ydddyyytttt");
Update push = new Update().push("comments", comment);
WriteResult updateFirst = tempelate.updateFirst(query, push, User.class);
System.out.println(updateFirst.getN());
}
// 给jack老师批量新增两条评论($push,$each)
// db.users.updateOne({"username":"jack"},
// {"$push":{"comments":
// {"$each":[{"author":"lison33","content":"lison33lison33"},
// {"author":"lison44","content":"lison44lison44"}]}}})
@Test
public void addManyComment(){
Query query = query(Criteria.where("username").is("jack"));
Comment comment1 = new Comment();
comment1.setAuthor("lison55");
comment1.setContent("lison55lison55");
Comment comment2 = new Comment();
comment2.setAuthor("lison66");
comment2.setContent("lison66lison66");
Update push = new Update().pushAll("comments", new Comment[]{comment1,comment2});
WriteResult updateFirst = tempelate.updateFirst(query, push, User.class);
System.out.println(updateFirst.getN());
}
// 给jack老师批量新增两条评论并对数组进行排序($push,$eachm,$sort)
// db.users.updateOne({"username":"jack"},
// {"$push": {"comments":
// {"$each":[ {"author":"lison22","content":"yyyytttt"},
// {"author":"lison23","content":"ydddyyytttt"} ],
// $sort: {"author":1} } } })
@Test
public void addManySortComment(){
Query query = query(Criteria.where("username").is("jack"));
Comment comment1 = new Comment();
comment1.setAuthor("lison77");
comment1.setContent("lison55lison55");
Comment comment2 = new Comment();
comment2.setAuthor("lison88");
comment2.setContent("lison66lison66");
Update update = new Update();
PushOperatorBuilder pob = update.push("comments");
pob.each(comment1,comment2);
pob.sort(new Sort(new Sort.Order(Direction.DESC, "author")));
System.out.println("---------------");
WriteResult updateFirst = tempelate.updateFirst(query, update,User.class);
System.out.println(updateFirst.getN());
}
//--------------------------------------delete demo--------------------------------------------------------------
// 删除lison1对jack的所有评论 (批量删除)
// db.users.update({"username":“jack"},
// {"$pull":{"comments":{"author":"lison23"}}})
@Test
public void deleteByAuthorComment(){
Query query = query(Criteria.where("username").is("jack"));
Comment comment1 = new Comment();
comment1.setAuthor("lison55");
Update pull = new Update().pull("comments",comment1);
WriteResult updateFirst = tempelate.updateFirst(query, pull, User.class);
System.out.println(updateFirst.getN());
}
// 删除lison5对lison评语为“lison是苍老师的小迷弟”的评论(精确删除)
// db.users.update({"username":"lison"},
// {"$pull":{"comments":{"author":"lison5",
// "content":"lison是苍老师的小迷弟"}}})
@Test
public void deleteByAuthorContentComment(){
Query query = query(Criteria.where("username").is("lison"));
Comment comment1 = new Comment();
comment1.setAuthor("lison5");
comment1.setContent("lison是苍老师的小迷弟");
Update pull = new Update().pull("comments",comment1);
WriteResult updateFirst = tempelate.updateFirst(query, pull, User.class);
System.out.println(updateFirst.getN());
}
//--------------------------------------update demo--------------------------------------------------------------
// db.users.updateMany({"username":"jack","comments.author":"lison1"},
// {"$set":{"comments.$.content":"xxoo",
// "comments.$.author":"lison10" }})
// 含义:精确修改某人某一条精确的评论,如果有多个符合条件的数据,则修改最后一条数据。无法批量修改数组元素
@Test
public void updateOneComment(){
Query query = query(where("username").is("lison").and("comments.author").is("lison4"));
Update update = update("comments.$.content","xxoo").set("comments.$.author","lison11");
WriteResult updateFirst = tempelate.updateFirst(query, update, User.class);
System.out.println(updateFirst.getN());
}
//--------------------------------------findandModify demo--------------------------------------------------------------
//使用findandModify方法在修改数据同时返回更新前的数据或更新后的数据
//db.num.findAndModify({
// "query":{"_id":ObjectId("5a58cef99506c50abaeb4384")},
// "update":{"$inc":{"saleOrder":1}},
// "new":true
// })
@Test
public void findAndModifyTest(){
Query query = query(where("_id").is(new ObjectId("5a5a3a87d7598152855d758e")));
Update update = new Update().inc("saleOrder", 1);
FindAndModifyOptions famo = FindAndModifyOptions.options().returnNew(true);
MyOrder ret = tempelate.findAndModify(query, update,famo, MyOrder.class);
System.out.println(ret.getSaleOrder());
}
}