2012-06-15 10 views
12

Znajomi!Iteracja na dużej kolekcji w MongoDB za pomocą danych sprężynowych

Używam MongoDB w projekcie Java za pośrednictwem danych sprężyn. Używam interfejsów Repository, aby uzyskać dostęp do danych w kolekcjach. Do pewnego przetwarzania muszę powtórzyć wszystkie elementy kolekcji. Mogę użyć metody repozytorium fetchAll, ale zawsze zwraca ona ArrayList.

Jednak przypuszcza się, że jedna z kolekcji byłaby duża - do 1 miliona, co najmniej po kilka kilobajtów. Przypuszczam, że nie powinienem używać FetchAll w takich przypadkach, ale nie mogłem znaleźć ani wygodnych metod zwracających jakiś iterator (który może pozwolić na pobranie częściowo), ani wygodnych metod z callbackami.

Widziałem tylko obsługę pobierania takich kolekcji na stronach. Zastanawiam się, czy to jedyny sposób na pracę z takimi kolekcjami?

+0

można użyć 'granicę()' funkcja ograniczyć funkcję pobierać dane w kawałkach –

+0

Nie jestem zaznajomiony z ramą, której używasz, ale byłbym bardzo dziwny, gdyby nie miał jakiegoś otoki dla kursorów MongoDB. Czy jesteś pewien, że to, co dostajesz, to 'ArrayList', a nie niestandardowa implementacja' List', która owija się wokół kursora? – thkala

+2

yes, surely - Właśnie zarejestrowałem jego findAll(). GetClass() dla kolekcji około 3 milionów i myślę, że widziałem java.util.ArrayList ... –

Odpowiedz

17

Późna odpowiedź, ale może pomoże komuś w przyszłości ..) Dane sprężynowe nie zapewniają żadnego interfejsu API do objęcia funkcji Mongo DB Cursor. Używa go w metodach find, ale zawsze zwraca kompletną listę obiektów. Opcje są do korzystania Mongo API bezpośrednio lub użyć Wiosna Dane stronicowania API, coś takiego:

 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

Po prostu chciałem zadzwonić jeszcze później i powiedzieć, że dla duże zbiory danych, należy również trzymać się z daleka od interfejsu API stronicowania, ponieważ musi przejść całą kolekcję przed zbudowaniem każdej strony. To szybko staje się drogie. Pozostań przy użyciu API Mongo bezpośrednio. –

+0

@ShawnBush Jesteś tego pewien? – javadev

3

inny sposób:

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

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

Zastosowanie MongoTemplate :: strumień() jako prawdopodobnie najbardziej odpowiedni wrapper Java DBCursor

6

można nadal korzystać mongoTemplate dostęp do kolekcji i po prostu użyć DBCursor:

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

Możesz wypróbować sposób DBCursor w następujący sposób:

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

Strumienie jako Kursor:

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

Tak na dużą ilość danych można przesyłać je i przetwarzać linia po linii bez ograniczeń pamięci

Powiązane problemy