2015-07-08 11 views
7

Sto usando mongo-java-driver 3.0.2.Driver Java MongoDB 3.x: come passare allowDiskUse = true al metodo aggregate()?

ho un metodo che utilizza MongoCollection.aggregate(List<Bson> pipeline) per ordinare e limite:

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

Quando n è grande, non riesce con:

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.' 

ho trovato che il MongoDB guscio fornisce un metodo db.collection.aggregate(pipeline, options) (link) dove options può contenere un campo allowDiskUse.

Non riesco a trovare l'equivalente nell'API Java . Sebbene esista una classe AggregationOptions, la classe MongoCollection non fornisce un metodo aggregate(List<Bson> pipeline, AggregationOptions options).

risposta

9

Questo funziona ancora sul driver 3.0.3:

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

Naturalmente è anche possibile utilizzare le classi più recenti così:

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

Così .aggregate() su MongoCollection restituisce un'istanza AggregateIterable classe, che ha un metodo .allowDiskuse() e altri per impostare le opzioni di aggregazione.

+0

Il metodo 'mongoClient.getDB()' è deprecato in 3.x. Mi aspettavo che tutte le funzionalità delle vecchie classi 'DB' e' DBCollection' fossero state spostate nelle nuove classi 'MongoDatabase' e' MongoCollection' ma immagino che non sia ancora successo. – romanws

+0

@romanws Non è deprecato in quanto non ci sono avvisi di deprecazione. Inoltre hai colpito l'unghia sulla testa con "nuovo". È così nuovo che ci sono ancora cose da fare per mantenere la piena compatibilità con tutte le funzionalità. –

+0

@romanws Ma ovviamente è anche possibile utilizzare le classi più recenti, è solo che ora le opzioni vengono specificate in modo diverso. –

Problemi correlati