Spring Data MongoDB更新

在Spring Data MongoDB中,可以使用如下方法更新文档:

  1. save - 如果_id存在则更新,否则插入。更新整个文档。
  2. updateFirst - 更新查询出的第一个文档。
  3. updateMulti - 更新查询出的所有文档。
  4. upsert - 如果没有查询出文档,则会创建一个新文档。
  5. findAndModify - 和updateMulti相同,但是它有一个额外的选项可以返回更新前或更新后的文档。

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]

1. saveOrUpdate - 例2

这是一个失败的例子,请仔细阅读,这是一个相当普遍的错误。

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

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

使用Query获取只包含name字段的文档,返回的User对象的age、ic和createDate字段都为null,如果要修改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()方法之后,age字段被正确更新了,但是ic和createdDate字段都是null,整个user对象都被更新了。为了只更新某个字段而不是整个对象,可以使用updateFirst()或者updateMulti(),而不是save()

3. updateFirst

更新符合查询条件的第一个文档。本例中,只有age字段被更新。

{
    "_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. 完整实例

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]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 简介 MongoDB 是一个基于分布式文件存储的NoSQL数据库 由C++语言编写,运行稳定,性能高 旨在为 WE...
    大熊_7d48阅读 36,785评论 1 9
  • NoSql数据库优缺点 在优势方面主要体现在下面几点: 简单的扩展 快速的读写 低廉的成本 灵活的数据模型 在不足...
    dreamer_lk阅读 2,716评论 0 6
  • 知识点:美化输出:db.stu.find().pretty() $project:修改输入文档的结构。可以用来重命...
    胖虎很可爱阅读 724评论 0 1
  • 1. MongoDB 简介 MongoDB是一个可扩展的高性能,开源,模式自由,面向文档的NoSQL,基于分布式文...
    rhlp阅读 1,112评论 0 3
  • 十、有很多人请你去制作他们的Logo。 九、你至少有一本关于椅子的书籍。 八、你知道CMYK中K代表了什么。 七、...
    GoooIce阅读 175评论 0 1