Spring 数据 MongoDB - 聚合方法

Spring Data MongoDB - Aggregate Method

有人知道如何使用 Spring-data 将以下聚合函数转换为 java 代码吗?

db.myCollection.aggregate([
    {$match:{"status" : {$in:["WORKING","UNASSIGNED"]}}},
    {$group:{
            _id:{
                "status":"$status",
                "queue":"$queueName"
             },
             "count":{$sum:1},
             "oldest":{$min:"$queueTime"},
             "slow":{$sum:{$cond:[
                                {$lte: ["$queueServiceTs", new Date()]},
                                        1,
                                        0]}
                          }

        }
    }
]);

Spring mongo 目前不支持:

  1. 具有自定义键名称的复合聚合_id,当然您可以只接受默认字段名称翻译

  2. 使用 $cond operation or any expression within a $sum,因为它仅支持映射字段。

因此,在这种情况下,第二个问题会破坏聚合辅助函数的使用。您可以先执行 $project 来解决这个问题,但这需要额外的执行阶段,这会影响性能。

但是您可以创建自己的抽象 class,它在标准构建器函数中工作,但允许您使用标准对象构建管道阶段:

public class CustomGroupOperation implements AggregationOperation {
    private DBObject operation;

    public CustomGroupOperation (DBObject operation) {
        this.operation = operation;
    }

    @Override
    public DBObject toDBObject(AggregationOperationContext context) {
        return context.getMappedObject(operation);
    }
}

然后您可以将它与标准生成器一起使用,如下所示:

    Aggregation aggregation = newAggregation(
            new CustomGroupOperation(
                    new BasicDBObject("$group",
                        new BasicDBObject("_id",
                            new BasicDBObject("status","$status")
                                .append("queue","$queueName")
                        )
                        .append("count",new BasicDBObject("$sum",1))
                        .append("oldest", new BasicDBObject("$min","$queueTime"))
                        .append("slow",
                            new BasicDBObject("$sum",
                                new BasicDBObject("$cond",Arrays.asList(
                                    new BasicDBObject("$lte",Arrays.asList(
                                        "$queueServiceTs",
                                        new Date()
                                    )),
                                    1,
                                    0
                                ))
                            )
                        )
                    )
            )
    );

这会完全按照您定义的方式构建具有 $group 阶段的管道。