diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java index ea7ef1966..efd8d0568 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableUpdateOperation.java @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core; import java.util.Optional; +import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.UpdateDefinition; @@ -157,22 +158,12 @@ public interface ExecutableUpdateOperation { * @param update must not be {@literal null}. * @return new instance of {@link TerminatingUpdate}. * @throws IllegalArgumentException if update is {@literal null}. + * @since 2.3 + * @see Update + * @see AggregationUpdate */ TerminatingUpdate apply(UpdateDefinition update); - /** - * Set the {@link Update} to be applied. - * - * @param update must not be {@literal null}. - * @return new instance of {@link TerminatingUpdate}. - * @throws IllegalArgumentException if update is {@literal null}. - * @deprecated since 2.3 in favor of {@link #apply(UpdateDefinition)}. - */ - @Deprecated - default TerminatingUpdate apply(Update update) { - return apply((UpdateDefinition) update); - } - /** * Specify {@code replacement} object. * 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 c1d2d7c6a..ccc06584f 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 @@ -27,6 +27,7 @@ import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; import org.springframework.data.mongodb.core.aggregation.AggregationResults; +import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -654,7 +655,7 @@ public interface MongoOperations extends FluentMongoOperations { * {@code $geoNear} aggregation command to emulate {@code geoNear} command functionality. We recommend using * aggregations directly: *

- * + * *
 	 * TypedAggregation<T> geoNear = TypedAggregation.newAggregation(entityClass, Aggregation.geoNear(near, "dis"))
 	 * 		.withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
@@ -679,7 +680,7 @@ public interface MongoOperations extends FluentMongoOperations {
 	 * {@code $geoNear} aggregation command to emulate {@code geoNear} command functionality. We recommend using
 	 * aggregations directly:
 	 * 

- * + * *
 	 * TypedAggregation<T> geoNear = TypedAggregation.newAggregation(entityClass, Aggregation.geoNear(near, "dis"))
 	 * 		.withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
@@ -888,27 +889,12 @@ public interface MongoOperations extends FluentMongoOperations {
 	 * @param entityClass the parametrized type. Must not be {@literal null}.
 	 * @return the converted object that was updated before it was updated or {@literal null}, if not found.
 	 * @since 2.3
+	 * @see Update
+	 * @see AggregationUpdate
 	 */
 	@Nullable
 	 T findAndModify(Query query, UpdateDefinition update, Class entityClass);
 
-	/**
-	 * Triggers findAndModify 
-	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
-	 *
-	 * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
-	 *          fields specification. Must not be {@literal null}.
-	 * @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
-	 * @param entityClass the parametrized type. Must not be {@literal null}.
-	 * @return the converted object that was updated before it was updated or {@literal null}, if not found.
-	 * @deprecated since 2.3 in favor of {@link #findAndModify(Query, UpdateDefinition, Class)}.
-	 */
-	@Deprecated
-	@Nullable
-	default  T findAndModify(Query query, Update update, Class entityClass) {
-		return findAndModify(query, (UpdateDefinition) update, entityClass);
-	}
-
 	/**
 	 * Triggers findAndModify 
 	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
@@ -920,28 +906,12 @@ public interface MongoOperations extends FluentMongoOperations {
 	 * @param collectionName the collection to query. Must not be {@literal null}.
 	 * @return the converted object that was updated before it was updated or {@literal null}, if not found.
 	 * @since 2.3
+	 * @see Update
+	 * @see AggregationUpdate
 	 */
 	@Nullable
 	 T findAndModify(Query query, UpdateDefinition update, Class entityClass, String collectionName);
 
-	/**
-	 * Triggers findAndModify 
-	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}.
-	 *
-	 * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
-	 *          fields specification. Must not be {@literal null}.
-	 * @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
-	 * @param entityClass the parametrized type. Must not be {@literal null}.
-	 * @param collectionName the collection to query. Must not be {@literal null}.
-	 * @return the converted object that was updated before it was updated or {@literal null}, if not found.
-	 * @deprecated since 2.3 in favor of {@link #findAndModify(Query, UpdateDefinition, Class, String)}.
-	 */
-	@Deprecated
-	@Nullable
-	default  T findAndModify(Query query, Update update, Class entityClass, String collectionName) {
-		return findAndModify(query, (UpdateDefinition) update, entityClass, collectionName);
-	}
-
 	/**
 	 * Triggers findAndModify 
 	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
@@ -956,31 +926,12 @@ public interface MongoOperations extends FluentMongoOperations {
 	 *         {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as
 	 *         it is after the update.
 	 * @since 2.3
+	 * @see Update
+	 * @see AggregationUpdate
 	 */
 	@Nullable
 	 T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class entityClass);
 
-	/**
-	 * Triggers findAndModify 
-	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
-	 * {@link FindAndModifyOptions} into account.
-	 *
-	 * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
-	 *          fields specification.
-	 * @param update the {@link Update} to apply on matching documents.
-	 * @param options the {@link FindAndModifyOptions} holding additional information.
-	 * @param entityClass the parametrized type.
-	 * @return the converted object that was updated or {@literal null}, if not found. Depending on the value of
-	 *         {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as
-	 *         it is after the update.
-	 * @deprecated since 2.3 in favor of {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class)}
-	 */
-	@Nullable
-	@Deprecated
-	default  T findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass) {
-		return findAndModify(query, (UpdateDefinition) update, options, entityClass);
-	}
-
 	/**
 	 * Triggers findAndModify 
 	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
@@ -996,35 +947,13 @@ public interface MongoOperations extends FluentMongoOperations {
 	 *         {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as
 	 *         it is after the update.
 	 * @since 2.3
+	 * @see Update
+	 * @see AggregationUpdate
 	 */
 	@Nullable
 	 T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class entityClass,
 			String collectionName);
 
-	/**
-	 * Triggers findAndModify 
-	 * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking
-	 * {@link FindAndModifyOptions} into account.
-	 *
-	 * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
-	 *          fields specification. Must not be {@literal null}.
-	 * @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
-	 * @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
-	 * @param entityClass the parametrized type. Must not be {@literal null}.
-	 * @param collectionName the collection to query. Must not be {@literal null}.
-	 * @return the converted object that was updated or {@literal null}, if not found. Depending on the value of
-	 *         {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as
-	 *         it is after the update.
-	 * @deprecated since 2.3 in favor of
-	 *             {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class, String)}.
-	 */
-	@Deprecated
-	@Nullable
-	default  T findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass,
-			String collectionName) {
-		return findAndModify(query, (UpdateDefinition) update, options, entityClass, collectionName);
-	}
-
 	/**
 	 * Triggers
 	 * findOneAndReplace
@@ -1371,313 +1300,165 @@ public interface MongoOperations extends FluentMongoOperations {
 	 * 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. 
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing object. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult upsert(Query query, UpdateDefinition 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 upserted. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. - * @param entityClass class that determines the collection to use. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #upsert(Query, UpdateDefinition, Class)} - */ - @Deprecated - default UpdateResult upsert(Query query, Update update, Class entityClass) { - return upsert(query, (UpdateDefinition) update, 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.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support. - *
+ * domain type information. Use {@link #upsert(Query, UpdateDefinition, Class, String)} to get full type specific + * support.
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing object. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult upsert(Query query, UpdateDefinition update, 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.
- * NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support. - * - * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #upsert(Query, UpdateDefinition, String)} - */ - @Deprecated - default UpdateResult upsert(Query query, Update update, String collectionName) { - return upsert(query, (UpdateDefinition) update, 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. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing object. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult upsert(Query query, UpdateDefinition update, Class entityClass, 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.
- * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead. - * - * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #upsert(Query, UpdateDefinition, Class, String)} - */ - @Deprecated - default UpdateResult upsert(Query query, Update update, Class entityClass, String collectionName) { - return upsert(query, (UpdateDefinition) update, entityClass, 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. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class that determines the collection to use. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult updateFirst(Query query, UpdateDefinition update, Class entityClass); - /** - * Updates the first object that is found in the collection of the entity class that matches the query document with - * the provided update document.
- * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class)} instead. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class that determines the collection to use. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateFirst(Query, UpdateDefinition, Class)}. - */ - @Deprecated - default UpdateResult updateFirst(Query query, Update update, Class entityClass) { - return updateFirst(query, (UpdateDefinition) update, entityClass); - } - /** * Updates the first object that is found in the specified collection that matches the query document criteria with * the provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support. + * domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific + * support. *
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult updateFirst(Query query, UpdateDefinition update, String collectionName); /** * Updates the first object that is found in the specified collection that matches the query document criteria with * the provided updated document.
- * NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateFirst(Query, UpdateDefinition, String)}. - */ - @Deprecated - default UpdateResult updateFirst(Query query, Update update, String collectionName) { - return updateFirst(query, (UpdateDefinition) update, collectionName); - } - - /** - * Updates the first object that is found in the specified collection that matches the query document criteria with - * the provided updated document.
- * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult updateFirst(Query query, UpdateDefinition update, Class entityClass, String collectionName); - /** - * Updates the first object that is found in the specified collection that matches the query document criteria with - * the provided updated document.
- * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateFirst(Query, UpdateDefinition, Class, String)}. - */ - @Deprecated - default UpdateResult updateFirst(Query query, Update update, Class entityClass, String collectionName) { - return updateFirst(query, (UpdateDefinition) update, entityClass, collectionName); - } - /** * Updates all objects that are found in the collection for the entity class that matches the query document criteria * with the provided updated document. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult updateMulti(Query query, UpdateDefinition update, Class entityClass); - /** - * Updates all objects that are found in the collection for the entity class that matches the query document criteria - * with the provided updated document. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateMulti(Query, UpdateDefinition, Class)}. - */ - @Deprecated - default UpdateResult updateMulti(Query query, Update update, Class entityClass) { - return updateMulti(query, (UpdateDefinition) update, entityClass); - } - /** * Updates all objects that are found in the specified collection that matches the query document criteria with the * provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support. + * domain type information. Use {@link #updateMulti(Query, UpdateDefinition, Class, String)} to get full type specific + * support. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult updateMulti(Query query, UpdateDefinition update, String collectionName); - /** - * Updates all objects that are found in the specified collection that matches the query document criteria with the - * provided updated document.
- * NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateMulti(Query, UpdateDefinition, String)}. - */ - @Deprecated - default UpdateResult updateMulti(Query query, Update update, String collectionName) { - return updateMulti(query, (UpdateDefinition) update, collectionName); - } - /** * Updates all objects that are found in the collection for the entity class that matches the query document criteria * with the provided updated document. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ UpdateResult updateMulti(Query query, UpdateDefinition update, Class entityClass, String collectionName); - /** - * Updates all objects that are found in the collection for the entity class that matches the query document criteria - * with the provided updated document. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateMulti(Query, UpdateDefinition, Class, String)}. - */ - @Deprecated - default UpdateResult updateMulti(Query query, Update update, Class entityClass, String collectionName) { - return updateMulti(query, (UpdateDefinition) update, entityClass, collectionName); - } - /** * Remove the given object from the collection by {@literal id} and (if applicable) its * {@link org.springframework.data.annotation.Version}.
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 a2f2a804e..819426236 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 @@ -437,7 +437,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @SuppressWarnings("ConstantConditions") - protected CloseableIterator doStream(Query query, final Class entityType, String collectionName, + protected CloseableIterator doStream(Query query, Class entityType, String collectionName, Class returnType) { Assert.notNull(query, "Query must not be null!"); @@ -471,7 +471,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, */ @Override @SuppressWarnings("ConstantConditions") - public Document executeCommand(final String jsonCommand) { + public Document executeCommand(String jsonCommand) { Assert.hasText(jsonCommand, "JsonCommand must not be null nor empty!"); @@ -484,7 +484,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, */ @Override @SuppressWarnings("ConstantConditions") - public Document executeCommand(final Document command) { + public Document executeCommand(Document command) { Assert.notNull(command, "Command must not be null!"); @@ -655,7 +655,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * (non-Javadoc) * @see org.springframework.data.mongodb.core.MongoOperations#createCollection(java.lang.String) */ - public MongoCollection createCollection(final String collectionName) { + public MongoCollection createCollection(String collectionName) { Assert.notNull(collectionName, "CollectionName must not be null!"); @@ -666,8 +666,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * (non-Javadoc) * @see org.springframework.data.mongodb.core.MongoOperations#createCollection(java.lang.String, org.springframework.data.mongodb.core.CollectionOptions) */ - public MongoCollection createCollection(final String collectionName, - final @Nullable CollectionOptions collectionOptions) { + public MongoCollection createCollection(String collectionName, + @Nullable CollectionOptions collectionOptions) { Assert.notNull(collectionName, "CollectionName must not be null!"); return doCreateCollection(collectionName, convertToDocument(collectionOptions)); @@ -678,7 +678,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * @see org.springframework.data.mongodb.core.MongoOperations#getCollection(java.lang.String) */ @SuppressWarnings("ConstantConditions") - public MongoCollection getCollection(final String collectionName) { + public MongoCollection getCollection(String collectionName) { Assert.notNull(collectionName, "CollectionName must not be null!"); @@ -698,7 +698,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, * @see org.springframework.data.mongodb.core.ExecutableInsertOperation#getCollection(java.lang.String) */ @SuppressWarnings("ConstantConditions") - public boolean collectionExists(final String collectionName) { + public boolean collectionExists(String collectionName) { Assert.notNull(collectionName, "CollectionName must not be null!"); @@ -729,15 +729,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, Assert.notNull(collectionName, "CollectionName must not be null!"); - execute(collectionName, new CollectionCallback() { - public Void doInCollection(MongoCollection collection) throws MongoException, DataAccessException { - collection.drop(); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Dropped collection [{}]", - collection.getNamespace() != null ? collection.getNamespace().getCollectionName() : collectionName); - } - return null; + execute(collectionName, (CollectionCallback) collection -> { + collection.drop(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Dropped collection [{}]", + collection.getNamespace() != null ? collection.getNamespace().getCollectionName() : collectionName); } + return null; }); } @@ -1154,7 +1152,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @Override - public long count(final Query query, String collectionName) { + public long count(Query query, String collectionName) { return count(query, null, collectionName); } @@ -1484,7 +1482,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @SuppressWarnings("ConstantConditions") - protected Object insertDocument(final String collectionName, final Document document, final Class entityClass) { + protected Object insertDocument(String collectionName, Document document, Class entityClass) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Inserting Document containing fields: {} in collection: {}", document.keySet(), collectionName); @@ -1505,7 +1503,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, }); } - protected List insertDocumentList(final String collectionName, final List documents) { + protected List insertDocumentList(String collectionName, List documents) { if (documents.isEmpty()) { return Collections.emptyList(); @@ -1533,34 +1531,32 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, return MappedDocument.toIds(documents); } - protected Object saveDocument(final String collectionName, final Document dbDoc, final Class entityClass) { + protected Object saveDocument(String collectionName, Document dbDoc, Class entityClass) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Saving Document containing fields: {}", dbDoc.keySet()); } - return execute(collectionName, new CollectionCallback() { - public Object doInCollection(MongoCollection collection) throws MongoException, DataAccessException { - MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass, - dbDoc, null); - WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); + return execute(collectionName, collection -> { + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass, + dbDoc, null); + WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); - MappedDocument mapped = MappedDocument.of(dbDoc); + MappedDocument mapped = MappedDocument.of(dbDoc); - if (!mapped.hasId()) { - if (writeConcernToUse == null) { - collection.insertOne(dbDoc); - } else { - collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc); - } - } else if (writeConcernToUse == null) { - collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true)); + if (!mapped.hasId()) { + if (writeConcernToUse == null) { + collection.insertOne(dbDoc); } else { - collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc, - new ReplaceOptions().upsert(true)); + collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc); } - return mapped.getId(); + } else if (writeConcernToUse == null) { + collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true)); + } else { + collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc, + new ReplaceOptions().upsert(true)); } + return mapped.getId(); }); } @@ -1588,7 +1584,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @Override - public UpdateResult updateFirst(final Query query, final UpdateDefinition update, final String collectionName) { + public UpdateResult updateFirst(Query query, UpdateDefinition update, String collectionName) { return doUpdate(collectionName, query, update, null, false, false); } @@ -1606,13 +1602,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @Override - public UpdateResult updateMulti(final Query query, final UpdateDefinition update, String collectionName) { + public UpdateResult updateMulti(Query query, UpdateDefinition update, String collectionName) { return doUpdate(collectionName, query, update, null, false, true); } @Override - public UpdateResult updateMulti(final Query query, final UpdateDefinition update, Class entityClass, - String collectionName) { + public UpdateResult updateMulti(Query query, UpdateDefinition update, Class entityClass, String collectionName) { Assert.notNull(entityClass, "EntityClass must not be null!"); @@ -1620,8 +1615,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @SuppressWarnings("ConstantConditions") - protected UpdateResult doUpdate(final String collectionName, final Query query, final UpdateDefinition update, - @Nullable final Class entityClass, final boolean upsert, final boolean multi) { + protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefinition update, + @Nullable Class entityClass, boolean upsert, boolean multi) { Assert.notNull(collectionName, "CollectionName must not be null!"); Assert.notNull(query, "Query must not be null!"); @@ -1659,22 +1654,23 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, ? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper) : Aggregation.DEFAULT_CONTEXT; - AggregationUpdate aUppdate = ((AggregationUpdate) update); - List pipeline = new AggregationUtil(queryMapper, mappingContext).createPipeline(aUppdate, context); + List pipeline = new AggregationUtil(queryMapper, mappingContext) + .createPipeline((AggregationUpdate) update, context); return execute(collectionName, collection -> { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Calling update using query: {} and update: {} in collection: {}", + serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName); + } + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, update.getUpdateObject(), queryObj); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection; - if (multi) { - return collection.updateMany(queryObj, pipeline, opts); - } - - return collection.updateOne(queryObj, pipeline, opts); + return multi ? collection.updateMany(queryObj, pipeline, opts) : collection.updateOne(queryObj, pipeline, opts); }); } @@ -1707,11 +1703,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, return collection.replaceOne(queryObj, updateObj, replaceOptions); } else { - if (multi) { - return collection.updateMany(queryObj, updateObj, opts); - } else { - return collection.updateOne(queryObj, updateObj, opts); - } + return multi ? collection.updateMany(queryObj, updateObj, opts) + : collection.updateOne(queryObj, updateObj, opts); } }); } @@ -1764,14 +1757,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } @SuppressWarnings("ConstantConditions") - protected DeleteResult doRemove(final String collectionName, final Query query, - @Nullable final Class entityClass, boolean multi) { + protected DeleteResult doRemove(String collectionName, Query query, @Nullable Class entityClass, + boolean multi) { Assert.notNull(query, "Query must not be null!"); Assert.hasText(collectionName, "Collection name must not be null or empty!"); - final MongoPersistentEntity entity = getPersistentEntity(entityClass); - final Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), entity); + MongoPersistentEntity entity = getPersistentEntity(entityClass); + Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), entity); return execute(collectionName, collection -> { @@ -2693,7 +2686,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, Document mappedQuery = queryMapper.getMappedObject(query, entity); - Object mappedUpdate = new Document(); + Object mappedUpdate; if (update instanceof AggregationUpdate) { AggregationOperationContext context = entityClass != null @@ -3114,7 +3107,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, } else if (update instanceof List) { return collection.findOneAndUpdate(query, (List) update, opts); } - throw new IllegalArgumentException("doh - that does not work"); + + throw new IllegalArgumentException(String.format("Using %s is not supported in findOneAndUpdate", update)); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 93bde21ee..c3d230b7b 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -29,6 +29,7 @@ import org.springframework.data.geo.GeoResult; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationOptions; +import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -683,25 +684,11 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param entityClass the parametrized type. Must not be {@literal null}. * @return the converted object that was updated before it was updated. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono findAndModify(Query query, UpdateDefinition update, Class entityClass); - /** - * Triggers findAndModify - * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. - * - * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional - * fields specification. Must not be {@literal null}. - * @param update the {@link Update} to apply on matching documents. Must not be {@literal null}. - * @param entityClass the parametrized type. Must not be {@literal null}. - * @return the converted object that was updated before it was updated. - * @deprecated since 2.3 in favor of {@link #findAndModify(Query, UpdateDefinition, Class)}. - */ - @Deprecated - default Mono findAndModify(Query query, Update update, Class entityClass) { - return findAndModify(query, (UpdateDefinition) update, entityClass); - } - /** * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. @@ -713,26 +700,11 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @param collectionName the collection to query. Must not be {@literal null}. * @return the converted object that was updated before it was updated. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono findAndModify(Query query, UpdateDefinition update, Class entityClass, String collectionName); - /** - * Triggers findAndModify - * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query}. - * - * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional - * fields specification. Must not be {@literal null}. - * @param update the {@link Update} to apply on matching documents. Must not be {@literal null}. - * @param entityClass the parametrized type. Must not be {@literal null}. - * @param collectionName the collection to query. Must not be {@literal null}. - * @return the converted object that was updated before it was updated. - * @deprecated since 2.3 in favor of {@link #findAndModify(Query, UpdateDefinition, Class, String)}. - */ - @Deprecated - default Mono findAndModify(Query query, Update update, Class entityClass, String collectionName) { - return findAndModify(query, (UpdateDefinition) update, entityClass, collectionName); - } - /** * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking @@ -746,28 +718,11 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()} * this will either be the object as it was before the update or as it is after the update. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class entityClass); - /** - * Triggers findAndModify - * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking - * {@link FindAndModifyOptions} into account. - * - * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional - * fields specification. - * @param update the {@link Update} to apply on matching documents. - * @param options the {@link FindAndModifyOptions} holding additional information. - * @param entityClass the parametrized type. - * @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()} - * this will either be the object as it was before the update or as it is after the update. - * @deprecated since 2.3 in favor of {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class)}. - */ - @Deprecated - default Mono findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass) { - return findAndModify(query, (UpdateDefinition) update, options, entityClass); - } - /** * Triggers findAndModify * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking @@ -782,32 +737,12 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()} * this will either be the object as it was before the update or as it is after the update. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class entityClass, String collectionName); - /** - * Triggers findAndModify - * to apply provided {@link Update} on documents matching {@link Criteria} of given {@link Query} taking - * {@link FindAndModifyOptions} into account. - * - * @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional - * fields specification. Must not be {@literal null}. - * @param update the {@link Update} to apply on matching documents. Must not be {@literal null}. - * @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}. - * @param entityClass the parametrized type. Must not be {@literal null}. - * @param collectionName the collection to query. Must not be {@literal null}. - * @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()} - * this will either be the object as it was before the update or as it is after the update. - * @deprecated since 2.3 in favor of - * {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class, String)}. - */ - @Deprecated - default Mono findAndModify(Query query, Update update, FindAndModifyOptions options, Class entityClass, - String collectionName) { - return findAndModify(query, (UpdateDefinition) update, options, entityClass, collectionName); - } - /** * Triggers * findOneAndReplace @@ -1228,313 +1163,164 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * 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.
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, Class)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing object. Must not be {@literal null}. * @param entityClass class that determines the collection to use. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono upsert(Query query, UpdateDefinition 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 upserted. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. - * @param entityClass class that determines the collection to use. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #upsert(Query, UpdateDefinition, Class)}. - */ - @Deprecated - default Mono upsert(Query query, Update update, Class entityClass) { - return upsert(query, (UpdateDefinition) update, 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.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support. + * domain type information. Use {@link #upsert(Query, UpdateDefinition, Class, String)} to get full type specific + * support. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing object. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono upsert(Query query, UpdateDefinition update, 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.
- * NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support. - *
- * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. - * - * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #upsert(Query, UpdateDefinition, String)}. - */ - @Deprecated - default Mono upsert(Query query, Update update, String collectionName) { - return upsert(query, (UpdateDefinition) update, 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. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing object. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono upsert(Query query, UpdateDefinition update, Class entityClass, 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.
- * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. - * - * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing - * object. Must not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #upsert(Query, UpdateDefinition, Class, String)}. - */ - @Deprecated - default Mono upsert(Query query, Update update, Class entityClass, String collectionName) { - return upsert(query, (UpdateDefinition) update, entityClass, 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.
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class)} instead. + * Use {@link #findAndModify(Query, UpdateDefinition, Class)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class that determines the collection to use. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono updateFirst(Query query, UpdateDefinition update, Class entityClass); - /** - * Updates the first object that is found in the collection of the entity class that matches the query document with - * the provided update document. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class that determines the collection to use. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateFirst(Query, UpdateDefinition, Class)}. - */ - @Deprecated - default Mono updateFirst(Query query, Update update, Class entityClass) { - return updateFirst(query, (UpdateDefinition) update, entityClass); - } - /** * Updates the first object that is found in the specified collection that matches the query document criteria with * the provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support. - *
+ * domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific + * support.
* NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono updateFirst(Query query, UpdateDefinition update, String collectionName); /** * Updates the first object that is found in the specified collection that matches the query document criteria with * the provided updated document.
- * NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateFirst(Query, UpdateDefinition, String)}. - */ - @Deprecated - default Mono updateFirst(Query query, Update update, String collectionName) { - return updateFirst(query, (UpdateDefinition) update, collectionName); - } - - /** - * Updates the first object that is found in the specified collection that matches the query document criteria with - * the provided updated document.
- * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. - * Use {@link #findAndModify(Query, Update, Class, String)} instead. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono updateFirst(Query query, UpdateDefinition update, Class entityClass, String collectionName); - /** - * Updates the first object that is found in the specified collection that matches the query document criteria with - * the provided updated document.
- * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateFirst(Query, UpdateDefinition, Class, String)}. - */ - @Deprecated - default Mono updateFirst(Query query, Update update, Class entityClass, String collectionName) { - return updateFirst(query, (UpdateDefinition) update, entityClass, collectionName); - } - /** * Updates all objects that are found in the collection for the entity class that matches the query document criteria * with the provided updated document. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono updateMulti(Query query, UpdateDefinition update, Class entityClass); - /** - * Updates all objects that are found in the collection for the entity class that matches the query document criteria - * with the provided updated document. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateMulti(Query, UpdateDefinition, Class)}. - */ - @Deprecated - default Mono updateMulti(Query query, Update update, Class entityClass) { - return updateMulti(query, (UpdateDefinition) update, entityClass); - } - /** * Updates all objects that are found in the specified collection that matches the query document criteria with the * provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support. + * domain type information. Use {@link #updateMulti(Query, UpdateDefinition, Class, String)} to get full type specific + * support. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono updateMulti(Query query, UpdateDefinition update, String collectionName); - /** - * Updates all objects that are found in the specified collection that matches the query document criteria with the - * provided updated document.
- * NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of - * domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateMulti(Query, UpdateDefinition, String)}. - */ - @Deprecated - default Mono updateMulti(Query query, Update update, String collectionName) { - return updateMulti(query, (UpdateDefinition) update, collectionName); - } - /** * Updates all objects that are found in the collection for the entity class that matches the query document criteria * with the provided updated document. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. + * @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate + * the existing. Must not be {@literal null}. * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. * @param collectionName name of the collection to update the object in. Must not be {@literal null}. * @return the {@link UpdateResult} which lets you access the results of the previous write. * @since 2.3 + * @see Update + * @see AggregationUpdate */ Mono updateMulti(Query query, UpdateDefinition update, Class entityClass, String collectionName); - /** - * Updates all objects that are found in the collection for the entity class that matches the query document criteria - * with the provided updated document. - * - * @param query the query document that specifies the criteria used to select a record to be updated. Must not be - * {@literal null}. - * @param update the update document that contains the updated object or $ operators to manipulate the existing. Must - * not be {@literal null}. - * @param entityClass class of the pojo to be operated on. Must not be {@literal null}. - * @param collectionName name of the collection to update the object in. Must not be {@literal null}. - * @return the {@link UpdateResult} which lets you access the results of the previous write. - * @deprecated since 2.3 in favor of {@link #updateMulti(Query, UpdateDefinition, Class, String)}. - */ - @Deprecated - default Mono updateMulti(Query query, Update update, Class entityClass, String collectionName) { - return updateMulti(query, (UpdateDefinition) update, entityClass, collectionName); - } - /** * Remove the given object from the collection by id. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 39c83c6ee..47b272b79 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -1157,6 +1157,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati Class entityClass, String collectionName) { Assert.notNull(options, "Options must not be null! "); + Assert.notNull(entityClass, "Entity class must not be null!"); FindAndModifyOptions optionsToUse = FindAndModifyOptions.of(options); @@ -1788,7 +1789,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati queryObj.put("$isolated", 1); } - Flux result = Flux.empty(); + Flux result; if (update instanceof AggregationUpdate) { @@ -1796,29 +1797,30 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati ? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper) : Aggregation.DEFAULT_CONTEXT; - AggregationUpdate aUppdate = ((AggregationUpdate) update); - List pipeline = new AggregationUtil(queryMapper, mappingContext).createPipeline(aUppdate, context); + List pipeline = new AggregationUtil(queryMapper, mappingContext) + .createPipeline((AggregationUpdate) update, context); result = execute(collectionName, collection -> { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s", + serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName)); + } + MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, update.getUpdateObject(), queryObj); WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction); collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection; - if (multi) { - return collection.updateMany(queryObj, pipeline, updateOptions); - } - - return collection.updateOne(queryObj, pipeline, updateOptions); + return multi ? collection.updateMany(queryObj, pipeline, updateOptions) + : collection.updateOne(queryObj, pipeline, updateOptions); }); } else { result = execute(collectionName, collection -> { - Document updateObj = update == null ? new Document() - : updateMapper.getMappedObject(update.getUpdateObject(), entity); + Document updateObj = updateMapper.getMappedObject(update.getUpdateObject(), entity); if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s", @@ -1838,10 +1840,9 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati return collectionToUse.replaceOne(queryObj, updateObj, replaceOptions); } - if (multi) { - return collectionToUse.updateMany(queryObj, updateObj, updateOptions); - } - return collectionToUse.updateOne(queryObj, updateObj, updateOptions); + + return multi ? collectionToUse.updateMany(queryObj, updateObj, updateOptions) + : collectionToUse.updateOne(queryObj, updateObj, updateOptions); }); } @@ -1850,8 +1851,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati if (entity != null && entity.hasVersionProperty() && !multi) { if (updateResult.wasAcknowledged() && updateResult.getMatchedCount() == 0) { - Document updateObj = update == null ? new Document() - : updateMapper.getMappedObject(update.getUpdateObject(), entity); + Document updateObj = updateMapper.getMappedObject(update.getUpdateObject(), entity); if (containsVersionProperty(queryObj, entity)) throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: " + updateObj.toString() + " to collection " + collectionName); @@ -2085,8 +2085,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati if (query == null) { - // TODO: clean up - LOGGER.debug(String.format("find for class: %s in collection: %s", entityClass, collectionName)); + LOGGER.debug(String.format("Tail for class: %s in collection: %s", entityClass, collectionName)); return executeFindMultiInternal( collection -> new FindCallback(null).doInCollection(collection).cursorType(CursorType.TailableAwait), @@ -2586,12 +2585,11 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati Document mappedQuery = queryMapper.getMappedObject(query, entity); - Object mappedUpdate = new Document(); + Object mappedUpdate; if (update instanceof AggregationUpdate) { - AggregationOperationContext context = entityClass != null - ? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper) - : Aggregation.DEFAULT_CONTEXT; + AggregationOperationContext context = new RelaxedTypeBasedAggregationOperationContext(entityClass, + mappingContext, queryMapper); mappedUpdate = new AggregationUtil(queryMapper, mappingContext).createPipeline((Aggregation) update, context); } else { @@ -2997,7 +2995,9 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati } else if (update instanceof List) { return collection.findOneAndUpdate(query, (List) update, findOneAndUpdateOptions); } - return Flux.error(new IllegalArgumentException("doh - that does not work")); + + return Flux + .error(new IllegalArgumentException(String.format("Using %s is not supported in findOneAndUpdate", update))); } private static FindOneAndUpdateOptions convertToFindOneAndUpdateOptions(FindAndModifyOptions options, diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java index 7739f9980..711a20cb3 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveUpdateOperation.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core; +import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; import org.springframework.data.mongodb.core.query.UpdateDefinition; import reactor.core.publisher.Mono; @@ -119,27 +120,16 @@ public interface ReactiveUpdateOperation { interface UpdateWithUpdate { /** - * Set the {@link org.springframework.data.mongodb.core.query.Update} to be applied. + * Set the {@link UpdateDefinition} to be applied. * * @param update must not be {@literal null}. * @return new instance of {@link TerminatingUpdate}. Never {@literal null}. * @throws IllegalArgumentException if update is {@literal null}. * @since 2.3 + * @see Update + * @see AggregationUpdate */ - TerminatingUpdate apply(org.springframework.data.mongodb.core.query.UpdateDefinition update); - - /** - * Set the {@link org.springframework.data.mongodb.core.query.Update} to be applied. - * - * @param update must not be {@literal null}. - * @return new instance of {@link TerminatingUpdate}. Never {@literal null}. - * @throws IllegalArgumentException if update is {@literal null}. - * @deprecated since 2.3 in favor of {@link #apply(UpdateDefinition)}. - */ - @Deprecated - default TerminatingUpdate apply(org.springframework.data.mongodb.core.query.Update update) { - return apply((UpdateDefinition) update); - } + TerminatingUpdate apply(UpdateDefinition update); /** * Specify {@code replacement} object. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java index 7cc230466..0803eb0f7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdate.java @@ -21,22 +21,22 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.StringJoiner; import java.util.stream.Collectors; import org.bson.Document; + import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.SerializationUtils; -import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.UpdateDefinition; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** - * Abstraction for an {@code db.collection.update()} using an aggregation pipeline for a more expressive update - * statement expressing conditional updates based on current field values or updating one field using the value of - * another field(s). - * + * Abstraction for {@code db.collection.update()} using an aggregation pipeline. Aggregation pipeline updates use a more + * expressive update statement expressing conditional updates based on current field values or updating one field using + * the value of another field(s). + * *
  * AggregationUpdate update = AggregationUpdate.update().set("average")
  * 		.toValue(ArithmeticOperators.valueOf("tests").avg()).set("grade")
@@ -47,9 +47,9 @@ import org.springframework.util.StringUtils;
  * 						CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(60)).then("D"))
  * 				.defaultTo("F"));
  * 
- * - * The above sample is equivalent to the JSON update statement - * + * + * The above sample is equivalent to the JSON update statement: + * *
  * db.collection.update(
  *    { },
@@ -70,6 +70,7 @@ import org.springframework.util.StringUtils;
  * 
* * @author Christoph Strobl + * @author Mark Paluch * @see
MongoDB * Reference Documentation @@ -83,7 +84,7 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { /** * Create new {@link AggregationUpdate}. */ - public AggregationUpdate() { + protected AggregationUpdate() { this(new ArrayList<>()); } @@ -92,18 +93,14 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { * * @param pipeline must not be {@literal null}. */ - private AggregationUpdate(List pipeline) { + protected AggregationUpdate(List pipeline) { super(pipeline); for (AggregationOperation operation : pipeline) { if (operation instanceof FieldsExposingAggregationOperation) { ((FieldsExposingAggregationOperation) operation).getFields().forEach(it -> { - if (it instanceof Field) { - keysTouched.add(((Field) it).getName()); - } else { - keysTouched.add(it.toString()); - } + keysTouched.add(it.getName()); }); } } @@ -140,11 +137,7 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { Assert.notNull(setOperation, "SetOperation must not be null!"); setOperation.getFields().forEach(it -> { - if (it instanceof Field) { - keysTouched.add(((Field) it).getName()); - } else { - keysTouched.add(it.toString()); - } + keysTouched.add(it.getName()); }); operations.add(setOperation); return this; @@ -240,7 +233,7 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { /** * Prevents a write operation that affects multiple documents from yielding to other reads or writes * once the first document is written.
- * Use with {@link org.springframework.data.mongodb.core.MongoOperations#updateMulti(Query, Update, Class)}. + * Use with {@link org.springframework.data.mongodb.core.MongoOperations#updateMulti(Query, UpdateDefinition, Class)}. * * @return never {@literal null}. */ @@ -260,6 +253,8 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { } /* + * Returns a update document containing the update pipeline. + * The resulting document needs to be unwrapped to be used with update operations. * (non-Javadoc) * @see org.springframework.data.mongodb.core.query.UpdateDefinition#getUpdateObject() */ @@ -298,18 +293,16 @@ public class AggregationUpdate extends Aggregation implements UpdateDefinition { @Override public String toString() { - String target = "[\n"; - target += StringUtils.collectionToDelimitedString(toPipeline(Aggregation.DEFAULT_CONTEXT).stream() - .map(SerializationUtils::serializeToJsonSafely).collect(Collectors.toList()), ",\n"); - target += "\n]"; - return target; + StringJoiner joiner = new StringJoiner(",\n", "[\n", "\n]"); + toPipeline(Aggregation.DEFAULT_CONTEXT).stream().map(SerializationUtils::serializeToJsonSafely) + .forEach(joiner::add); + return joiner.toString(); } /** * Fluent API AggregationUpdate builder. * * @author Christoph Strobl - * @since 2.3 */ public interface SetValueAppender { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 0e1d97a49..89d808183 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -1723,7 +1723,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Test // DATAMONGO-2331 public void updateShouldAllowAggregationExpressions() { - AggregationUpdate update = new AggregationUpdate().set("total") + AggregationUpdate update = AggregationUpdate.update().set("total") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); template.updateFirst(new BasicQuery("{}"), update, Wrapper.class); @@ -1739,7 +1739,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Test // DATAMONGO-2331 public void updateShouldAllowMultipleAggregationExpressions() { - AggregationUpdate update = new AggregationUpdate() // + AggregationUpdate update = AggregationUpdate.update() // .set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) // .set("grade").toValue(ConditionalOperators.switchCases( // CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(90)).then("A"), // @@ -1767,7 +1767,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Test // DATAMONGO-2331 public void updateShouldMapAggregationExpressionToDomainType() { - AggregationUpdate update = new AggregationUpdate().set("name") + AggregationUpdate update = AggregationUpdate.update().set("name") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); template.updateFirst(new BasicQuery("{}"), update, Jedi.class); @@ -1785,7 +1785,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { SetOperation setOperation = SetOperation.builder().set("status").toValue("Modified").and().set("comments") .toValue(Fields.fields("misc1").and("misc2").asList()); - AggregationUpdate update = new AggregationUpdate(); + AggregationUpdate update = AggregationUpdate.update(); update.set(setOperation); update.unset("misc1", "misc2"); @@ -1803,7 +1803,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Test // DATAMONGO-2331 public void updateShouldMapAggregationUnsetToDomainType() { - AggregationUpdate update = new AggregationUpdate(); + AggregationUpdate update = AggregationUpdate.update(); update.unset("name"); template.updateFirst(new BasicQuery("{}"), update, Jedi.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index ed07f88c9..2766ae121 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import com.mongodb.client.MongoClient; import org.junit.Before; import org.junit.ClassRule; import org.junit.Ignore; @@ -39,7 +40,6 @@ import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; import org.springframework.data.mongodb.test.util.MongoVersionRule; -import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; /** @@ -58,7 +58,7 @@ public class MongoTemplateUpdateTests { public void setUp() { client = MongoTestUtils.replSetClient(); - template = new MongoTemplate(new SimpleMongoDbFactory(client, DB_NAME)); + template = new MongoTemplate(new SimpleMongoClientDbFactory(client, DB_NAME)); MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Score.class), client); MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Versioned.class), client); @@ -73,7 +73,7 @@ public class MongoTemplateUpdateTests { template.insertAll(Arrays.asList(score1, score2)); - AggregationUpdate update = new AggregationUpdate().set(SetOperation.builder() // + AggregationUpdate update = AggregationUpdate.update().set(SetOperation.builder() // .set("totalHomework").toValueOf(ArithmeticOperators.valueOf("homework").sum()).and() // .set("totalQuiz").toValueOf(ArithmeticOperators.valueOf("quiz").sum())) // .set(SetOperation.builder() // @@ -98,7 +98,7 @@ public class MongoTemplateUpdateTests { template.insertAll(Arrays.asList(one)); - AggregationUpdate update = new AggregationUpdate().set("author").toValue(new Author("Ada", "Lovelace")); + AggregationUpdate update = AggregationUpdate.update().set("author").toValue(new Author("Ada", "Lovelace")); template.update(Book.class).matching(Query.query(Criteria.where("id").is(one.id))).apply(update).all(); @@ -111,7 +111,7 @@ public class MongoTemplateUpdateTests { Versioned source = template.insert(Versioned.class).one(new Versioned("id-1", "value-0")); - AggregationUpdate update = new AggregationUpdate().set("value").toValue("changed"); + AggregationUpdate update = AggregationUpdate.update().set("value").toValue("changed"); template.update(Versioned.class).matching(Query.query(Criteria.where("id").is(source.id))).apply(update).first(); assertThat( @@ -125,7 +125,7 @@ public class MongoTemplateUpdateTests { Versioned source = template.insert(Versioned.class).one(new Versioned("id-1", "value-0")); - AggregationUpdate update = new AggregationUpdate() + AggregationUpdate update = AggregationUpdate.update() .set(SetOperation.builder().set("value").toValue("changed").and().set("version").toValue(10L)); template.update(Versioned.class).matching(Query.query(Criteria.where("id").is(source.id))).apply(update).first(); @@ -158,7 +158,7 @@ public class MongoTemplateUpdateTests { template.insertAll(Arrays.asList(antelopeAntics, beesBabble)); - AggregationUpdate update = new AggregationUpdate().unset("isbn", "stock"); + AggregationUpdate update = AggregationUpdate.update().unset("isbn", "stock"); template.update(Book.class).apply(update).all(); assertThat(all(Book.class)).containsExactlyInAnyOrder( // @@ -181,7 +181,8 @@ public class MongoTemplateUpdateTests { template.insertAll(Arrays.asList(one, two)); - AggregationUpdate update = new AggregationUpdate().replaceWith(ReplaceWithOperation.replaceWithValueOf("author")); + AggregationUpdate update = AggregationUpdate.update() + .replaceWith(ReplaceWithOperation.replaceWithValueOf("author")); template.update(Book.class).apply(update).all(); @@ -203,7 +204,7 @@ public class MongoTemplateUpdateTests { template.insertAll(Arrays.asList(one, two)); - AggregationUpdate update = new AggregationUpdate().replaceWith(new Author("Ada", "Lovelace")); + AggregationUpdate update = AggregationUpdate.update().replaceWith(new Author("Ada", "Lovelace")); template.update(Book.class).matching(Query.query(Criteria.where("id").is(one.id))).apply(update).all(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java index 1b6f2f9e8..c420daa62 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java @@ -894,7 +894,7 @@ public class ReactiveMongoTemplateUnitTests { @Test // DATAMONGO-2331 public void updateShouldAllowAggregationExpressions() { - AggregationUpdate update = new AggregationUpdate().set("total") + AggregationUpdate update = AggregationUpdate.update().set("total") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); template.updateFirst(new BasicQuery("{}"), update, Wrapper.class).subscribe(); @@ -910,7 +910,7 @@ public class ReactiveMongoTemplateUnitTests { @Test // DATAMONGO-2331 public void updateShouldAllowMultipleAggregationExpressions() { - AggregationUpdate update = new AggregationUpdate() // + AggregationUpdate update = AggregationUpdate.update() // .set("average").toValue(ArithmeticOperators.valueOf("tests").avg()) // .set("grade").toValue(ConditionalOperators.switchCases( // CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(90)).then("A"), // @@ -938,7 +938,7 @@ public class ReactiveMongoTemplateUnitTests { @Test // DATAMONGO-2331 public void updateShouldMapAggregationExpressionToDomainType() { - AggregationUpdate update = new AggregationUpdate().set("name") + AggregationUpdate update = AggregationUpdate.update().set("name") .toValue(ArithmeticOperators.valueOf("val1").sum().and("val2")); template.updateFirst(new BasicQuery("{}"), update, Jedi.class).subscribe(); @@ -956,7 +956,7 @@ public class ReactiveMongoTemplateUnitTests { SetOperation setOperation = SetOperation.builder().set("status").toValue("Modified").and().set("comments") .toValue(Fields.fields("misc1").and("misc2").asList()); - AggregationUpdate update = new AggregationUpdate(); + AggregationUpdate update = AggregationUpdate.update(); update.set(setOperation); update.unset("misc1", "misc2"); @@ -974,7 +974,7 @@ public class ReactiveMongoTemplateUnitTests { @Test // DATAMONGO-2331 public void updateShouldMapAggregationUnsetToDomainType() { - AggregationUpdate update = new AggregationUpdate(); + AggregationUpdate update = AggregationUpdate.update(); update.unset("name"); template.updateFirst(new BasicQuery("{}"), update, Jedi.class).subscribe(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java index f8ef235b3..7f3c05bf2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUpdateTests.java @@ -79,7 +79,7 @@ public class ReactiveMongoTemplateUpdateTests { template.insertAll(Arrays.asList(score1, score2)).then().as(StepVerifier::create).verifyComplete(); - AggregationUpdate update = new AggregationUpdate().set(SetOperation.builder() // + AggregationUpdate update = AggregationUpdate.update().set(SetOperation.builder() // .set("totalHomework").toValueOf(ArithmeticOperators.valueOf("homework").sum()).and() // .set("totalQuiz").toValueOf(ArithmeticOperators.valueOf("quiz").sum())) // .set(SetOperation.builder() // @@ -105,7 +105,7 @@ public class ReactiveMongoTemplateUpdateTests { Versioned source = new Versioned("id-1", "value-0"); template.insert(Versioned.class).one(source).then().as(StepVerifier::create).verifyComplete(); - AggregationUpdate update = new AggregationUpdate().set("value").toValue("changed"); + AggregationUpdate update = AggregationUpdate.update().set("value").toValue("changed"); template.update(Versioned.class).matching(Query.query(Criteria.where("id").is(source.id))).apply(update).first() .then().as(StepVerifier::create).verifyComplete(); @@ -123,7 +123,7 @@ public class ReactiveMongoTemplateUpdateTests { Versioned source = new Versioned("id-1", "value-0"); template.insert(Versioned.class).one(source).then().as(StepVerifier::create).verifyComplete(); - AggregationUpdate update = new AggregationUpdate() + AggregationUpdate update = AggregationUpdate.update() .set(SetOperation.builder().set("value").toValue("changed").and().set("version").toValue(10L)); template.update(Versioned.class).matching(Query.query(Criteria.where("id").is(source.id))).apply(update).first() @@ -160,7 +160,7 @@ public class ReactiveMongoTemplateUpdateTests { template.insertAll(Arrays.asList(antelopeAntics, beesBabble)).then().as(StepVerifier::create).verifyComplete(); - AggregationUpdate update = new AggregationUpdate().unset("isbn", "stock"); + AggregationUpdate update = AggregationUpdate.update().unset("isbn", "stock"); template.update(Book.class).apply(update).all().then().as(StepVerifier::create).verifyComplete(); all(Book.class).collectList().as(StepVerifier::create).consumeNextWith(it -> { @@ -187,7 +187,8 @@ public class ReactiveMongoTemplateUpdateTests { template.insertAll(Arrays.asList(one, two)).then().as(StepVerifier::create).verifyComplete(); ; - AggregationUpdate update = new AggregationUpdate().replaceWith(ReplaceWithOperation.replaceWithValueOf("author")); + AggregationUpdate update = AggregationUpdate.update() + .replaceWith(ReplaceWithOperation.replaceWithValueOf("author")); template.update(Book.class).apply(update).all().then().as(StepVerifier::create).verifyComplete(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java index b76a1ba5e..48faa1e09 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationUpdateUnitTests.java @@ -21,6 +21,8 @@ import org.bson.Document; import org.junit.Test; /** + * Unit tests for {@link AggregationUpdate}. + * * @author Christoph Strobl */ public class AggregationUpdateUnitTests { @@ -36,6 +38,4 @@ public class AggregationUpdateUnitTests { .containsExactly(new Document("$set", new Document("stage-1", "value-1")), new Document("$unset", "stage-2"), new Document("$set", new Document("stage-3", "value-3"))); } - - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java index ef09839ae..f5eb12877 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SetOperationUnitTests.java @@ -29,6 +29,8 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.lang.Nullable; /** + * Unit tests for {@link SetOperation}. + * * @author Christoph Strobl */ public class SetOperationUnitTests { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java index 25b4aed7c..9f59e429d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/UnsetOperationUnitTests.java @@ -32,6 +32,8 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.lang.Nullable; /** + * Unit tests for {@link UnsetOperation}. + * * @author Christoph Strobl */ public class UnsetOperationUnitTests { diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 5e1210736..4ddf33ac3 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -1,6 +1,11 @@ [[new-features]] = New & Noteworthy +[[new-features.2-3-0]] +== What's New in Spring Data MongoDB 2.3 + +* Support for <>. + [[new-features.2-2-0]] == What's New in Spring Data MongoDB 2.2 * Compatibility with MongoDB 4.2 deprecating `eval`, `group` and `geoNear` Template API methods. diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 96b7495fd..3eb5ec511 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -999,8 +999,9 @@ assertThat(p.getAge(), is(1)); [[mongo-template.aggregation-update]] === Aggregation Pipeline Updates -The update methods exposed by `MongoOperations` and `ReactiveMongoOperations` also accept an <> via `AggregationUpdate`. -This allows to leverage https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline[MongoDB 4.2 aggregations] in an update operation. +Update methods exposed by `MongoOperations` and `ReactiveMongoOperations` also accept an <> via `AggregationUpdate`. +Using `AggregationUpdate` allows leveraging https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline[MongoDB 4.2 aggregations] in an update operation. +Using aggregations in an update allows updating one or more fields by expressing multiple stages and multiple conditions with a single operation. The update can consist of the following stages: @@ -1048,7 +1049,7 @@ db.students.update( <3> <1> The 1st `$set` stage calculates a new field _average_ based on the average of the _tests_ field. <2> The 2nd `$set` stage calculates a new field _grade_ based on the _average_ field calculated by the first aggregation stage. <3> The pipeline is executed on the _students_ collection and uses `Student` for the aggregation field mapping. -<4> Apply the update to all documents within the collection. +<4> Apply the update to all matching documents in the collection. ==== [[mongo-template.find-and-replace]]