2012-06-15 9 views
12

¡Amigos!Iteramos la colección grande en MongoDB a través de los datos de la primavera

Estoy usando MongoDB en el proyecto de Java a través de Spring-Data. Utilizo interfaces de repositorio para acceder a datos en colecciones. Para algunos procesos, necesito iterar sobre todos los elementos de la colección. Puedo usar fetchAll method of repository, pero siempre devuelve ArrayList.

Sin embargo, se supone que una de las colecciones sería grande, hasta 1 millón de registros varios kilobytes cada uno como mínimo. Supongo que no debería usar fetchAll en tales casos, pero no pude encontrar ningún método conveniente que devuelva algún iterador (lo que puede permitir que la colección se obtenga de forma parcial), ni métodos convenientes con devoluciones de llamadas.

He visto solo soporte para recuperar tales colecciones en páginas. Me pregunto si es la única forma de trabajar con esas colecciones.

+0

puede usar 'límite()' función de limitar la función de recuperar datos en fragmentos –

+0

No estoy familiarizado con el marco que está utilizando, pero me resultaría muy extraño si no tiene algún contenedor para los cursores de MongoDB. ¿Estás seguro de que lo que obtienes es un 'ArrayList', y no una implementación personalizada' List' que envuelve un cursor? – thkala

+2

sí, seguramente - Acabo de registrar su findAll(). GetClass() para la colección de aproximadamente 3 millones y creo que vi java.util.ArrayList ... –

Respuesta

17

Última respuesta, pero tal vez ayude a alguien en el futuro ...) Los datos de primavera no proporcionan ninguna API para ajustar Mongo DB Cursor capacidades. Lo usa dentro de los métodos find, pero siempre devuelve una lista completa de objetos. Las opciones son utilizar la API de Mongo directa o utilizar primavera de datos de localización API, algo así:

 final int pageLimit = 300; 
     int pageNumber = 0; 
     Page<T> page = repository.findAll(new PageRequest(pageNumber, pageLimit)); 
     while (page.hasNextPage()) { 
      processPageContent(page.getContent()); 
      page = repository.findAll(new PageRequest(++pageNumber, pageLimit)); 
     } 
     // process last page 
     processPageContent(page.getContent()); 
+8

Solo quería sonar más tarde y decir eso para grandes conjuntos de datos, también debe mantenerse alejado de la API de paginación, ya que tiene que recorrer toda la colección antes de compilar cada página. Esto se pone caro rápidamente. Seguir usando la API de Mongo directamente. –

+0

@ShawnBush ¿Estás seguro de esto? – javadev

3

Otra forma:

do{ 
    page = repository.findAll(new PageRequest(pageNumber, pageLimit)); 
    pageNumber++; 

}while (!page.isLastPage()); 
7

Uso MongoTemplate :: corriente() como probablemente el envoltorio de Java más adecuado para dbcursor

6

puede seguir utilizando mongoTemplate para acceder a la colección y simplemente usar dbcursor:

 DBCollection collection = mongoTemplate.getCollection("boundary"); 
    DBCursor cursor = collection.find();   
    while(cursor.hasNext()){ 
     DBObject obj = cursor.next(); 
     Object object = obj.get("polygons"); 
     .. 
     ... 
    } 
0

Es posible que desee probar el modo DBCursor de esta manera:

DBObject query = new BasicDBObject(); //setup the query criteria 
    query.put("method", method); 
    query.put("ctime", (new BasicDBObject("$gte", bTime)).append("$lt", eTime)); 

    logger.debug("query: {}", query); 

    DBObject fields = new BasicDBObject(); //only get the needed fields. 
    fields.put("_id", 0); 
    fields.put("uId", 1); 
    fields.put("ctime", 1); 

    DBCursor dbCursor = mongoTemplate.getCollection("collectionName").find(query, fields); 

    while (dbCursor.hasNext()){ 
     DBObject object = dbCursor.next(); 
     logger.debug("object: {}", object); 
     //do something. 
    } 
1

corrientes como cursor:

@Query("{}") 
Stream<Alarm> findAllByCustomQueryAndStream(); 

Así, por la gran cantidad de datos que puede transmitir ellos y procesar la línea por línea y sin limitación de memoria

Cuestiones relacionadas