diff --git a/pom.xml b/pom.xml
index d864b2e4e6..b54ac65d06 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.1.0-SNAPSHOT
+ 4.1.x-GH-3218-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml
index 1b2a1390e6..4dd1549a1a 100644
--- a/spring-data-mongodb-benchmarks/pom.xml
+++ b/spring-data-mongodb-benchmarks/pom.xml
@@ -7,7 +7,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.1.0-SNAPSHOT
+ 4.1.x-GH-3218-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 8db8d798fb..ed455a503b 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.1.0-SNAPSHOT
+ 4.1.x-GH-3218-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 9a57f7eb52..597aebc0be 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 4.1.0-SNAPSHOT
+ 4.1.x-GH-3218-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/HintFunction.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/HintFunction.java
index c9b5514b28..c4e07f5b37 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/HintFunction.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/HintFunction.java
@@ -27,6 +27,7 @@
* Function object to apply a query hint. Can be an index name or a BSON document.
*
* @author Mark Paluch
+ * @author Christoph Strobl
* @since 4.1
*/
class HintFunction {
@@ -67,6 +68,23 @@ public boolean isPresent() {
return (hint instanceof String hintString && StringUtils.hasText(hintString)) || hint instanceof Bson;
}
+ /**
+ * Apply the hint to consumers depending on the hint format if {@link #isPresent() present}.
+ *
+ * @param registryProvider
+ * @param stringConsumer
+ * @param bsonConsumer
+ * @param
+ */
+ public void ifPresent(@Nullable CodecRegistryProvider registryProvider, Function stringConsumer,
+ Function bsonConsumer) {
+
+ if (!isPresent()) {
+ return;
+ }
+ apply(registryProvider, stringConsumer, bsonConsumer);
+ }
+
/**
* Apply the hint to consumers depending on the hint format.
*
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
index 2e86b80080..05aeda069b 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryOperations.java
@@ -715,6 +715,7 @@ UpdateOptions getUpdateOptions(@Nullable Class> domainType, @Nullable Consumer
.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList()));
}
+ HintFunction.from(getQuery().getHint()).ifPresent(codecRegistryProvider, options::hintString, options::hint);
applyCollation(domainType, options::collation);
if (callback != null) {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
index 3f4a63232e..2497812a3f 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
@@ -978,6 +978,28 @@ void updateManyShouldUseCollationWhenPresent() {
assertThat(options.getValue().getCollation().getLocale()).isEqualTo("fr");
}
+ @Test // GH-3218
+ void updateUsesHintStringFromQuery() {
+
+ template.updateFirst(new Query().withHint("index-1"), new Update().set("spring", "data"), Human.class);
+
+ ArgumentCaptor options = ArgumentCaptor.forClass(UpdateOptions.class);
+ verify(collection).updateOne(any(Bson.class), any(Bson.class), options.capture());
+
+ assertThat(options.getValue().getHintString()).isEqualTo("index-1");
+ }
+
+ @Test // GH-3218
+ void updateUsesHintDocumentFromQuery() {
+
+ template.updateFirst(new Query().withHint("{ name : 1 }"), new Update().set("spring", "data"), Human.class);
+
+ ArgumentCaptor options = ArgumentCaptor.forClass(UpdateOptions.class);
+ verify(collection).updateOne(any(Bson.class), any(Bson.class), options.capture());
+
+ assertThat(options.getValue().getHint()).isEqualTo(new Document("name", 1));
+ }
+
@Test // DATAMONGO-1518
void replaceOneShouldUseCollationWhenPresent() {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
index ec4e9e90f7..48b48a2e23 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
@@ -350,7 +350,28 @@ void updateManyShouldUseCollationWhenPresent() {
verify(collection).updateMany(any(), any(Bson.class), options.capture());
assertThat(options.getValue().getCollation().getLocale()).isEqualTo("fr");
+ }
+
+ @Test // GH-3218
+ void updateUsesHintStringFromQuery() {
+
+ template.updateFirst(new Query().withHint("index-1"), new Update().set("spring", "data"), Person.class).subscribe();
+
+ ArgumentCaptor options = ArgumentCaptor.forClass(UpdateOptions.class);
+ verify(collection).updateOne(any(Bson.class), any(Bson.class), options.capture());
+
+ assertThat(options.getValue().getHintString()).isEqualTo("index-1");
+ }
+
+ @Test // GH-3218
+ void updateUsesHintDocumentFromQuery() {
+
+ template.updateFirst(new Query().withHint("{ firstname : 1 }"), new Update().set("spring", "data"), Person.class).subscribe();
+
+ ArgumentCaptor options = ArgumentCaptor.forClass(UpdateOptions.class);
+ verify(collection).updateOne(any(Bson.class), any(Bson.class), options.capture());
+ assertThat(options.getValue().getHint()).isEqualTo(new Document("firstname", 1));
}
@Test // DATAMONGO-1518
diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc
index ebfc97e75b..45f54b6cab 100644
--- a/src/main/asciidoc/reference/mongodb.adoc
+++ b/src/main/asciidoc/reference/mongodb.adoc
@@ -922,6 +922,7 @@ Most methods return the `Update` object to provide a fluent style for the API.
* *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`.
+NOTE: Index hints for the update operation can be provided via `Query.withHint(...)`.
[[mongodb-template-update.update]]
==== Methods in the `Update` Class