ドキュメントの更新
ドキュメントの更新を行うためのメソッドは複数用意されています。複数件のupdateのように、MongoDBのメソッドでは引数としてスイッチしていた動作も、MongoTemplateではメソッドとして個々に定義されているため、その数は非常に多くなっています。
また、更新用のメソッドの大多数は引数としてorg.springframework.data.mongodb.core.query.Update(以下、Update)を取ります。UpdateにはMongoDBで利用可能な更新用modifierに対応したメソッドが用意されています。
ここでは更新処理における代表的なメソッドとして以下の3種類について解説を行います。
- updateMulti
- save
- findAndModify
updateMulti
これはMongoDBのupdateメソッドのオプションで、multiをtrueに指定した場合と同様になります。つまり、指定した条件にマッチする複数のドキュメントに対して更新を行います。
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メソッドと同様に、キーが一致するドキュメントが存在すれば更新、なければ新規作成を行います。
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から利用できます。
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()を指定する必要があります。
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());
}
}
