DATAMONGO-960 - Allow to pass options to the Aggregation Pipeline.
We introduced AggregationOptions abstraction to conveniently construct option objects that can be handed to an Aggregation via the new Aggregation.withOptions(...) factory method. For more details, see the Builder class' JavaDoc. Note that we exposed the "rawResults" in AggregationResults and put a null guard in MongoTemplate aggregate in order to support the "explain" option. Original pull request: #195.
This commit is contained in:
committed by
Oliver Gierke
parent
1fb76d135b
commit
9858dcd740
@@ -1413,17 +1413,32 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
CommandResult commandResult = executeCommand(command);
|
||||
handleCommandError(commandResult, command);
|
||||
|
||||
// map results
|
||||
return new AggregationResults<O>(returnPotentiallyMappedResults(outputType, commandResult), commandResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the potentially mapped results of the given {@commandResult} contained some.
|
||||
*
|
||||
* @param outputType
|
||||
* @param commandResult
|
||||
* @return
|
||||
*/
|
||||
private <O> List<O> returnPotentiallyMappedResults(Class<O> outputType, CommandResult commandResult) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterable<DBObject> resultSet = (Iterable<DBObject>) commandResult.get("result");
|
||||
List<O> mappedResults = new ArrayList<O>();
|
||||
if (resultSet == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
DbObjectCallback<O> callback = new UnwrapAndReadDbObjectCallback<O>(mongoConverter, outputType);
|
||||
|
||||
List<O> mappedResults = new ArrayList<O>();
|
||||
for (DBObject dbObject : resultSet) {
|
||||
mappedResults.add(callback.doWith(dbObject));
|
||||
}
|
||||
|
||||
return new AggregationResults<O>(mappedResults, commandResult);
|
||||
return mappedResults;
|
||||
}
|
||||
|
||||
protected String replaceWithResourceIfNecessary(String function) {
|
||||
|
||||
@@ -45,8 +45,11 @@ import com.mongodb.DBObject;
|
||||
public class Aggregation {
|
||||
|
||||
public static final AggregationOperationContext DEFAULT_CONTEXT = new NoOpAggregationOperationContext();
|
||||
public static final AggregationOptions DEFAULT_OPTIONS = newAggregationOptions().build();
|
||||
|
||||
private final List<AggregationOperation> operations;
|
||||
protected final List<AggregationOperation> operations;
|
||||
|
||||
private final AggregationOptions options;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||
@@ -66,6 +69,20 @@ public class Aggregation {
|
||||
return new Aggregation(operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this {@link Aggregation} with the given {@link AggregationOptions} set. Note that options are
|
||||
* supported in MongoDB version 2.6+.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
public Aggregation withOptions(AggregationOptions options) {
|
||||
|
||||
Assert.notNull(options, "AggregationOptions must not be null.");
|
||||
return new Aggregation(this.operations, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TypedAggregation} for the given type and {@link AggregationOperation}s.
|
||||
*
|
||||
@@ -92,11 +109,43 @@ public class Aggregation {
|
||||
* @param aggregationOperations must not be {@literal null} or empty.
|
||||
*/
|
||||
protected Aggregation(AggregationOperation... aggregationOperations) {
|
||||
this(asAggregationList(aggregationOperations));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aggregationOperations must not be {@literal null} or empty.
|
||||
* @return
|
||||
*/
|
||||
protected static List<AggregationOperation> asAggregationList(AggregationOperation... aggregationOperations) {
|
||||
|
||||
Assert.notEmpty(aggregationOperations, "AggregationOperations must not be null or empty!");
|
||||
|
||||
return Arrays.asList(aggregationOperations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||
*
|
||||
* @param aggregationOperations must not be {@literal null} or empty.
|
||||
*/
|
||||
protected Aggregation(List<AggregationOperation> aggregationOperations) {
|
||||
this(aggregationOperations, DEFAULT_OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
|
||||
*
|
||||
* @param aggregationOperations must not be {@literal null} or empty.
|
||||
* @param options must not be {@literal null} or empty.
|
||||
*/
|
||||
protected Aggregation(List<AggregationOperation> aggregationOperations, AggregationOptions options) {
|
||||
|
||||
Assert.notNull(aggregationOperations, "AggregationOperations must not be null!");
|
||||
Assert.isTrue(aggregationOperations.length > 0, "At least one AggregationOperation has to be provided");
|
||||
Assert.isTrue(aggregationOperations.size() > 0, "At least one AggregationOperation has to be provided");
|
||||
Assert.notNull(options, "AggregationOptions must not be null!");
|
||||
|
||||
this.operations = Arrays.asList(aggregationOperations);
|
||||
this.operations = aggregationOperations;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,6 +280,16 @@ public class Aggregation {
|
||||
return Fields.from(field(name, target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link AggregationOptions.Builder}.
|
||||
*
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
public static AggregationOptions.Builder newAggregationOptions() {
|
||||
return new AggregationOptions.Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this {@link Aggregation} specification to a {@link DBObject}.
|
||||
*
|
||||
@@ -255,6 +314,8 @@ public class Aggregation {
|
||||
DBObject command = new BasicDBObject("aggregate", inputCollectionName);
|
||||
command.put("pipeline", operationDocuments);
|
||||
|
||||
command = options.applyAndReturnPotentiallyChangedCommand(command);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Holds a set of configurable aggregation options that can be used within an aggregation pipeline. A list of support
|
||||
* aggregation options can be found in the MongoDB reference documentation
|
||||
* http://docs.mongodb.org/manual/reference/command/aggregate/#aggregate
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @see Aggregation#withOptions(AggregationOptions)
|
||||
* @see TypedAggregation#withOptions(AggregationOptions)
|
||||
* @since 1.6
|
||||
*/
|
||||
public class AggregationOptions {
|
||||
|
||||
private static final String CURSOR = "cursor";
|
||||
private static final String EXPLAIN = "explain";
|
||||
private static final String ALLOW_DISK_USE = "allowDiskUse";
|
||||
|
||||
private final boolean allowDiskUse;
|
||||
private final boolean explain;
|
||||
private final DBObject cursor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AggregationOptions}.
|
||||
*
|
||||
* @param allowDiskUse whether to off-load intensive sort-operations to disk.
|
||||
* @param explain whether to get the execution plan for the aggregation instead of the actual results.
|
||||
* @param cursor can be {@literal null}, used to pass additional options to the aggregation.
|
||||
*/
|
||||
public AggregationOptions(boolean allowDiskUse, boolean explain, DBObject cursor) {
|
||||
|
||||
this.allowDiskUse = allowDiskUse;
|
||||
this.explain = explain;
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables writing to temporary files. When set to true, aggregation stages can write data to the _tmp subdirectory in
|
||||
* the dbPath directory.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isAllowDiskUse() {
|
||||
return allowDiskUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies to return the information on the processing of the pipeline.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isExplain() {
|
||||
return explain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a document that contains options that control the creation of the cursor object.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DBObject getCursor() {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potentially adjusted copy for the given {@code aggregationCommandObject} with the configuration
|
||||
* applied.
|
||||
*
|
||||
* @param command the aggregation command.
|
||||
* @return
|
||||
*/
|
||||
DBObject applyAndReturnPotentiallyChangedCommand(DBObject command) {
|
||||
|
||||
DBObject result = new BasicDBObject(command.toMap());
|
||||
|
||||
if (allowDiskUse && !result.containsField(ALLOW_DISK_USE)) {
|
||||
result.put(ALLOW_DISK_USE, allowDiskUse);
|
||||
}
|
||||
|
||||
if (explain && !result.containsField(EXPLAIN)) {
|
||||
result.put(EXPLAIN, explain);
|
||||
}
|
||||
|
||||
if (cursor != null && !result.containsField(CURSOR)) {
|
||||
result.put("cursor", cursor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DBObject} representation of this {@link AggregationOptions}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DBObject toDbObject() {
|
||||
|
||||
DBObject dbo = new BasicDBObject();
|
||||
dbo.put(ALLOW_DISK_USE, allowDiskUse);
|
||||
dbo.put(EXPLAIN, explain);
|
||||
dbo.put(CURSOR, cursor);
|
||||
|
||||
return dbo;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return toDbObject().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Builder for {@link AggregationOptions}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private boolean allowDiskUse;
|
||||
private boolean explain;
|
||||
private DBObject cursor;
|
||||
|
||||
/**
|
||||
* Defines whether to off-load intensive sort-operations to disk.
|
||||
*
|
||||
* @param allowDiskUse
|
||||
* @return
|
||||
*/
|
||||
public Builder allowDiskUse(boolean allowDiskUse) {
|
||||
|
||||
this.allowDiskUse = allowDiskUse;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines whether to get the execution plan for the aggregation instead of the actual results.
|
||||
*
|
||||
* @param explain
|
||||
* @return
|
||||
*/
|
||||
public Builder explain(boolean explain) {
|
||||
|
||||
this.explain = explain;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional options to the aggregation.
|
||||
*
|
||||
* @param cursor
|
||||
* @return
|
||||
*/
|
||||
public Builder cursor(DBObject cursor) {
|
||||
|
||||
this.cursor = cursor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link AggregationOptions} instance with the given configuration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public AggregationOptions build() {
|
||||
return new AggregationOptions(allowDiskUse, explain, cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import com.mongodb.DBObject;
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @param <T> The class in which the results are mapped onto.
|
||||
* @since 1.3
|
||||
*/
|
||||
@@ -90,6 +91,16 @@ public class AggregationResults<T> implements Iterable<T> {
|
||||
return serverUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw result that was returned by the server.
|
||||
*
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
public DBObject getRawResults() {
|
||||
return rawResults;
|
||||
}
|
||||
|
||||
private String parseServerUsed() {
|
||||
|
||||
Object object = rawResults.get("serverUsed");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -30,11 +32,34 @@ public class TypedAggregation<I> extends Aggregation {
|
||||
/**
|
||||
* Creates a new {@link TypedAggregation} from the given {@link AggregationOperation}s.
|
||||
*
|
||||
* @param inputType must not be {@literal null}.
|
||||
* @param operations must not be {@literal null} or empty.
|
||||
*/
|
||||
public TypedAggregation(Class<I> inputType, AggregationOperation... operations) {
|
||||
this(inputType, asAggregationList(operations));
|
||||
}
|
||||
|
||||
super(operations);
|
||||
/**
|
||||
* Creates a new {@link TypedAggregation} from the given {@link AggregationOperation}s.
|
||||
*
|
||||
* @param inputType must not be {@literal null}.
|
||||
* @param operations must not be {@literal null} or empty.
|
||||
*/
|
||||
public TypedAggregation(Class<I> inputType, List<AggregationOperation> operations) {
|
||||
this(inputType, operations, DEFAULT_OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TypedAggregation} from the given {@link AggregationOperation}s and the given
|
||||
* {@link AggregationOptions}.
|
||||
*
|
||||
* @param inputType must not be {@literal null}.
|
||||
* @param operations must not be {@literal null} or empty.
|
||||
* @param options must not be {@literal null}.
|
||||
*/
|
||||
public TypedAggregation(Class<I> inputType, List<AggregationOperation> operations, AggregationOptions options) {
|
||||
|
||||
super(operations, options);
|
||||
|
||||
Assert.notNull(inputType, "Input type must not be null!");
|
||||
this.inputType = inputType;
|
||||
@@ -48,4 +73,14 @@ public class TypedAggregation<I> extends Aggregation {
|
||||
public Class<I> getInputType() {
|
||||
return inputType;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.aggregation.Aggregation#withOptions(org.springframework.data.mongodb.core.aggregation.AggregationOptions)
|
||||
*/
|
||||
public TypedAggregation<I> withOptions(AggregationOptions options) {
|
||||
|
||||
Assert.notNull(options, "AggregationOptions must not be null.");
|
||||
return new TypedAggregation<I>(inputType, operations, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AggregationOptions}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @since 1.6
|
||||
*/
|
||||
public class AggregationOptionsTests {
|
||||
|
||||
AggregationOptions aggregationOptions;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
aggregationOptions = newAggregationOptions().explain(true).cursor(new BasicDBObject("foo", 1)).allowDiskUse(true)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void aggregationOptionsBuilderShouldSetOptionsAccordingly() {
|
||||
|
||||
assertThat(aggregationOptions.isAllowDiskUse(), is(true));
|
||||
assertThat(aggregationOptions.isExplain(), is(true));
|
||||
assertThat(aggregationOptions.getCursor(), is((DBObject) new BasicDBObject("foo", 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void aggregationOptionsToString() {
|
||||
assertThat(aggregationOptions.toString(),
|
||||
is("{ \"allowDiskUse\" : true , \"explain\" : true , \"cursor\" : { \"foo\" : 1}}"));
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,7 @@ public class AggregationTests {
|
||||
private static final String INPUT_COLLECTION = "aggregation_test_collection";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AggregationTests.class);
|
||||
private static final Version TWO_DOT_FOUR = new Version(2, 4);
|
||||
private static final Version TWO_DOT_SIX = new Version(2, 6);
|
||||
|
||||
private static boolean initialized = false;
|
||||
|
||||
@@ -414,23 +415,7 @@ public class AggregationTests {
|
||||
|
||||
createUserWithLikesDocuments();
|
||||
|
||||
/*
|
||||
...
|
||||
$group: {
|
||||
_id:"$like",
|
||||
number:{ $sum:1}
|
||||
}
|
||||
...
|
||||
|
||||
*/
|
||||
|
||||
TypedAggregation<UserWithLikes> agg = newAggregation(UserWithLikes.class, //
|
||||
unwind("likes"), //
|
||||
group("likes").count().as("number"), //
|
||||
sort(DESC, "number"), //
|
||||
limit(5), //
|
||||
sort(ASC, previousOperation()) //
|
||||
);
|
||||
TypedAggregation<UserWithLikes> agg = createUsersWithCommonLikesAggregation();
|
||||
|
||||
assertThat(agg, is(notNullValue()));
|
||||
assertThat(agg.toString(), is(notNullValue()));
|
||||
@@ -447,6 +432,16 @@ public class AggregationTests {
|
||||
assertLikeStats(result.getMappedResults().get(4), "e", 3);
|
||||
}
|
||||
|
||||
protected TypedAggregation<UserWithLikes> createUsersWithCommonLikesAggregation() {
|
||||
return newAggregation(UserWithLikes.class, //
|
||||
unwind("likes"), //
|
||||
group("likes").count().as("number"), //
|
||||
sort(DESC, "number"), //
|
||||
limit(5), //
|
||||
sort(ASC, previousOperation()) //
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arithmenticOperatorsInProjectionExample() {
|
||||
|
||||
@@ -857,6 +852,57 @@ public class AggregationTests {
|
||||
assertThat(result.getMappedResults(), hasSize(3));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabled() {
|
||||
|
||||
assumeTrue(mongoVersion.isGreaterThanOrEqualTo(TWO_DOT_SIX));
|
||||
|
||||
createUserWithLikesDocuments();
|
||||
|
||||
TypedAggregation<UserWithLikes> agg = createUsersWithCommonLikesAggregation() //
|
||||
.withOptions(newAggregationOptions().allowDiskUse(true).build());
|
||||
|
||||
assertThat(agg, is(notNullValue()));
|
||||
assertThat(agg.toString(), is(notNullValue()));
|
||||
|
||||
AggregationResults<LikeStats> result = mongoTemplate.aggregate(agg, LikeStats.class);
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result.getMappedResults(), is(notNullValue()));
|
||||
assertThat(result.getMappedResults().size(), is(5));
|
||||
|
||||
assertLikeStats(result.getMappedResults().get(0), "a", 4);
|
||||
assertLikeStats(result.getMappedResults().get(1), "b", 2);
|
||||
assertLikeStats(result.getMappedResults().get(2), "c", 4);
|
||||
assertLikeStats(result.getMappedResults().get(3), "d", 2);
|
||||
assertLikeStats(result.getMappedResults().get(4), "e", 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithExplainOptionEnabled() {
|
||||
|
||||
assumeTrue(mongoVersion.isGreaterThanOrEqualTo(TWO_DOT_SIX));
|
||||
|
||||
createUserWithLikesDocuments();
|
||||
|
||||
TypedAggregation<UserWithLikes> agg = createUsersWithCommonLikesAggregation() //
|
||||
.withOptions(newAggregationOptions().explain(true).build());
|
||||
|
||||
AggregationResults<LikeStats> result = mongoTemplate.aggregate(agg, LikeStats.class);
|
||||
|
||||
assertThat(result.getMappedResults(), is(empty()));
|
||||
|
||||
DBObject rawResult = result.getRawResults();
|
||||
|
||||
assertThat(rawResult, is(notNullValue()));
|
||||
assertThat(rawResult.containsField("stages"), is(true));
|
||||
}
|
||||
|
||||
private void assertLikeStats(LikeStats like, String id, long count) {
|
||||
|
||||
assertThat(like, is(notNullValue()));
|
||||
|
||||
@@ -219,6 +219,43 @@ public class AggregationUnitTests {
|
||||
assertThat(projection1, is((DBObject) new BasicDBObject("b", "$ba")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void shouldRenderAggregationWithDefaultOptionsCorrectly() {
|
||||
|
||||
DBObject agg = newAggregation( //
|
||||
project().and("a").as("aa") //
|
||||
).toDbObject("foo", Aggregation.DEFAULT_CONTEXT);
|
||||
|
||||
assertThat(agg.toString(),
|
||||
is("{ \"aggregate\" : \"foo\" , \"pipeline\" : [ { \"$project\" : { \"aa\" : \"$a\"}}]}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void shouldRenderAggregationWithCustomOptionsCorrectly() {
|
||||
|
||||
AggregationOptions aggregationOptions = newAggregationOptions().explain(true).cursor(new BasicDBObject("foo", 1))
|
||||
.allowDiskUse(true).build();
|
||||
|
||||
DBObject agg = newAggregation( //
|
||||
project().and("a").as("aa") //
|
||||
) //
|
||||
.withOptions(aggregationOptions) //
|
||||
.toDbObject("foo", Aggregation.DEFAULT_CONTEXT);
|
||||
|
||||
assertThat(agg.toString(), is("{ \"aggregate\" : \"foo\" , " //
|
||||
+ "\"pipeline\" : [ { \"$project\" : { \"aa\" : \"$a\"}}] , " //
|
||||
+ "\"allowDiskUse\" : true , " //
|
||||
+ "\"explain\" : true , " //
|
||||
+ "\"cursor\" : { \"foo\" : 1}}" //
|
||||
));
|
||||
}
|
||||
|
||||
private DBObject extractPipelineElement(DBObject agg, int index, String operation) {
|
||||
|
||||
List<DBObject> pipeline = (List<DBObject>) agg.get("pipeline");
|
||||
|
||||
@@ -146,6 +146,29 @@ public class TypeBasedAggregationOperationContextUnitTests {
|
||||
assertThat(age, is((DBObject) new BasicDBObject("v", 10)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-960
|
||||
*/
|
||||
@Test
|
||||
public void rendersAggregationOptionsInTypedAggregationContextCorrectly() {
|
||||
|
||||
AggregationOperationContext context = getContext(FooPerson.class);
|
||||
TypedAggregation<FooPerson> agg = newAggregation(FooPerson.class, project("name", "age")) //
|
||||
.withOptions(
|
||||
newAggregationOptions().allowDiskUse(true).explain(true).cursor(new BasicDBObject("foo", 1)).build());
|
||||
|
||||
DBObject dbo = agg.toDbObject("person", context);
|
||||
|
||||
DBObject projection = getPipelineElementFromAggregationAt(dbo, 0);
|
||||
assertThat(projection.containsField("$project"), is(true));
|
||||
|
||||
assertThat(projection.get("$project"), is((Object) new BasicDBObject("name", 1).append("age", 1)));
|
||||
|
||||
assertThat(dbo.get("allowDiskUse"), is((Object) true));
|
||||
assertThat(dbo.get("explain"), is((Object) true));
|
||||
assertThat(dbo.get("cursor"), is((Object) new BasicDBObject("foo", 1)));
|
||||
}
|
||||
|
||||
@Document(collection = "person")
|
||||
public static class FooPerson {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user