This project contains samples for using MongoDB Aggregations showing both the programmatic and declarative approach for integrating an Aggregation Pipeline into a repository.
The programmatic approach uses a custom repository implementation along with the Aggregation Framework.
class OrderRepositoryImpl implements OrderRepositoryCustom {
private MongoOperations operations;
// ...
@Override
public Invoice getInvoiceFor(Order order) {
AggregationResults<Invoice> results = operations.aggregate(newAggregation(Order.class,
match(where("id").is(order.getId())),
unwind("items"),
project("id", "customerId", "items")
.andExpression("'$items.price' * '$items.quantity'").as("lineTotal"),
group("id")
.sum("lineTotal").as("netAmount")
.addToSet("items").as("items"),
project("id", "items", "netAmount")
.and("orderId").previousOperation()
.andExpression("netAmount * [0]", taxRate).as("taxAmount")
.andExpression("netAmount * (1 + [0])", taxRate).as("totalAmount")
), Invoice.class);
return results.getUniqueMappedResult();
}
}
The declarative approach allows to define an Aggregation Pipeline via the @Aggregation
annotation.
public interface OrderRepository extends CrudRepository<Order, String>, OrderRepositoryCustom {
@Aggregation("{ $group : { _id : $customerId, total : { $sum : 1 } } }")
List<OrdersPerCustomer> totalOrdersPerCustomer(Sort sort);
@Aggregation(pipeline = { "{ $match : { customerId : ?0 } }", "{ $count : total }" })
Long totalOrdersForCustomer(String customerId);
}