use of org.springframework.data.mongodb.core.aggregation.AggregationOptions in project spring-data-mongodb by spring-projects.
the class ReactiveMongoTemplate method aggregate.
/**
* @param aggregation must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @param outputType must not be {@literal null}.
* @param context can be {@literal null} and will be defaulted to {@link Aggregation#DEFAULT_CONTEXT}.
* @return never {@literal null}.
*/
protected <O> Flux<O> aggregate(Aggregation aggregation, String collectionName, Class<O> outputType, @Nullable AggregationOperationContext context) {
Assert.notNull(aggregation, "Aggregation pipeline must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
Assert.notNull(outputType, "Output type must not be null!");
AggregationOperationContext rootContext = context == null ? Aggregation.DEFAULT_CONTEXT : context;
AggregationOptions options = aggregation.getOptions();
List<Document> pipeline = aggregation.toPipeline(rootContext);
Assert.isTrue(!options.isExplain(), "Cannot use explain option with streaming!");
Assert.isNull(options.getCursorBatchSize(), "Cannot use batchSize cursor option with streaming!");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Streaming aggregation: {} in collection {}", serializeToJsonSafely(pipeline), collectionName);
}
ReadDocumentCallback<O> readCallback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName);
return execute(collectionName, collection -> aggregateAndMap(collection, pipeline, options, readCallback));
}
use of org.springframework.data.mongodb.core.aggregation.AggregationOptions in project spring-data-mongodb by spring-projects.
the class MongoTemplate method doAggregate.
@SuppressWarnings("ConstantConditions")
protected <O> AggregationResults<O> doAggregate(Aggregation aggregation, String collectionName, Class<O> outputType, AggregationOperationContext context) {
ReadDocumentCallback<O> callback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName);
AggregationOptions options = aggregation.getOptions();
AggregationUtil aggregationUtil = new AggregationUtil(queryMapper, mappingContext);
if (options.isExplain()) {
Document command = aggregationUtil.createCommand(collectionName, aggregation, context);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Executing aggregation: %s", serializeToJsonSafely(command)));
}
Document commandResult = executeCommand(command);
return new AggregationResults<>(commandResult.get("results", new ArrayList<Document>(0)).stream().map(callback::doWith).collect(Collectors.toList()), commandResult);
}
List<Document> pipeline = aggregationUtil.createPipeline(aggregation, context);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Executing aggregation: %s in collection %s", serializeToJsonSafely(pipeline), collectionName));
}
return execute(collectionName, collection -> {
List<Document> rawResult = new ArrayList<>();
Class<?> domainType = aggregation instanceof TypedAggregation ? ((TypedAggregation<?>) aggregation).getInputType() : null;
Optional<Collation> collation = Optionals.firstNonEmpty(options::getCollation, () -> //
operations.forType(domainType).getCollation());
AggregateIterable<Document> aggregateIterable = //
collection.aggregate(pipeline, Document.class).collation(//
collation.map(Collation::toMongoCollation).orElse(null)).allowDiskUse(options.isAllowDiskUse());
if (options.getCursorBatchSize() != null) {
aggregateIterable = aggregateIterable.batchSize(options.getCursorBatchSize());
}
options.getComment().ifPresent(aggregateIterable::comment);
options.getHint().ifPresent(aggregateIterable::hint);
if (options.hasExecutionTimeLimit()) {
aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS);
}
if (options.isSkipResults()) {
// toCollection only allowed for $out and $merge if those are the last stages
if (aggregation.getPipeline().isOutOrMerge()) {
aggregateIterable.toCollection();
} else {
aggregateIterable.first();
}
return new AggregationResults<>(Collections.emptyList(), new Document());
}
MongoIterable<O> iterable = aggregateIterable.map(val -> {
rawResult.add(val);
return callback.doWith(val);
});
return new AggregationResults<>(iterable.into(new ArrayList<>()), new Document("results", rawResult).append("ok", 1.0D));
});
}
use of org.springframework.data.mongodb.core.aggregation.AggregationOptions in project spring-data-mongodb by spring-projects.
the class ReactiveMongoTemplate method doAggregate.
protected <O> Flux<O> doAggregate(Aggregation aggregation, String collectionName, @Nullable Class<?> inputType, Class<O> outputType) {
Assert.notNull(aggregation, "Aggregation pipeline must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
Assert.notNull(outputType, "Output type must not be null!");
AggregationOptions options = aggregation.getOptions();
Assert.isTrue(!options.isExplain(), "Cannot use explain option with streaming!");
AggregationDefinition ctx = queryOperations.createAggregation(aggregation, inputType);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Streaming aggregation: %s in collection %s", serializeToJsonSafely(ctx.getAggregationPipeline()), collectionName));
}
ReadDocumentCallback<O> readCallback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName);
return execute(collectionName, collection -> aggregateAndMap(collection, ctx.getAggregationPipeline(), ctx.isOutOrMerge(), options, readCallback, ctx.getInputType()));
}
use of org.springframework.data.mongodb.core.aggregation.AggregationOptions in project spring-data-mongodb by spring-projects.
the class ReactiveStringBasedAggregation method doExecute.
/*
* (non-Javascript)
* @see org.springframework.data.mongodb.repository.query.AbstractReactiveMongoQuery#doExecute(org.springframework.data.mongodb.repository.query.ReactiveMongoQueryMethod, org.springframework.data.repository.query.ResultProcessor, org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor, java.lang.Class)
*/
@Override
protected Publisher<Object> doExecute(ReactiveMongoQueryMethod method, ResultProcessor processor, ConvertingParameterAccessor accessor, Class<?> typeToRead) {
return computePipeline(accessor).flatMapMany(it -> {
Class<?> sourceType = method.getDomainClass();
Class<?> targetType = typeToRead;
List<AggregationOperation> pipeline = it;
AggregationUtils.appendSortIfPresent(pipeline, accessor, typeToRead);
AggregationUtils.appendLimitAndOffsetIfPresent(pipeline, accessor);
boolean isSimpleReturnType = isSimpleReturnType(typeToRead);
boolean isRawReturnType = ClassUtils.isAssignable(org.bson.Document.class, typeToRead);
if (isSimpleReturnType || isRawReturnType) {
targetType = Document.class;
}
AggregationOptions options = computeOptions(method, accessor);
TypedAggregation<?> aggregation = new TypedAggregation<>(sourceType, pipeline, options);
Flux<?> flux = reactiveMongoOperations.aggregate(aggregation, targetType);
if (isSimpleReturnType && !isRawReturnType) {
flux = flux.handle((item, sink) -> {
Object result = AggregationUtils.extractSimpleTypeResult((Document) item, typeToRead, mongoConverter);
if (result != null) {
sink.next(result);
}
});
}
return method.isCollectionQuery() ? flux : flux.next();
});
}
use of org.springframework.data.mongodb.core.aggregation.AggregationOptions in project spring-data-mongodb by spring-projects.
the class ReactiveStringBasedAggregationUnitTests method plainStringAggregationWithSortParameter.
// DATAMONGO-2153
@Test
public void plainStringAggregationWithSortParameter() {
AggregationInvocation invocation = executeAggregation("plainStringAggregation", Sort.by(Direction.DESC, "lastname"));
assertThat(inputTypeOf(invocation)).isEqualTo(Person.class);
assertThat(targetTypeOf(invocation)).isEqualTo(PersonAggregate.class);
assertThat(pipelineOf(invocation)).containsExactly(GROUP_BY_LASTNAME, SORT);
AggregationOptions options = invocation.aggregation.getOptions();
assertThat(options.getComment()).isEmpty();
assertThat(options.getCursorBatchSize()).isNull();
}
Aggregations