From 0f0a4ed31b40224e699ef0e9cd2e7014841baf34 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 20 Sep 2019 11:18:03 +0200 Subject: [PATCH] DATAMONGO-1731 - Improve update & upsert documentation. --- .../data/mongodb/core/MongoOperations.java | 22 +++++++++++++++---- .../data/mongodb/core/MongoTemplate.java | 6 +++++ .../mongodb/core/ReactiveMongoOperations.java | 20 ++++++++++++++--- .../mongodb/core/ReactiveMongoTemplate.java | 6 +++++ .../data/mongodb/core/query/BasicQuery.java | 9 ++++++++ .../data/mongodb/core/query/Query.java | 13 ++++++++++- .../data/mongodb/core/query/TextQuery.java | 9 ++++++++ src/main/asciidoc/reference/mongodb.adoc | 4 ++++ 8 files changed, 81 insertions(+), 8 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 1b7ceb612..ae8d941b6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -1232,7 +1232,9 @@ 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. + * combining the query document and the update document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. @@ -1248,6 +1250,9 @@ public interface MongoOperations extends FluentMongoOperations { * combining the query document and the update document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of * domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support. + *
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, 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}. @@ -1260,8 +1265,10 @@ 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. - * + * combining the query document and the update document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead. + * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. * @param update the update document that contains the updated object or $ operators to manipulate the existing @@ -1274,7 +1281,9 @@ public interface MongoOperations extends FluentMongoOperations { /** * Updates the first object that is found in the collection of the entity class that matches the query document with - * the provided update document. + * the provided update document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. @@ -1290,6 +1299,9 @@ public interface MongoOperations extends FluentMongoOperations { * the provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of * domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support. + *
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. @@ -1303,6 +1315,8 @@ public interface MongoOperations extends FluentMongoOperations { /** * Updates the first object that is found in the specified collection that matches the query document criteria with * the provided updated document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 7d0345304..574e03976 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -1576,6 +1576,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware, Assert.notNull(query, "Query must not be null!"); Assert.notNull(update, "Update must not be null!"); + if (query.isSorted() && LOGGER.isWarnEnabled()) { + + LOGGER.warn("{} does not support sort ('{}'). Please use findAndModify() instead.", + upsert ? "Upsert" : "UpdateFirst", serializeToJsonSafely(query.getSortObject())); + } + return execute(collectionName, new CollectionCallback() { public UpdateResult doInCollection(MongoCollection collection) throws MongoException, DataAccessException { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index b94b78f70..9f7298869 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -1101,7 +1101,9 @@ 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. + * combining the query document and the update document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. @@ -1117,6 +1119,9 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * combining the query document and the update document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of * domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support. + *
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. @@ -1129,7 +1134,9 @@ 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. + * combining the query document and the update document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be upserted. Must not be * {@literal null}. @@ -1143,7 +1150,9 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { /** * Updates the first object that is found in the collection of the entity class that matches the query document with - * the provided update document. + * the provided update document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. @@ -1159,6 +1168,9 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { * the provided updated document.
* NOTE: Any additional support for field mapping, versions, etc. is not available due to the lack of * domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support. + *
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. @@ -1172,6 +1184,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations { /** * Updates the first object that is found in the specified collection that matches the query document criteria with * the provided updated document.
+ * NOTE: {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}. + * Use {@link #findAndModify(Query, Update, Class, String)} instead. * * @param query the query document that specifies the criteria used to select a record to be updated. Must not be * {@literal null}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index 99d826ec7..4020ebad2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -1620,6 +1620,12 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati private Mono doUpdate(String collectionName, Query query, @Nullable UpdateDefinition update, @Nullable Class entityClass, boolean upsert, boolean multi) { + if (query.isSorted() && LOGGER.isWarnEnabled()) { + + LOGGER.warn("{} does not support sort ('{}'). Please use findAndModify() instead.", + upsert ? "Upsert" : "UpdateFirst", serializeToJsonSafely(query.getSortObject())); + } + MongoPersistentEntity entity = entityClass == null ? null : getPersistentEntity(entityClass); Flux result = execute(collectionName, collection -> { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java index 13f3891e2..65f23e303 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/BasicQuery.java @@ -148,6 +148,15 @@ public class BasicQuery extends Query { this.sortObject = sortObject; } + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.query.Query#isSorted() + */ + @Override + public boolean isSorted() { + return super.isSorted() || !sortObject.isEmpty(); + } + /** * Set the fields (projection) {@link Document}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java index 4a5add199..20bccc3e8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Query.java @@ -262,6 +262,17 @@ public class Query { return document; } + /** + * Returns {@literal true} if the {@link Query} has a sort parameter. + * + * @return {@literal true} if sorted. + * @see Sort#isSorted() + * @since 2.1 + */ + public boolean isSorted() { + return sort.isSorted(); + } + /** * Get the number of documents to skip. * @@ -372,7 +383,7 @@ public class Query { * Set the number of documents to return in each response batch.
* Use {@literal 0 (zero)} for no limit. A negative limit closes the cursor after returning a single * batch indicating to the server that the client will not ask for a subsequent one. - * + * * @param batchSize The number of documents to return per batch. * @return this. * @see Meta#setCursorBatchSize(int) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java index c38098452..8eeb78750 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/TextQuery.java @@ -180,4 +180,13 @@ public class TextQuery extends Query { return sort; } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.query.Query#isSorted() + */ + @Override + public boolean isSorted() { + return super.isSorted() || sortByScore; + } } diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 0514efbbd..66521c8e0 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -868,6 +868,8 @@ Most methods return the `Update` object to provide a fluent style for the API. * *updateFirst*: Updates the first document that matches the query document criteria with the updated document. * *updateMulti*: Updates all objects that match the query document criteria with the updated document. +WARNING: `updateFirst` does not support ordering. Please use <> to apply `Sort`. + [[mongodb-template-update.update]] ==== Methods in the `Update` Class @@ -919,6 +921,8 @@ Related to performing an `updateFirst` operation, you can also perform an "`upse template.upsert(query(where("ssn").is(1111).and("firstName").is("Joe").and("Fraizer").is("Update")), update("address", addr), Person.class); ---- +WARNING: `upsert` does not support ordering. Please use <> to apply `Sort`. + [[mongo-template.find-and-upsert]] === Finding and Upserting Documents in a Collection