5

All of the methods have being deprecated but I havn't been able to find the replacement class for aggregation with the java driver.

user2312688
  • 521
  • 7
  • 17

5 Answers5

3

Thanks to evanchooly answer, here is what to do.
Replace:

 AggregationOutput output = collection.aggregate(pipe);
 for (DBObject obj : output.results()) {
     //...
 }

by

  // this build of options is taken from the original method
  // aggregate(pipe) to have same behaviour
  AggregationOptions options = AggregationOptions.builder()
            .outputMode(AggregationOptions.OutputMode.INLINE)
            .build();

  Cursor cursor = collection.aggregate(pipe,options); 
  while (cursor.hasNext() ) {
      DBObject obj = cursor.next();
      //...
  }
JR Utily
  • 1,792
  • 1
  • 23
  • 38
  • 1
    .outputMode(AggregationOptions.OutputMode.INLINE) is also deprecated. – viveknaskar May 30 '19 at 10:38
  • I'm not working with MongoDB any more, it was 4 years ago ;) Feel free to give a more up-to-date answer if this one is now deprecated ! – JR Utily Jun 03 '19 at 14:43
  • 1
    seems right, this is deprecated :( http://mongodb.github.io/mongo-java-driver/3.10/javadoc/com/mongodb/AggregationOptions.Builder.html – JR Utily Jun 03 '19 at 14:50
3

I was also facing the same issues and after scanning the MongoAPI docs, I got confused even more, but found an alternative for AggregationOutput class after going through various sites and documentation and some experimentation.

Initial Code

List<DBObject> studentAggregationQuery = new ArrayList<>();
studentAggregationQuery.add(new BasicDBObject("$roll", roll));
studentAggregationQuery.add(new BasicDBObject("$marks", marks));

AggregationOutput studentOutput = collection.aggregate(studentAggregationQuery);

List<StudentData> studentDataList = new ArrayList<>();
studentOutput.results().forEach(dbObject -> {
    orderMetricsList.add(new 
    StudentData(mongoTemplate.getConverter().read(Students.class, 
            (Integer) dbObject.get("roll"), (Double) dbObject.get("marks")));
}); 

So the DBObject class is also deprecated, I had to replace it with Document class. You can read more about it here. And I have used AggregateIterable interface with MongoCursor and that did the trick.

Final Code

List<Document> studentAggregationQuery = new ArrayList<>();
studentAggregationQuery.add(new Document("$roll", roll));
studentAggregationQuery.add(new Document("$marks", marks));

AggregateIterable studentDataIterator = 
collection.aggregate(studentAggregationQuery);

List<StudentData> studentDataList = new ArrayList<>();
MongoCursor<Document> studentIterator = studentDataIterator.iterator();
while (studentIterator.hasNext()) {
    Document next = studentIterator.next();
    studentDataList.add(new 
    StudentData(mongoTemplate.getConverter().read(Students.class,
        (Integer) next.get("roll"), (Double) next.get("marks")));
}

I hope you would be able to replace AggregationOutput with AggregateIterable to get the desired output/results.

viveknaskar
  • 2,136
  • 1
  • 20
  • 35
2

If you look at DBCollection you'll see several variants of aggregate() including those that return AggregationOutput. The preferred version is to use the variants that take AggregationOptions and return a Cursor, however. This allows you to configure a number of options but most importantly, the ability to use a cursor for the response for cases where the aggregated results would break the 16M document size limit. If you were to use $out in your pipeline, this would be the preferred method as well since it would let you immediately start iterating over the collection you just populated.

evanchooly
  • 6,102
  • 1
  • 16
  • 23
0

MongoAPI Docs has no clue about which class has replaced AggregationOutput.

But as of the functionality, AggregationOutput class was used to store the result set of a mongo query. And object of aggregationOutput.results() will provide an array of documents which you can iterate using an iterator to get the individual docs.

So DBCursor is the close match in that case.

mohamedrias
  • 18,326
  • 2
  • 38
  • 47
0

This is an example of how you must use aggregata. my function in Java

 /**
 * MongoDB Code:
 * db.review_Rating.aggregate([
 * { $match : { media_id:"456" } },
 * { $group:{ _id:"$media_id", avg_rating:{ $avg : "$rating" } } } ] )
 *
 * @param mediaID that is being sought
 * @return Float arage rating for the media with param mediaID,
 * if not found return null
 */
Float getAvrageRating(String mediaID) {

    DBCollection collection = getConnection("MongoMedia", "review_Rating");

    if(mediaID != null) {
        LinkedList<DBObject> pipe = new LinkedList<>();
        pipe.add(new BasicDBObject("media_id", mediaID));

        DBObject groupFields = new BasicDBObject("media_id", mediaID);
        groupFields.put("avg_rating", new BasicDBObject("$avg", "$rating"));
        pipe.add(new BasicDBObject("$group", groupFields));
        AggregationOutput cursor = collection.aggregate(pipe);

        LinkedList<String> values = new LinkedList<>();
        for (DBObject doc : cursor.results()) {
            JSONObject obj = new JSONObject(doc.toString());
            values.add(obj.getString("avg_rating"));

            JSONObject idObj = (JSONObject) obj.get("_id");
            values.add((String) idObj.get("$oid"));
        }
        return Float.valueOf(values.getFirst());
    }
    return null;

}
Ar maj
  • 1,974
  • 1
  • 16
  • 16