8

In the below query

{ $group : {
        _id :  { success:'$success', responseCode:'$responseCode', label:'$label'},
        max_timeStamp : { $timeStamp : 1 },
        count_responseCode : { $sum : 1 },
        avg_value : { $sum : "$value" },
        count_success : { $sum : 1 }
    }}

How _id : { success:'$success', responseCode:'$responseCode', label:'$label'}, can be translated to use in java mongodb driver.

I tried

BasicDBList list = new BasicDBList();
list.add(new BasicDBObject("success", "$success"));
list.add(new BasicDBObject("responseCode", "$responseCode"));
list.add(new BasicDBObject("label", "$label"));
AggregationOutput output = collection.aggregate(match, project, group); 

and

Multi-dimension array

String [][] muitiGroupBy = {{"success", "$success"},{"responseCode", "$responseCode"},{"label", "$label"}};

etc..

But i always get like this as result

"_id" : [ { "success" : "$success"} , { "responseCode" : "$responseCode"}]

If I use only one field it works.

DBObject groupFields = new BasicDBObject( "_id", new BasicDBObject("success", "$success"));

3 Answers 3

9

I had a similar need and titogeo's answer from 2013 led me in the right direction after many failed attempts to translate my aggregation operation into something the Java client could handle. This is what I used:

MongoCollection<Document> myCollection = myDB.getCollection("myCollection");

Map<String, Object> multiIdMap = new HashMap<String, Object>();
multiIdMap.put("groupField1", "$groupField1");
multiIdMap.put("groupField2", "$groupField2");

Document groupFields = new Document(multiIdMap);
AggregateIterable<Document> aggregate = myCollection.aggregate(Arrays.asList(
        Aggregates.group(groupFields,
                Accumulators.last("lastDate", "$dateCreated"),
                Accumulators.last("lastNumAvail", "$availableUnits")
                )
        ));

I got back exactly what I needed to match the result from this:

db.myCollection.aggregate([
            {"$group":{ "_id":{
                groupField1: "$groupField1", 
                groupField2: "$groupField2"}, 
                lastDate: 
                    {"$last":"$dateCreated"}, 
                lastNumAvail: 
                    {"$last":"$availableUnits"}
                }
               }                
            ]);
Sign up to request clarification or add additional context in comments.

2 Comments

You're a an absolute star for this answer, thank you! I've been upgrading an aging tech stack's MongoDB from 3.4 to 6.0 and all of our client code was written in GMongo format which needed to be replaced. I couldn't for the life of my figure out how to do multiple group fields in the Java Sync Driver API like this. I spent days looking for a solution until I happened your answer. Cheers!
@ionised, wow, thank you so much for the feedback. I'm real happy to have helped you out. Good luck with your stack upgrade!
6

We did figure out how. We can achieve by using this.

Map<String, Object> dbObjIdMap = new HashMap<String, Object>();
dbObjIdMap.put("success", "$success");
dbObjIdMap.put("responseCode", "$responseCode");
dbObjIdMap.put("label", "$label");
DBObject groupFields = new BasicDBObject( "_id", new BasicDBObject(dbObjIdMap));

Comments

0

I could achieve this through this code (grails code and mongo-java-driver-3.2):

DBObject groupFields = new BasicDBObject()
groupFields.put('success', "\$success")
groupFields.put('responseCode', "\$responseCode")
groupFields.put('label', "\$label")
def result = collection.aggregate(Arrays.asList(Aggregates.group(groupFields, []))).iterator()

1 Comment

With Java driver 3+ the Document class should be used instead of BasicDBObject.

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.