DATAMONGO-2331 - Polishing.

Remove deprecated methods accepting Update in favor of methods accepting UpdateDefinition in Template APIs.
Hide AggregationUpdate constructor.

Tweak Javadoc and reference documentation.

Original pull request: #789.
This commit is contained in:
Mark Paluch
2019-11-12 11:06:48 +01:00
parent cc07a1bbb4
commit 1a5de2e1db
16 changed files with 257 additions and 710 deletions

View File

@@ -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<T> 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<T> apply(Update update) {
return apply((UpdateDefinition) update);
}
/**
* Specify {@code replacement} object.
*

View File

@@ -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:
* </p>
*
*
* <pre class="code">
* TypedAggregation&lt;T&gt; 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:
* </p>
*
*
* <pre class="code">
* TypedAggregation&lt;T&gt; 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> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, Update update, Class<T> entityClass) {
return findAndModify(query, (UpdateDefinition) update, entityClass);
}
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName) {
return findAndModify(query, (UpdateDefinition) update, entityClass, collectionName);
}
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass) {
return findAndModify(query, (UpdateDefinition) update, options, entityClass);
}
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
* 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> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName) {
return findAndModify(query, (UpdateDefinition) update, options, entityClass, collectionName);
}
/**
* Triggers
* <a href="https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/">findOneAndReplace<a/>
@@ -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. <br />
* <strong>NOTE:</strong> {@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. <br />
* <strong>NOTE:</strong> 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.
* <br />
* domain type information. Use {@link #upsert(Query, UpdateDefinition, Class, String)} to get full type specific
* support. <br />
* <strong>NOTE:</strong> {@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. <br />
* <strong>NOTE:</strong> 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. <br />
* <strong>NOTE:</strong> {@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. <br />
* <strong>NOTE:</strong> {@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. <br />
* <strong>NOTE:</strong> 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.
* <br />
* <strong>NOTE:</strong> {@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. <br />
* <strong>NOTE:</strong> 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. <br />
*
* @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. <br />
* <strong>NOTE:</strong> {@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. <br />
* <strong>NOTE:</strong> 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. <br />
* <strong>NOTE:</strong> 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}. <br />

View File

@@ -437,7 +437,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@SuppressWarnings("ConstantConditions")
protected <T> CloseableIterator<T> doStream(Query query, final Class<?> entityType, String collectionName,
protected <T> CloseableIterator<T> doStream(Query query, Class<?> entityType, String collectionName,
Class<T> 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<Document> createCollection(final String collectionName) {
public MongoCollection<Document> 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<Document> createCollection(final String collectionName,
final @Nullable CollectionOptions collectionOptions) {
public MongoCollection<Document> 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<Document> getCollection(final String collectionName) {
public MongoCollection<Document> 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<Void>() {
public Void doInCollection(MongoCollection<Document> 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<Void>) 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<Object> insertDocumentList(final String collectionName, final List<Document> documents) {
protected List<Object> insertDocumentList(String collectionName, List<Document> 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<Object>() {
public Object doInCollection(MongoCollection<Document> 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<Document> pipeline = new AggregationUtil(queryMapper, mappingContext).createPipeline(aUppdate, context);
List<Document> 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 <T> DeleteResult doRemove(final String collectionName, final Query query,
@Nullable final Class<T> entityClass, boolean multi) {
protected <T> DeleteResult doRemove(String collectionName, Query query, @Nullable Class<T> 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<Document>) update, opts);
}
throw new IllegalArgumentException("doh - that does not work");
throw new IllegalArgumentException(String.format("Using %s is not supported in findOneAndUpdate", update));
}
}

View File

@@ -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
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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 <T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass) {
return findAndModify(query, (UpdateDefinition) update, entityClass);
}
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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 <T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass, String collectionName) {
return findAndModify(query, (UpdateDefinition) update, entityClass, collectionName);
}
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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 <T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass) {
return findAndModify(query, (UpdateDefinition) update, options, entityClass);
}
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
* 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 <T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName) {
return findAndModify(query, (UpdateDefinition) update, options, entityClass, collectionName);
}
/**
* Triggers
* <a href="https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/">findOneAndReplace<a/>
@@ -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. <br />
* <strong>NOTE:</strong> {@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<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 Mono<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. <br />
* <strong>NOTE:</strong> 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<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. <br />
* <strong>NOTE:</strong> 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.
* <br />
* <strong>NOTE:</strong> {@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<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
*/
Mono<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. <br />
* <strong>NOTE:</strong> {@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<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. <br />
* <strong>NOTE:</strong> {@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<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.
*
* @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<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. <br />
* <strong>NOTE:</strong> 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.
* <br />
* domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific
* support. <br />
* <strong>NOTE:</strong> {@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<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. <br />
* <strong>NOTE:</strong> 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<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. <br />
* <strong>NOTE:</strong> {@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<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. <br />
*
* @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<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
*/
Mono<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 Mono<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. <br />
* <strong>NOTE:</strong> 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<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. <br />
* <strong>NOTE:</strong> 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<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
*/
Mono<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 Mono<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 id.
*

View File

@@ -1157,6 +1157,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Class<T> 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<UpdateResult> result = Flux.empty();
Flux<UpdateResult> 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<Document> pipeline = new AggregationUtil(queryMapper, mappingContext).createPipeline(aUppdate, context);
List<Document> 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<Document>) 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,

View File

@@ -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<T> {
/**
* 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<T> 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<T> apply(org.springframework.data.mongodb.core.query.Update update) {
return apply((UpdateDefinition) update);
}
TerminatingUpdate<T> apply(UpdateDefinition update);
/**
* Specify {@code replacement} object.

View File

@@ -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).
*
* <pre class="code">
* 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"));
* </pre>
*
* The above sample is equivalent to the JSON update statement
*
*
* The above sample is equivalent to the JSON update statement:
*
* <pre class="code">
* db.collection.update(
* { },
@@ -70,6 +70,7 @@ import org.springframework.util.StringUtils;
* </pre>
*
* @author Christoph Strobl
* @author Mark Paluch
* @see <a href=
* "https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline">MongoDB
* Reference Documentation</a>
@@ -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<AggregationOperation> pipeline) {
protected AggregationUpdate(List<AggregationOperation> 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 <strong>multiple</strong> documents from yielding to other reads or writes
* once the first document is written. <br />
* 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 {

View File

@@ -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);

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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")));
}
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -1,6 +1,11 @@
[[new-features]]
= New & Noteworthy
[[new-features.2-3-0]]
== What's New in Spring Data MongoDB 2.3
* Support for <<mongo-template.aggregation-update,aggregation pipelines in update operations>>.
[[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.

View File

@@ -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 <<mongo.aggregation, Aggregation Pipeline>> 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 <<mongo.aggregation, Aggregation Pipeline>> 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]]