Skip to content

Commit 8ce3e45

Browse files
committed
DATAMONGO-2153 - Apply Meta comment and cursor size to AggregationOptions.
We now apply propagate the cursor size to aggregation options. We introduced AggregationOptions.comment to propagate the meta comment to aggregation execution. Original pull request: #743.
1 parent f456851 commit 8ce3e45

File tree

11 files changed

+173
-25
lines changed

11 files changed

+173
-25
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,8 @@ protected <O> AggregationResults<O> doAggregate(Aggregation aggregation, String
21362136
aggregateIterable = aggregateIterable.batchSize(options.getCursorBatchSize());
21372137
}
21382138

2139+
options.getComment().ifPresent(aggregateIterable::comment);
2140+
21392141
MongoIterable<O> iterable = aggregateIterable.map(val -> {
21402142

21412143
rawResult.add(val);
@@ -2177,6 +2179,8 @@ protected <O> CloseableIterator<O> aggregateStream(Aggregation aggregation, Stri
21772179
cursor = cursor.batchSize(options.getCursorBatchSize());
21782180
}
21792181

2182+
options.getComment().ifPresent(cursor::comment);
2183+
21802184
Class<?> domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation) aggregation).getInputType()
21812185
: null;
21822186

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,8 @@ private <O> Flux<O> aggregateAndMap(MongoCollection<Document> collection, List<D
10361036
cursor = cursor.batchSize(options.getCursorBatchSize());
10371037
}
10381038

1039+
options.getComment().ifPresent(cursor::comment);
1040+
10391041
Optionals.firstNonEmpty(options::getCollation, () -> operations.forType(inputType).getCollation()) //
10401042
.map(Collation::toMongoCollation) //
10411043
.ifPresent(cursor::collation);

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/AggregationOptions.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ public class AggregationOptions {
4444
private static final String EXPLAIN = "explain";
4545
private static final String ALLOW_DISK_USE = "allowDiskUse";
4646
private static final String COLLATION = "collation";
47+
private static final String COMMENT = "comment";
4748

4849
private final boolean allowDiskUse;
4950
private final boolean explain;
5051
private final Optional<Document> cursor;
5152
private final Optional<Collation> collation;
53+
private final Optional<String> comment;
5254

5355
/**
5456
* Creates a new {@link AggregationOptions}.
@@ -73,11 +75,28 @@ public AggregationOptions(boolean allowDiskUse, boolean explain, Document cursor
7375
*/
7476
public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor,
7577
@Nullable Collation collation) {
78+
this(allowDiskUse, explain, cursor, collation, null);
79+
}
80+
81+
/**
82+
* Creates a new {@link AggregationOptions}.
83+
*
84+
* @param allowDiskUse whether to off-load intensive sort-operations to disk.
85+
* @param explain whether to get the execution plan for the aggregation instead of the actual results.
86+
* @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the
87+
* aggregation.
88+
* @param collation collation for string comparison. Can be {@literal null}.
89+
* @param comment execution comment. Can be {@literal null}.
90+
* @since 2.2
91+
*/
92+
public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor,
93+
@Nullable Collation collation, @Nullable String comment) {
7694

7795
this.allowDiskUse = allowDiskUse;
7896
this.explain = explain;
7997
this.cursor = Optional.ofNullable(cursor);
8098
this.collation = Optional.ofNullable(collation);
99+
this.comment = Optional.ofNullable(comment);
81100
}
82101

83102
/**
@@ -108,8 +127,9 @@ public static AggregationOptions fromDocument(Document document) {
108127
Document cursor = document.get(CURSOR, Document.class);
109128
Collation collation = document.containsKey(COLLATION) ? Collation.from(document.get(COLLATION, Document.class))
110129
: null;
130+
String comment = document.getString(COMMENT);
111131

112-
return new AggregationOptions(allowDiskUse, explain, cursor, collation);
132+
return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
113133
}
114134

115135
/**
@@ -176,6 +196,16 @@ public Optional<Collation> getCollation() {
176196
return collation;
177197
}
178198

199+
/**
200+
* Get the comment for the aggregation.
201+
*
202+
* @return
203+
* @since 2.2
204+
*/
205+
public Optional<String> getComment() {
206+
return comment;
207+
}
208+
179209
/**
180210
* Returns a new potentially adjusted copy for the given {@code aggregationCommandObject} with the configuration
181211
* applied.
@@ -219,6 +249,7 @@ public Document toDocument() {
219249

220250
cursor.ifPresent(val -> document.put(CURSOR, val));
221251
collation.ifPresent(val -> document.append(COLLATION, val.toDocument()));
252+
comment.ifPresent(val -> document.append(COMMENT, val));
222253

223254
return document;
224255
}
@@ -247,6 +278,7 @@ public static class Builder {
247278
private boolean explain;
248279
private @Nullable Document cursor;
249280
private @Nullable Collation collation;
281+
private @Nullable String comment;
250282

251283
/**
252284
* Defines whether to off-load intensive sort-operations to disk.
@@ -302,20 +334,34 @@ public Builder cursorBatchSize(int batchSize) {
302334
*
303335
* @param collation can be {@literal null}.
304336
* @return
337+
* @since 2.0
305338
*/
306339
public Builder collation(@Nullable Collation collation) {
307340

308341
this.collation = collation;
309342
return this;
310343
}
311344

345+
/**
346+
* Define a comment to describe the execution.
347+
*
348+
* @param comment can be {@literal null}.
349+
* @return
350+
* @since 2.2
351+
*/
352+
public Builder comment(@Nullable String comment) {
353+
354+
this.comment = comment;
355+
return this;
356+
}
357+
312358
/**
313359
* Returns a new {@link AggregationOptions} instance with the given configuration.
314360
*
315361
* @return
316362
*/
317363
public AggregationOptions build() {
318-
return new AggregationOptions(allowDiskUse, explain, cursor, collation);
364+
return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
319365
}
320366
}
321367
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AggregationUtils.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,22 @@
3030
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
3131
import org.springframework.data.mongodb.core.convert.MongoConverter;
3232
import org.springframework.data.mongodb.core.query.Collation;
33+
import org.springframework.data.mongodb.core.query.Meta;
3334
import org.springframework.data.mongodb.core.query.Query;
3435
import org.springframework.data.mongodb.util.json.ParameterBindingContext;
3536
import org.springframework.data.mongodb.util.json.ParameterBindingDocumentCodec;
3637
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
3738
import org.springframework.expression.spel.standard.SpelExpressionParser;
3839
import org.springframework.lang.Nullable;
3940
import org.springframework.util.ClassUtils;
41+
import org.springframework.util.StringUtils;
4042

4143
/**
4244
* Internal utility class to help avoid duplicate code required in both the reactive and the sync {@link Aggregation}
4345
* support offered by repositories.
4446
*
4547
* @author Christoph Strobl
48+
* @author Mark Paluch
4649
* @since 2.2
4750
*/
4851
@UtilityClass
@@ -72,6 +75,27 @@ static AggregationOptions.Builder applyCollation(AggregationOptions.Builder buil
7275
return collation == null ? builder : builder.collation(collation);
7376
}
7477

78+
/**
79+
* Apply {@link Meta#getComment()} and {@link Meta#getCursorBatchSize()}.
80+
*
81+
* @param builder must not be {@literal null}.
82+
* @param queryMethod must not be {@literal null}.
83+
*/
84+
static AggregationOptions.Builder applyMeta(AggregationOptions.Builder builder, MongoQueryMethod queryMethod) {
85+
86+
Meta meta = queryMethod.getQueryMetaAttributes();
87+
88+
if (StringUtils.hasText(meta.getComment())) {
89+
builder.comment(meta.getComment());
90+
}
91+
92+
if (meta.getCursorBatchSize() != null) {
93+
builder.cursorBatchSize(meta.getCursorBatchSize());
94+
}
95+
96+
return builder;
97+
}
98+
7599
/**
76100
* Compute the {@link AggregationOperation aggregation} pipeline for the given {@link MongoQueryMethod}. The raw
77101
* {@link org.springframework.data.mongodb.repository.Aggregation#pipeline()} is parsed with a

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ReactiveStringBasedAggregation.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,13 @@ List<AggregationOperation> computePipeline(ConvertingParameterAccessor accessor)
115115

116116
private AggregationOptions computeOptions(MongoQueryMethod method, ConvertingParameterAccessor accessor) {
117117

118-
return AggregationUtils
119-
.applyCollation(Aggregation.newAggregationOptions(), method.getAnnotatedCollation(), accessor,
120-
method.getParameters(), expressionParser, evaluationContextProvider) //
121-
.build();
118+
AggregationOptions.Builder builder = Aggregation.newAggregationOptions();
119+
120+
AggregationUtils.applyCollation(builder, method.getAnnotatedCollation(), accessor, method.getParameters(),
121+
expressionParser, evaluationContextProvider);
122+
AggregationUtils.applyMeta(builder, method);
123+
124+
return builder.build();
122125
}
123126

124127
/*

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/StringBasedAggregation.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,13 @@ List<AggregationOperation> computePipeline(MongoQueryMethod method, ConvertingPa
125125

126126
private AggregationOptions computeOptions(MongoQueryMethod method, ConvertingParameterAccessor accessor) {
127127

128-
return AggregationUtils
129-
.applyCollation(Aggregation.newAggregationOptions(), method.getAnnotatedCollation(), accessor,
130-
method.getParameters(), expressionParser, evaluationContextProvider) //
131-
.build();
128+
AggregationOptions.Builder builder = Aggregation.newAggregationOptions();
129+
130+
AggregationUtils.applyCollation(builder, method.getAnnotatedCollation(), accessor, method.getParameters(),
131+
expressionParser, evaluationContextProvider);
132+
AggregationUtils.applyMeta(builder, method);
133+
134+
return builder.build();
132135
}
133136

134137
/*

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.springframework.data.geo.Point;
5656
import org.springframework.data.mongodb.MongoDbFactory;
5757
import org.springframework.data.mongodb.core.aggregation.Aggregation;
58+
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
5859
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
5960
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
6061
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
@@ -418,6 +419,16 @@ public void aggregateShouldIgnoreReadPreferenceWhenNotSet() {
418419
verify(collection, never()).withReadPreference(any());
419420
}
420421

422+
@Test // DATAMONGO-2153
423+
public void aggregateShouldHonorOptionsComment() {
424+
425+
AggregationOptions options = AggregationOptions.builder().comment("expensive").build();
426+
427+
template.aggregate(newAggregation(Aggregation.unwind("foo")).withOptions(options), "collection-1", Wrapper.class);
428+
429+
verify(aggregateIterable).comment("expensive");
430+
}
431+
421432
@Test // DATAMONGO-1166, DATAMONGO-2264
422433
public void geoNearShouldHonorReadPreferenceWhenSet() {
423434

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.beans.factory.annotation.Value;
4444
import org.springframework.data.annotation.Id;
4545
import org.springframework.data.mongodb.core.MongoTemplateUnitTests.AutogenerateableId;
46+
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
4647
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
4748
import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
4849
import org.springframework.data.mongodb.core.mapping.Field;
@@ -539,6 +540,17 @@ public void aggreateShouldUseCollationFromOptionsEvenIfDefaultCollationIsPresent
539540
verify(aggregatePublisher).collation(eq(com.mongodb.client.model.Collation.builder().locale("fr").build()));
540541
}
541542

543+
@Test // DATAMONGO-2153
544+
public void aggregateShouldHonorOptionsComment() {
545+
546+
AggregationOptions options = AggregationOptions.builder().comment("expensive").build();
547+
548+
template.aggregate(newAggregation(Sith.class, project("id")).withOptions(options), AutogenerateableId.class,
549+
Document.class).subscribe();
550+
551+
verify(aggregatePublisher).comment("expensive");
552+
}
553+
542554
@Test // DATAMONGO-18545
543555
public void findAndReplaceShouldUseCollationWhenPresent() {
544556

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationOptionsTests.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
*/
1616
package org.springframework.data.mongodb.core.aggregation;
1717

18-
import static org.hamcrest.CoreMatchers.*;
19-
import static org.junit.Assert.*;
18+
import static org.assertj.core.api.Assertions.*;
2019
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
2120

2221
import org.bson.Document;
@@ -40,36 +39,40 @@ public void setup() {
4039
aggregationOptions = newAggregationOptions().explain(true) //
4140
.cursorBatchSize(1) //
4241
.allowDiskUse(true) //
42+
.comment("hola!") //
4343
.build();
4444
}
4545

4646
@Test // DATAMONGO-960
4747
public void aggregationOptionsBuilderShouldSetOptionsAccordingly() {
4848

49-
assertThat(aggregationOptions.isAllowDiskUse(), is(true));
50-
assertThat(aggregationOptions.isExplain(), is(true));
51-
assertThat(aggregationOptions.getCursor().get(), is(new Document("batchSize", 1)));
49+
assertThat(aggregationOptions.isAllowDiskUse()).isTrue();
50+
assertThat(aggregationOptions.isExplain()).isTrue();
51+
assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1));
5252
}
5353

54-
@Test // DATAMONGO-1637
54+
@Test // DATAMONGO-1637, DATAMONGO-2153
5555
public void shouldInitializeFromDocument() {
5656

5757
Document document = new Document();
5858
document.put("cursor", new Document("batchSize", 1));
5959
document.put("explain", true);
6060
document.put("allowDiskUse", true);
61+
document.put("comment", "hola!");
6162

6263
aggregationOptions = AggregationOptions.fromDocument(document);
6364

64-
assertThat(aggregationOptions.isAllowDiskUse(), is(true));
65-
assertThat(aggregationOptions.isExplain(), is(true));
66-
assertThat(aggregationOptions.getCursor().get(), is(new Document("batchSize", 1)));
67-
assertThat(aggregationOptions.getCursorBatchSize(), is(1));
65+
assertThat(aggregationOptions.isAllowDiskUse()).isTrue();
66+
assertThat(aggregationOptions.isExplain()).isTrue();
67+
assertThat(aggregationOptions.getCursor().get()).isEqualTo(new Document("batchSize", 1));
68+
assertThat(aggregationOptions.getCursorBatchSize()).isEqualTo(1);
69+
assertThat(aggregationOptions.getComment().get()).isEqualTo("hola!");
6870
}
6971

70-
@Test // DATAMONGO-960
72+
@Test // DATAMONGO-960, DATAMONGO-2153
7173
public void aggregationOptionsToString() {
72-
assertThat(aggregationOptions.toDocument(),
73-
is(Document.parse("{ \"allowDiskUse\" : true , \"explain\" : true , \"cursor\" : { \"batchSize\" : 1}}")));
74+
75+
assertThat(aggregationOptions.toDocument()).isEqualTo(Document.parse(
76+
"{ \"allowDiskUse\" : true , \"explain\" : true , \"cursor\" : { \"batchSize\" : 1}, \"comment\": \"hola!\"}"));
7477
}
7578
}

0 commit comments

Comments
 (0)