From ce6a64e4a9a96e5d06548f9f30383d0625ae0e8c Mon Sep 17 00:00:00 2001 From: Mark Pollack Date: Wed, 16 Nov 2011 16:25:58 -0500 Subject: [PATCH] DATAMONGO-308 - Add support for upsert methods --- .../data/mongodb/core/MongoOperations.java | 28 +++++++++++++++++++ .../data/mongodb/core/MongoTemplate.java | 15 ++++++---- .../mongodb/core/mapping/MappingTests.java | 24 ++++++++++++++++ src/docbkx/reference/mongodb.xml | 12 ++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 189d95da9..f991b65b1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -639,6 +639,30 @@ public interface MongoOperations { */ void save(Object objectToSave, String collectionName); + /** + * Performs an upsert. If no document is found that matches the query, a new document is created and inserted + * by combining the query document and the update document. + * + * @param query the query document that specifies the criteria used to select a record to be upserted + * @param update the update document that contains the updated object or $ operators to manipulate the existing object + * @param entityClass class that determines the collection to use + * @return the WriteResult which lets you access the results of the previous write. + */ + WriteResult upsert(Query query, Update update, Class entityClass); + + + /** + * Performs an upsert. If no document is found that matches the query, a new document is created and inserted + * by combining the query document and the update document. + * + * @param query the query document that specifies the criteria used to select a record to be updated + * @param update the update document that contains the updated object or $ operators to manipulate the existing + * object. + * @param collectionName name of the collection to update the object in + * @return the WriteResult which lets you access the results of the previous write. + */ + WriteResult upsert(Query query, Update update, String collectionName); + /** * Updates the first object that is found in the collection of the entity class that matches the query document with * the provided update document. @@ -647,6 +671,7 @@ public interface MongoOperations { * @param update the update document that contains the updated object or $ operators to manipulate the existing * object. * @param entityClass class that determines the collection to use + * @return the WriteResult which lets you access the results of the previous write. */ WriteResult updateFirst(Query query, Update update, Class entityClass); @@ -658,6 +683,7 @@ public interface MongoOperations { * @param update the update document that contains the updated object or $ operators to manipulate the existing * object. * @param collectionName name of the collection to update the object in + * @return the WriteResult which lets you access the results of the previous write. */ WriteResult updateFirst(Query query, Update update, String collectionName); @@ -669,6 +695,7 @@ public interface MongoOperations { * @param update the update document that contains the updated object or $ operators to manipulate the existing * object. * @param entityClass class that determines the collection to use + * @return the WriteResult which lets you access the results of the previous write. */ WriteResult updateMulti(Query query, Update update, Class entityClass); @@ -680,6 +707,7 @@ public interface MongoOperations { * @param update the update document that contains the updated object or $ operators to manipulate the existing * object. * @param collectionName name of the collection to update the object in + * @return the WriteResult which lets you access the results of the previous write. */ WriteResult updateMulti(Query query, Update update, String collectionName); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 5c3a295c4..d23b1152c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -772,6 +772,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { }); } + + public WriteResult upsert(Query query, Update update, Class entityClass) { + return doUpdate(determineCollectionName(entityClass), query, update, entityClass, true, false); + } + + public WriteResult upsert(Query query, Update update, String collectionName) { + return doUpdate(collectionName, query, update, null, true, false); + } + public WriteResult updateFirst(Query query, Update update, Class entityClass) { return doUpdate(determineCollectionName(entityClass), query, update, entityClass, false, false); } @@ -813,11 +822,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, updateObj, queryObj); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); if (writeConcernToUse == null) { - if (multi) { - wr = collection.updateMulti(queryObj, updateObj); - } else { - wr = collection.update(queryObj, updateObj); - } + wr = collection.update(queryObj, updateObj, upsert, multi); } else { wr = collection.update(queryObj, updateObj, upsert, multi, writeConcernToUse); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java index f87c008dd..2e7bc0bda 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java @@ -353,7 +353,31 @@ public class MappingTests { Person p2 = template.findOne(query(where("ssn").is(1111)), Person.class); assertThat(p2.getAddress().getCity(), is("New Town")); } + + @Test + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void testUpsert() { + Address addr = new Address(); + addr.setLines(new String[]{"1234 W. 1st Street", "Apt. 12"}); + addr.setCity("Anytown"); + addr.setPostalCode(12345); + addr.setCountry("USA"); + Person p2 = template.findOne(query(where("ssn").is(1111)), Person.class); + assertNull(p2); + + template.upsert(query(where("ssn").is(1111).and("firstName").is("Query").and("lastName").is("Update")), update("address", addr), Person.class); + + p2 = template.findOne(query(where("ssn").is(1111)), Person.class); + assertThat(p2.getAddress().getCity(), is("Anytown")); + + template.dropCollection(Person.class); + template.upsert(query(where("ssn").is(1111).and("firstName").is("Query").and("lastName").is("Update")), update("address", addr), "person"); + p2 = template.findOne(query(where("ssn").is(1111)), Person.class); + assertThat(p2.getAddress().getCity(), is("Anytown")); + + } + @Test public void testOrQuery() { PersonWithObjectId p1 = new PersonWithObjectId(1, "first", ""); diff --git a/src/docbkx/reference/mongodb.xml b/src/docbkx/reference/mongodb.xml index 55670b419..ce3bfec87 100644 --- a/src/docbkx/reference/mongodb.xml +++ b/src/docbkx/reference/mongodb.xml @@ -1383,6 +1383,18 @@ import static org.springframework.data.mongodb.core.query.Update; +
+ Upserting documents in a collection + + Related to perfomring an updateFirst + operations, you can also perform an upsert operation which will perform + an insert if no document is found that matches the query. The document + that is inserted is a combination of the query document and the update + document. Here is an example + + template.upsert(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")), update("address", addr), Person.class); +
+
Methods for removing documents