首页 > 解决方案 > 改进聚合查询以获得不同的结果

问题描述

我有这个聚合查询,它返回Operation字段amount:BigDecimal高于minAmount并在日期范围内的对象。我只想获得不同的结果(每个Operation对象都有一个operationId:String),基于operationId.

我在这里找到了一个相关的例子,但它并没有帮助我解决我的问题:Get sorted distinct values with MongoTemplate

我了解addToSet, orgroup可以使用,但我不清楚如何将它准确地合并到查询的其余部分中

    private List<OperationDataVO> getInfoFromDB(BigDecimal minAmount,
                                                     Instant startDate, Instant endDate) {
        Criteria criterias = new Criteria()
            .andOperator(Criteria.where(WinningOperation.AMOUNT)
                    .gte(minAmount)
                    .and(Operation.TYPE).is(OperationTypeEnum.WINNING_TYPE)
                    .and("createdAt").gte(startDate).lte(endDate));

        MatchOperation matchOperation = Aggregation.match(criterias);

        ProjectionOperation projectionOperation = 
                Aggregation.project("amount", "operationId");

        Aggregation aggregation = Aggregation.newAggregation(matchOperation,
                projectionOperation, sort(direction, "amount"));

        AggregationResults<OperationDataVO> aggregate = mongoTemplate
                .aggregate(aggregation, COLLECTION, OperationDataVO.class);

        return aggregate.getMappedResults();
    }

另外,我尝试在Aggregation管道中添加组操作,但是当我这样做时,我会得到OperationDataVO每个对象的两个字段所在的列表null

( Aggregation aggregation = Aggregation.newAggregation(matchOperation, projectionOperation, sort(direction, "amount"), group("operationId")); )

标签: javamongodbaggregation-frameworkprojectionmongotemplate

解决方案


amount在进行分组之前,您需要按降序排序。应该使用“$first”累加器进行分组。我们使用$$ROOT. 然后,您可以将根文档替换为组中的文档。

分组不会保留任何顺序,因为您希望对最终结果进行排序,您需要再次排序。

实现此目的的 mongo shell 代码如下所示:

db.getCollection('operationData').aggregate([
{ $match: ... } ,
{ $project: { amount: 1, operationId: 1 } },
{ $sort: { amount: -1 } },
{ $group: { _id: '$operationId', g: { $first: {data: '$$ROOT'} }} },
{ $replaceRoot: { newRoot: '$g.data' }},
{ $sort: { amount: 1 } }
])

这需要翻译成 Spring Data Mongo(也许我以后有时间自己尝试一下)。


推荐阅读