2015-10-14 1 views
0

Я пытаюсь выполнить запрос агрегата mongo db из java, но размер буфера превышает 16 МБ. Есть ли способ настроить размер буфера или любой другой способ обхода. У меня нет возможности создавать коллекцию на стороне сервера mongo, а также у меня нет никакой утилиты mongo, такой как mongo.exe или mongoExport.exe в моей клиентской системе.Java/Grails - агрегация MongoDB 16MB ограничение размера буфера

Вот небольшая часть кода

if (!datasetObject?.isFlat && jsonFor != 'collection-grid'){ 
    //mongoPipeline = new AggregateArgs (Pipeline = pipeline, AllowDiskUse = true, OutputMode = AggregateOutputMode.Cursor) 
    output= dataSetCollection.aggregate(pipeline) 
}else{ 
    output= dataSetCollection.aggregate(project) 
    } 

У меня есть 100K записей с 30 поля. Когда я запрашиваю 5 полей для всех записей 100K, я получаю результат (успех). Но когда я делаю запрос для 100K записей со всеми полями, они бросают ниже ошибки.

Проблема заключается в том, что я пытаюсь получить доступ ко всем документам из коллекции, включая , все поля с документом размером более 16 МБ.

Фактическая ошибка:

com.mongodb.CommandFailureException: { "serverUsed" : "127.0.0.1:27017" , "errmsg" : "exception: aggregation result exceeds maximum document size (16MB)" , "code" : 16389 , "ok" : 0.0 

Как решить эту проблему?

Использование MongoDB-3.0.6

Примечание: GridFS не подходит для моих критериев. Потому что мне нужно получить все документы в одном запросе, а не один документ.

+0

Ну, нет. Кроме того, нет никакого шанса получить предложение лучшего подхода, не разделяя код, который вы сейчас пытаетесь сделать. –

+0

@BlakesSeven см. Обновленный вопрос. Я сохранил код. –

ответ

0

Есть два варианта решения этой проблемы

1) использование $out, который создает новую коллекцию и результат записи, что не очень хорошо, потому что этот процесс требует много времени и сложностей.

public class JavaAggregation { 
public static void main(String args[]) throws UnknownHostException { 

    MongoClient mongo = new MongoClient(); 
    DB db = mongo.getDB("databaseName"); 

    DBCollection coll = db.getCollection("dataset"); 

    /* 
     MONGO SHELL : 
     db.dataset.aggregate([ 
      { "$match": { isFlat : true } }, 
      { "$out": "datasetTemp" } 
     ]) 
    */ 

    DBObject match = new BasicDBObject("$match", new BasicDBObject("isFlat", true)); 
    DBObject out = new BasicDBObject("$out", "datasetTemp"); 

    AggregationOutput output = coll.aggregate(match, out); 

    DBCollection tempColl = db.getCollection("datasetTemp"); 
    DBCursor cursor = tempColl.find(); 

    try { 
     while(cursor.hasNext()) { 
      System.out.println(cursor.next()); 
     } 
    } finally { 
     cursor.close(); 
    } 
} 
} 

2. Использование allowDiskUse(true) очень прост в реализации и даже не отнимает много времени.

public class JavaAggregation { 
public static void main(String args[]) throws UnknownHostException { 

    MongoClient mongo = new MongoClient(); 
    DB db = mongo.getDB("databaseName"); 

    DBCollection coll = db.getCollection("dataset"); 

    /* 
     MONGO SHELL : 
     db.dataset.aggregate([ 
      { "$match": { isFlat : true } }, 
      { "$out": "datasetTemp" } 
     ]) 
    */ 

    DBObject match = new BasicDBObject("$match", new BasicDBObject("isFlat", true)); 
    def dbObjArray = new BasicDBObject[1] 
    dbObjArray[0]= match 
    List<DBObject> flatPipeline = Arrays.asList(dbObjArray) 

    AggregationOptions aggregationOptions = AggregationOptions.builder() 
            .batchSize(100) 
            .outputMode(AggregationOptions.OutputMode.CURSOR) 
            .allowDiskUse(true) 
            .build(); 
    def cursor = dataSetCollection.aggregate(flatPipeline,aggregationOptions) 
    try { 
     while(cursor.hasNext()) { 
      System.out.println(cursor.next()); 
     } 
    } 
    finally { 
     cursor.close(); 
    } 
} 

Для более см here и here

1

При запуске агрегации вы можете указать mongo на возврат курсора. С новым API, в драйвере 3.0 Java, который будет выглядеть следующим образом:

// Assuming MongoCollection 
dataSetCollection.aggregate(pipeline).useCursor(true) 

Вы также, возможно, придется сказать ему, чтобы использовать дисковое пространство на сервере, а не делать все это в памяти:

// Assuming MongoCollection 
dataSetCollection.aggregate(pipeline).useCursor(true).allowDiskUse(true) 

Если вы используете старый драйвер (или старый API в новом драйвере) эти два варианта будут выглядеть следующим образом:

// Assuming DBCollection 
dataSetCollection.aggregate(pipeline, AggregationOptions.builder() 
    .allowDiskUse(true) 
     .useCursor(true) 
     .build()) 
    .useCursor(true) 
+0

Я использую mongodb-win32-i386-3.0.6 –

+0

его не работает. Я попытался использовать этот dataSetCollection.aggregate (конвейер) .useCursor (true) .allowDiskUse (true).Теперь он дает ту же ошибку даже для данных небольшого размера <16Mb –

+0

Какое сообщение об ошибке? – evanchooly