DATAMONGO-2449 - Evaluate allowDiskUse added to Meta annotation when executing derived Aggregation.
@Meta(allowDiskUse...) allows to set the according aggregation option when executing a String based annotation via a repository definition. Original pull request: #827.
This commit is contained in:
committed by
Mark Paluch
parent
f8ee9648da
commit
85519eb84d
@@ -52,6 +52,7 @@ public class Meta {
|
||||
private final Map<String, Object> values = new LinkedHashMap<>(2);
|
||||
private final Set<CursorOption> flags = new LinkedHashSet<>();
|
||||
private Integer cursorBatchSize;
|
||||
private Boolean allowDiskUse;
|
||||
|
||||
public Meta() {}
|
||||
|
||||
@@ -65,6 +66,7 @@ public class Meta {
|
||||
this.values.putAll(source.values);
|
||||
this.flags.addAll(source.flags);
|
||||
this.cursorBatchSize = source.cursorBatchSize;
|
||||
this.allowDiskUse = source.allowDiskUse;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,6 +247,27 @@ public class Meta {
|
||||
return ObjectUtils.nullSafeEquals(this.flags, other.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* When set to true, aggregation stages can write data to disk.
|
||||
*
|
||||
* @return {@literal null} if not set.
|
||||
* @since 3.0
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getAllowDiskUse() {
|
||||
return allowDiskUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true, to allow aggregation stages to write data to disk.
|
||||
*
|
||||
* @param allowDiskUse use {@literal null} for server defaults.
|
||||
* @since 3.0
|
||||
*/
|
||||
public void setAllowDiskUse(@Nullable Boolean allowDiskUse) {
|
||||
this.allowDiskUse = allowDiskUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link CursorOption} represents {@code OP_QUERY} wire protocol flags to change the behavior of queries.
|
||||
*
|
||||
|
||||
@@ -67,4 +67,13 @@ public @interface Meta {
|
||||
*/
|
||||
org.springframework.data.mongodb.core.query.Meta.CursorOption[] flags() default {};
|
||||
|
||||
/**
|
||||
* When set to true, aggregation stages can write data to disk.
|
||||
*
|
||||
* @return {@literal false} by default.
|
||||
* @since 3.0
|
||||
* @see Aggregation
|
||||
*/
|
||||
boolean allowDiskUse() default false;
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -93,6 +94,14 @@ class AggregationUtils {
|
||||
builder.cursorBatchSize(meta.getCursorBatchSize());
|
||||
}
|
||||
|
||||
if(meta.getMaxTimeMsec() != null && meta.getMaxTimeMsec() > 0) {
|
||||
builder.maxTime(Duration.ofMillis(meta.getMaxTimeMsec()));
|
||||
}
|
||||
|
||||
if (meta.getAllowDiskUse() != null) {
|
||||
builder.allowDiskUse(meta.getAllowDiskUse());
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
@@ -293,6 +293,10 @@ public class MongoQueryMethod extends QueryMethod {
|
||||
}
|
||||
}
|
||||
|
||||
if(meta.allowDiskUse()) {
|
||||
metaAttributes.setAllowDiskUse(meta.allowDiskUse());
|
||||
}
|
||||
|
||||
return metaAttributes;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.*;
|
||||
import lombok.Value;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -33,7 +34,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
@@ -102,18 +102,19 @@ public class StringBasedAggregationUnitTests {
|
||||
assertThat(pipelineOf(invocation)).containsExactly(GROUP_BY_LASTNAME, SORT);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2153
|
||||
@Test // DATAMONGO-2153, DATAMONGO-2449
|
||||
public void plainStringAggregationConsidersMeta() {
|
||||
|
||||
AggregationInvocation invocation = executeAggregation("plainStringAggregation");
|
||||
|
||||
AggregationOptions options = invocation.aggregation.getOptions();
|
||||
|
||||
assertThat(options.getComment()).contains("expensive-aggregation");
|
||||
assertThat(options.getCursorBatchSize()).isEqualTo(42);
|
||||
assertThat(options.isAllowDiskUse()).isTrue();
|
||||
assertThat(options.getMaxTime()).isEqualTo(Duration.ofMillis(100));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2153
|
||||
@Test // DATAMONGO-2153, DATAMONGO-2449
|
||||
public void returnSingleObject() {
|
||||
|
||||
PersonAggregate expected = new PersonAggregate();
|
||||
@@ -126,6 +127,8 @@ public class StringBasedAggregationUnitTests {
|
||||
|
||||
assertThat(options.getComment()).isEmpty();
|
||||
assertThat(options.getCursorBatchSize()).isNull();
|
||||
assertThat(options.isAllowDiskUse()).isFalse();
|
||||
assertThat(options.getMaxTime()).isEqualTo(Duration.ZERO);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2153
|
||||
@@ -246,7 +249,7 @@ public class StringBasedAggregationUnitTests {
|
||||
|
||||
private interface SampleRepository extends Repository<Person, Long> {
|
||||
|
||||
@Meta(cursorBatchSize = 42, comment = "expensive-aggregation")
|
||||
@Meta(cursorBatchSize = 42, comment = "expensive-aggregation", allowDiskUse = true, maxExecutionTimeMs = 100)
|
||||
@Aggregation({ RAW_GROUP_BY_LASTNAME_STRING, RAW_SORT_STRING })
|
||||
PersonAggregate plainStringAggregation();
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ The definition may contain simple placeholders like `?0` as well as https://docs
|
||||
----
|
||||
public interface PersonRepository extends CrudReppsitory<Person, String> {
|
||||
|
||||
|
||||
@Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }")
|
||||
List<PersonAggregate> groupByLastnameAndFirstnames(); <1>
|
||||
|
||||
@@ -74,6 +73,36 @@ To gain more control, you might consider `AggregationResult` as method return ty
|
||||
<8> Like in <6>, a single value can be directly obtained from multiple result ``Document``s.
|
||||
====
|
||||
|
||||
In some scenarios aggregations might require additional options like a maximum execution time, additional log comments or the permission to temporarily write data to disk.
|
||||
Use the `@Meta` annotation to set those options via `maxExecutionTimeMs`, `comment` or `allowDiskUse`.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public interface PersonRepository extends CrudReppsitory<Person, String> {
|
||||
|
||||
@Meta(allowDiskUse = true)
|
||||
@Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }")
|
||||
List<PersonAggregate> groupByLastnameAndFirstnames();
|
||||
}
|
||||
----
|
||||
|
||||
Or use `@Meta` to create your own annotation as shown in the sample below.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD })
|
||||
@Meta(allowDiskUse = true)
|
||||
@interface AllowDiskUse { }
|
||||
|
||||
public interface PersonRepository extends CrudReppsitory<Person, String> {
|
||||
|
||||
@AllowDiskUse
|
||||
@Aggregation("{ $group: { _id : $lastname, names : { $addToSet : $firstname } } }")
|
||||
List<PersonAggregate> groupByLastnameAndFirstnames();
|
||||
}
|
||||
----
|
||||
|
||||
TIP: You can use `@Aggregation` also with <<mongo.reactive.repositories, Reactive Repositories>>.
|
||||
|
||||
[NOTE]
|
||||
|
||||
Reference in New Issue
Block a user