Skip to content

DATAMONGO-1836 - Add support to hint in aggregation options. #878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-DATAMONGO-1836-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-DATAMONGO-1836-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-DATAMONGO-1836-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.1.0-SNAPSHOT</version>
<version>3.1.0-DATAMONGO-1836-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
* @author Cimon Lucas
* @author Michael J. Simons
* @author Roman Puchkovskiy
* @author Yadhukrishna S Pai
*/
public class MongoTemplate implements MongoOperations, ApplicationContextAware, IndexOperationsProvider {

Expand Down Expand Up @@ -2149,6 +2150,8 @@ protected <O> AggregationResults<O> doAggregate(Aggregation aggregation, String

options.getComment().ifPresent(aggregateIterable::comment);

options.getHint().ifPresent(aggregateIterable::hint);

if (options.hasExecutionTimeLimit()) {
aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS);
}
Expand Down Expand Up @@ -2207,6 +2210,8 @@ protected <O> CloseableIterator<O> aggregateStream(Aggregation aggregation, Stri

options.getComment().ifPresent(cursor::comment);

options.getHint().ifPresent(cursor::hint);

Class<?> domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType()
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
* @author Christoph Strobl
* @author Roman Puchkovskiy
* @author Mathieu Ouellet
* @author Yadhukrishna S Pai
* @since 2.0
*/
public class ReactiveMongoTemplate implements ReactiveMongoOperations, ApplicationContextAware {
Expand Down Expand Up @@ -1024,6 +1025,8 @@ private <O> Flux<O> aggregateAndMap(MongoCollection<Document> collection, List<D

options.getComment().ifPresent(cursor::comment);

options.getHint().ifPresent(cursor::hint);

Optionals.firstNonEmpty(options::getCollation, () -> operations.forType(inputType).getCollation()) //
.map(Collation::toMongoCollation) //
.ifPresent(cursor::collation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @author Yadhukrishna S Pai
* @see Aggregation#withOptions(AggregationOptions)
* @see TypedAggregation#withOptions(AggregationOptions)
* @since 1.6
Expand All @@ -45,12 +46,14 @@ public class AggregationOptions {
private static final String COLLATION = "collation";
private static final String COMMENT = "comment";
private static final String MAX_TIME = "maxTimeMS";
private static final String HINT = "hint";

private final boolean allowDiskUse;
private final boolean explain;
private final Optional<Document> cursor;
private final Optional<Collation> collation;
private final Optional<String> comment;
private final Optional<Document> hint;
private Duration maxTime = Duration.ZERO;
private ResultOptions resultOptions = ResultOptions.READ;

Expand All @@ -77,7 +80,7 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, Document cursor
*/
public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor,
@Nullable Collation collation) {
this(allowDiskUse, explain, cursor, collation, null);
this(allowDiskUse, explain, cursor, collation, null, null);
}

/**
Expand All @@ -89,16 +92,18 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Docum
* aggregation.
* @param collation collation for string comparison. Can be {@literal null}.
* @param comment execution comment. Can be {@literal null}.
* @param hint can be {@literal null}, used to provide an index that would be forcibly used by query optimizer.
* @since 2.2
*/
public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor,
@Nullable Collation collation, @Nullable String comment) {
@Nullable Collation collation, @Nullable String comment, @Nullable Document hint) {

this.allowDiskUse = allowDiskUse;
this.explain = explain;
this.cursor = Optional.ofNullable(cursor);
this.collation = Optional.ofNullable(collation);
this.comment = Optional.ofNullable(comment);
this.hint = Optional.ofNullable(hint);
}

/**
Expand Down Expand Up @@ -130,8 +135,9 @@ public static AggregationOptions fromDocument(Document document) {
Collation collation = document.containsKey(COLLATION) ? Collation.from(document.get(COLLATION, Document.class))
: null;
String comment = document.getString(COMMENT);
Document hint = document.get(HINT, Document.class);

AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment, hint);
if (document.containsKey(MAX_TIME)) {
options.maxTime = Duration.ofMillis(document.getLong(MAX_TIME));
}
Expand Down Expand Up @@ -212,6 +218,16 @@ public Optional<String> getComment() {
return comment;
}

/**
* Get the hint used to to fulfill the aggregation.
*
* @return never {@literal null}.
*/
public Optional<Document> getHint() {
return hint;
}


/**
* @return the time limit for processing. {@link Duration#ZERO} is used for the default unbounded behavior.
* @since 3.0
Expand Down Expand Up @@ -248,6 +264,10 @@ Document applyAndReturnPotentiallyChangedCommand(Document command) {
result.put(EXPLAIN, explain);
}

if (result.containsKey(HINT)) {
hint.ifPresent(val -> result.append(HINT, val));
}

if (!result.containsKey(CURSOR)) {
cursor.ifPresent(val -> result.put(CURSOR, val));
}
Expand Down Expand Up @@ -277,6 +297,7 @@ public Document toDocument() {
cursor.ifPresent(val -> document.put(CURSOR, val));
collation.ifPresent(val -> document.append(COLLATION, val.toDocument()));
comment.ifPresent(val -> document.append(COMMENT, val));
hint.ifPresent(val -> document.append(HINT, val));

if (hasExecutionTimeLimit()) {
document.append(MAX_TIME, maxTime.toMillis());
Expand Down Expand Up @@ -318,6 +339,7 @@ public static class Builder {
private @Nullable Document cursor;
private @Nullable Collation collation;
private @Nullable String comment;
private @Nullable Document hint;
private @Nullable Duration maxTime;
private @Nullable ResultOptions resultOptions;

Expand Down Expand Up @@ -396,6 +418,19 @@ public Builder comment(@Nullable String comment) {
return this;
}

/**
* Define a hint is used forcibly by query optimizer to to fulfill the aggregation.
*
* @param hint can be {@literal null}.
* @return this.
* @since 2.2
*/
public Builder hint(@Nullable Document hint) {

this.hint = hint;
return this;
}

/**
* Set the time limit for processing.
*
Expand Down Expand Up @@ -431,7 +466,13 @@ public Builder skipOutput() {
*/
public AggregationOptions build() {

AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
AggregationOptions options = new AggregationOptions(
allowDiskUse,
explain,
cursor,
collation,
comment,
hint);
if (maxTime != null) {
options.maxTime = maxTime;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
* @author Mark Paluch
* @author Michael J. Simons
* @author Roman Puchkovskiy
* @author Yadhukrishna S Pai
*/
@MockitoSettings(strictness = Strictness.LENIENT)
public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
Expand Down Expand Up @@ -468,6 +469,17 @@ void aggregateShouldHonorOptionsComment() {
verify(aggregateIterable).comment("expensive");
}

@Test // DATAMONGO-1836
void aggregateShouldHonorOptionsHint() {

Document hint = new Document("dummyField", 1);
AggregationOptions options = AggregationOptions.builder().hint(hint).build();

template.aggregate(newAggregation(Aggregation.unwind("foo")).withOptions(options), "collection-1", Wrapper.class);

verify(aggregateIterable).hint(hint);
}

@Test // DATAMONGO-1166, DATAMONGO-2264
void geoNearShouldHonorReadPreferenceWhenSet() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
* @author Christoph Strobl
* @author Roman Puchkovskiy
* @author Mathieu Ouellet
* @author Yadhukrishna S Pai
*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
Expand Down Expand Up @@ -628,6 +629,17 @@ void aggregateShouldHonorOptionsComment() {
verify(aggregatePublisher).comment("expensive");
}

@Test // DATAMONGO-1836
void aggregateShouldHonorOptionsHint() {
Document hint = new Document("dummyHint", 1);
AggregationOptions options = AggregationOptions.builder().hint(hint).build();

template.aggregate(newAggregation(Sith.class, project("id")).withOptions(options), AutogenerateableId.class,
Document.class).subscribe();

verify(aggregatePublisher).hint(hint);
}

@Test // DATAMONGO-2390
void aggregateShouldNoApplyZeroOrNegativeMaxTime() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
* @author Thomas Darimont
* @author Mark Paluch
* @author Christoph Strobl
* @author Yadhukrishna S Pai
* @since 1.6
*/
public class AggregationOptionsTests {

private final Document dummyHint = new Document("dummyField", 1);
AggregationOptions aggregationOptions;

@BeforeEach
Expand All @@ -40,25 +42,28 @@ public void setup() {
.cursorBatchSize(1) //
.allowDiskUse(true) //
.comment("hola!") //
.hint(dummyHint) //
.build();
}

@Test // DATAMONGO-960
@Test // DATAMONGO-960, DATAMONGO-1836
public void aggregationOptionsBuilderShouldSetOptionsAccordingly() {

assertThat(aggregationOptions.isAllowDiskUse()).isTrue();
assertThat(aggregationOptions.isExplain()).isTrue();
assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1));
assertThat(aggregationOptions.getHint().get()).isEqualTo(dummyHint);
}

@Test // DATAMONGO-1637, DATAMONGO-2153
@Test // DATAMONGO-1637, DATAMONGO-2153, DATAMONGO-1836
public void shouldInitializeFromDocument() {

Document document = new Document();
document.put("cursor", new Document("batchSize", 1));
document.put("explain", true);
document.put("allowDiskUse", true);
document.put("comment", "hola!");
document.put("hint", dummyHint);

aggregationOptions = AggregationOptions.fromDocument(document);

Expand All @@ -67,12 +72,19 @@ public void shouldInitializeFromDocument() {
assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1));
assertThat(aggregationOptions.getCursorBatchSize()).isEqualTo(1);
assertThat(aggregationOptions.getComment().get()).isEqualTo("hola!");
assertThat(aggregationOptions.getHint().get()).isEqualTo(dummyHint);
}

@Test // DATAMONGO-960, DATAMONGO-2153
@Test // DATAMONGO-960, DATAMONGO-2153, DATAMONGO-1836
public void aggregationOptionsToString() {

assertThat(aggregationOptions.toDocument()).isEqualTo(Document.parse(
"{ \"allowDiskUse\" : true , \"explain\" : true , \"cursor\" : { \"batchSize\" : 1}, \"comment\": \"hola!\"}"));
"{ " +
"\"allowDiskUse\" : true , " +
"\"explain\" : true , " +
"\"cursor\" : { \"batchSize\" : 1}, " +
"\"comment\": \"hola!\", " +
"\"hint\" : { \"dummyField\" : 1}" +
"}"));
}
}