I'm using mongo-java-driver 3.0.2.
I have a method that uses MongoCollection.aggregate(List<Bson> pipeline)
to sort and limit:
private static MongoIterable<Document> selectTop(int n) {
BasicDBObject sortFields = new BasicDBObject("score", -1);
BasicDBObject sort = new BasicDBObject("$sort", sortFields);
BasicDBObject limit = new BasicDBObject("$limit", n);
List<BasicDBObject> pipeline = new ArrayList<>();
pipeline.add(sort);
pipeline.add(limit);
return playersCollection.aggregate(pipeline);
}
When n
is big, it fails with:
com.mongodb.MongoCommandException: Command failed with error 16820: 'exception: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.'
I've found that the MongoDB shell provides a method db.collection.aggregate(pipeline, options)
(link) where options
can contain an allowDiskUse
field.
I can't find the equivalent to this in the Java API. Although there is an AggregationOptions class, the MongoCollection
class doesn't provide an aggregate(List<Bson> pipeline, AggregationOptions options)
method.
This still works on the 3.0.3 driver:
MongoClient client = new MongoClient(new ServerAddress("127.0.0.1", 27017));
DB test = client.getDB("test");
DBCollection sample = test.getCollection("sample");
List<DBObject> aggregationQuery = Arrays.<DBObject>asList(
new BasicDBObject("$sort",new BasicDBObject("score",-1)),
new BasicDBObject("$limit",1)
);
System.out.println(aggregationQuery);
Cursor aggregateOutput = sample.aggregate(
aggregationQuery,
AggregationOptions.builder()
.allowDiskUse(true)
.build()
);
while ( aggregateOutput.hasNext() ) {
DBObject doc = aggregateOutput.next();
System.out.println(doc);
}
Of course you can also use newer classes as well:
MongoClient client = new MongoClient(new ServerAddress("192.168.2.4", 27017));
MongoDatabase db = client.getDatabase("test");
MongoCollection<Document> collection = db.getCollection("sample");
AggregateIterable<Document> result = collection.aggregate(Arrays.asList(
new BasicDBObject("$sort", new BasicDBObject("score", -1)),
new BasicDBObject("$limit", 1)
)).allowDiskUse(true);
MongoCursor<Document> cursor = result.iterator();
while (cursor.hasNext()) {
Document doc = cursor.next();
System.out.println(doc);
}
So .aggregate()
on MongoCollection returns an AggregateIterable
class instance, which has an .allowDiskuse()
method as well as others to set aggregation options.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With