SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine(コードジン) DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Spring Dataで始めるMongoDB

Spring Dataを利用したMongoDBの操作

Spring Dataで始めるMongoDB 第2回

ドキュメントの更新

 ドキュメントの更新を行うためのメソッドは複数用意されています。複数件のupdateのように、MongoDBのメソッドでは引数としてスイッチしていた動作も、MongoTemplateではメソッドとして個々に定義されているため、その数は非常に多くなっています。

 また、更新用のメソッドの大多数は引数としてorg.springframework.data.mongodb.core.query.Update(以下、Update)を取ります。UpdateにはMongoDBで利用可能な更新用modifierに対応したメソッドが用意されています。

 ここでは更新処理における代表的なメソッドとして以下の3種類について解説を行います。

  • updateMulti
  • save
  • findAndModify

updateMulti

 これはMongoDBのupdateメソッドのオプションで、multiをtrueに指定した場合と同様になります。つまり、指定した条件にマッチする複数のドキュメントに対して更新を行います。

UpdateMultiSample.java
public class UpdateMultiSample {
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class);

        WriteResult wr = mongoTemplate.updateMulti(new Query(Criteria.where("name").is("John")), new Update().set("age", 30),Person.class);
        System.out.println(wr.getN() + "件更新しました");
    }
}

 このサンプルでは"name"フィールドの値が"John"であるドキュメントの"age"フィールドの値を30に更新しています。Criteria同様にUpdateもメソッドチェイン形式で指定が可能となっています。

 また、このメソッドの戻り値の型であるWriteResultですが、クラス名のとおり更新処理の結果などが格納されています。今回はWriteResultに用意されているgetNという更新結果の件数を取得するメソッドを利用して、実際に更新された件数を標準出力に出力しています。

save

 MongoDBのsaveメソッドと同様に、キーが一致するドキュメントが存在すれば更新、なければ新規作成を行います。

SaveSample.java
public class SaveSample {
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class);

        Person person = mongoTemplate.findOne(new Query(Criteria.where("name").is("John")), Person.class);
        
        System.out.println("----------更新前----------");
        System.out.println("id : " + person.getId());
        System.out.println("name : " + person.getName());
        System.out.println("age : " + person.getAge());
        
        person.setAge(40);
        mongoTemplate.save(person);
        
        person = mongoTemplate.findOne(new Query(Criteria.where("name").is("John")), Person.class);
        System.out.println("----------更新後 1----------");
        System.out.println("id : " + person.getId());
        System.out.println("name : " + person.getName());
        System.out.println("age : " + person.getAge());
        
        Person new_person = new Person("Scott",20);
        
        mongoTemplate.save(new_person);
        List<Person> persons = mongoTemplate.findAll(Person.class);
        System.out.println("----------更新後 2----------");
        for(Person doc : persons){
            System.out.println("id : " + doc.getId());
            System.out.println("name : " + doc.getName());
            System.out.println("age : " + doc.getAge());
        }
    }
}

 上記の例では、まず既存の一件を取得し、取得結果が格納されているpersonオブジェクトの"age"フィールドの値に40をセットし、saveメソッドの引数として指定して実行しています。

 この時点では既存のドキュメントの取得結果を元に処理を行っているため、personの"id"にはドキュメントの"_id"フィールドの値が格納されている状態です。つまり、このsaveメソッドの実行はidを指定した実行となり、実際に指定されたidを持つドキュメントが存在しているため更新が行われています。

 しかし続けて実行している処理では、新たにPersonクラスのオブジェクトを作成し、idを指定せずにsaveメソッドを実行しています。この場合、マッチするドキュメントがないため新規にドキュメントが作成されています。これは最後に実行しているfindAllの結果で確認ができます。

findAndModify

 ドキュメントの更新と取得をアトミックに行うためのオペレーションであるfindAndModifyも、Spring Data MongoDBから利用できます。

FindAndModifySample.java
public class FindAndModifySample {
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class);
        
        Person new_person = new Person("Dave",20);
        mongoTemplate.insert(new_person);
    
        Person person = mongoTemplate.findAndModify(new Query(Criteria.where("name").is("Dave")), new Update().set("age", 30),Person.class);
        
        System.out.println("id : " + person.getId());
        System.out.println("name : " + person.getName());
        System.out.println("age : " + person.getAge());
    }
}

 findAndModifyはupdateFirstやupdateMultiと似ていますが、戻り値の型がWriteResultではなくドキュメントのオブジェクトである点が異なります。上記のコードを実行した場合、標準出力には変更前の値が出力されています。

 MongoTemplateのfindAndModifyメソッドでは、FindAndModifyOptionsを引数に指定しない場合、戻り値として変更前のドキュメントが返ってきます。変更後のドキュメントを取得するようにするには、FindAndModifOptions.returnNew()を指定する必要があります。

FindAndModifySample.java(変更後)
public class FindAndModifySample {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(
                AppConfig.class);
        MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class);

        Person new_person = new Person("Dave", 20);
        mongoTemplate.insert(new_person);

        Person person = mongoTemplate.findAndModify(
                new Query(Criteria.where("name").is("Dave")),
                new Update().set("age", 50),
                new FindAndModifyOptions().returnNew(true),
                Person.class);

        System.out.println("id : " + person.getId());
        System.out.println("name : " + person.getName());
        System.out.println("age : " + person.getAge());
    }
}

次のページ
ドキュメントの削除

この記事は参考になりましたか?

Spring Dataで始めるMongoDB連載記事一覧
この記事の著者

西谷 圭介(ニシタニ ケイスケ)

TIS株式会社所属。金融系基幹システムの開発等に従事したのち、サービス企画・開発を担当。IaaS開発を経て、現在はアプリ開発者のためのPaaS「eXcale」の開発責任者兼プログラマとして活動中。Tw...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7035 2013/03/18 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー