0

I know this question has been asked a million times before here, but I cannot find anything matching my use case. Probably due to lack of knowledge of the Spring Mongo aggregation framework. I hope someone can shed some light on the subject for me.

Mongo shell aggregation

db.mongoAuditEvent.aggregate([ 
    {$group: {_id : "$corrId", currentEvent: {"$last": "$event.status"}, events: { $push: "$$ROOT"} }}, 
    {$sort: {"timestamp": 1} }, 
    {$skip: 0 }, 
    {$limit: 10}
], {allowDiskUse: true}).pretty()

Produces

{
  "_id" : "00aa9c60-2950-439b-976e-0980da829981",
  "currentEvent" : "UPSTREAM_QUEUE",
  "events" : [
    {
      "_id" : "e746cd3f-dfe3-47b3-a1d0-3342adaf61c3",
      "_class" : "no.fint.audit.plugin.mongo.MongoAuditEvent",
      "corrId" : "00aa9c60-2950-439b-976e-0980da829981",
      "source" : "employee",
      "timestamp" : NumberLong("1484478431288"),
      "event" : {
        "corrId" : "00aa9c60-2950-439b-976e-0980da829981",
        "action" : "GET_ALL_EMPLOYEES",
        "status" : "DOWNSTREAM_QUEUE",
        "time" : NumberLong("1484478431287"),
        "source" : "employee",
        "client" : "CACHE_SERVICE"
      },
      "clearData" : true
    }
  ]
}

I managed to translate this to the following in Spring:

public List<DBObject> getAllAuditEvents(Integer page, Integer pageSize) {
    List<DBObject> agg = new ArrayList();
    agg.add(BasicDBObject.parse("{$group: {_id: \"$corrId\", currentEvent: {\"$last\": \"$event.status\"}, events: { $push: \"$$ROOT\"} }}"));
    agg.add(BasicDBObject.parse("{$sort: {\"timestamp\": -1} }"));
    agg.add(BasicDBObject.parse("{$limit: " + pageSize + "}"));
    agg.add(BasicDBObject.parse("{$skip: " + (page * pageSize) + " }"));
    return (List<DBObject>) mongoTemplate.getCollection("mongoAuditEvent")
        .aggregate(agg).results();
}

But this fails because I have not specified the allowDiskUse:true option anywhere, and I cannot seem to find the right place to specify it.

Then I saw that there's a more preferred way of specifying aggregations:

public List<MongoAuditEventGroup> getAllAuditEvents(Integer page, Integer pageSize) {
    return mongoTemplate.aggregate(
        Aggregation.newAggregation(
            Aggregation.group("corrId"),
            Aggregation.sort(Sort.Direction.DESC, "corrId"),
            Aggregation.limit(pageSize),
            Aggregation.skip((long)page * pageSize)
        ).withOptions(newAggregationOptions().allowDiskUse(true).build()),
            MongoAuditEvent.class, 
            MongoAuditEventGroup.class).getMappedResults();
}

But I cannot seem to wrap my head around how to add the currentEvent to the group.

I would be very grateful for any help or pointers anybody could give me here.

1 Answer 1

1

I'm going off your Mongo Shell Query. You can try something like this.

import static org.springframework.data.domain.Sort.Direction.ASC;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;

Aggregation agg = newAggregation(
                group("corrId").last("event.status").as("currentEvent").push("$$ROOT").as("events"),
                sort(ASC, "timestamp"),
                skip(0L),
                limit(10L)).
                withOptions(newAggregationOptions().allowDiskUse(true).build());

List<MongoAuditEventGroup> results =  mongoTemplate.aggregate(agg, MongoAuditEvent.class, 
        MongoAuditEventGroup.class).getMappedResults();
Sign up to request clarification or add additional context in comments.

2 Comments

That worked. :-) Thank you! But this leaves me with the issue of No serializer found for my output class. What am I missing here?
Nevermind. Forgot getters/setters on the properties of the output class. Again, thank you!

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.