4

Do anyone know how to convert the below aggregation function into a java code using Spring-data?

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]}
                          }

        }
    }
]);

1 Answer 1

6

Spring mongo does not currently support either:

  1. A composite aggregation _id with custom key names, though of course you could just accept the defualt field name translation

  2. Usage of the $cond operation or any expression within a $sum, as it just supports a mapped field only.

So the second there is the thing that breaks usage of the aggregation helper functions in this case. You could work around that by doing a $project first, but that requires an additional stage of execution that will affect the performance.

But what you can do is create your own abstract class that works within the standard builder functions but allows you to build the pipeline stage with standard objects:

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);
    }
}

And then you can use it with the standard builder as follows:

    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
                                ))
                            )
                        )
                    )
            )
    );

And that builds a pipeline with the $group stage exactly as you have it defined.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome., It works. Thanks @Blakes for the quick solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.