Support hints on Update.

This commit makes sure to read query hints and apply them to the MongoDB UpdateOptions when running an update via Reactive-/MongoTemplate.

Original pull request: #4311
Closes: #3218
This commit is contained in:
Christoph Strobl
2023-03-02 09:51:50 +01:00
committed by Mark Paluch
parent 0020499d4e
commit cd63501680
5 changed files with 63 additions and 0 deletions

View File

@@ -27,6 +27,7 @@ import org.springframework.util.StringUtils;
* 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 @@ class HintFunction {
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 <R>
*/
public <R> void ifPresent(@Nullable CodecRegistryProvider registryProvider, Function<String, R> stringConsumer,
Function<Bson, R> bsonConsumer) {
if (!isPresent()) {
return;
}
apply(registryProvider, stringConsumer, bsonConsumer);
}
/**
* Apply the hint to consumers depending on the hint format.
*

View File

@@ -715,6 +715,7 @@ class QueryOperations {
.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) {

View File

@@ -978,6 +978,28 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
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<UpdateOptions> 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<UpdateOptions> 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() {

View File

@@ -350,7 +350,28 @@ public class ReactiveMongoTemplateUnitTests {
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<UpdateOptions> 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<UpdateOptions> 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

View File

@@ -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 <<mongo-template.find-and-upsert, findAndModify>> 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