Подтвердить что ты не робот

Итерацию над большой коллекцией в MongoDB через spring -data

Друзья!

Я использую MongoDB в проекте java через spring -data. Я использую интерфейсы репозитория для доступа к данным в коллекциях. Для некоторой обработки мне нужно перебрать все элементы коллекции. Я могу использовать метод репозитория fetchAll, но он всегда возвращает ArrayList.

Однако предполагается, что одна из коллекций будет большой - до 1 миллиона записей по меньшей мере на несколько килобайт. Я полагаю, что я не должен использовать fetchAll в таких случаях, но я не мог найти ни удобные методы, возвращающие некоторый итератор (который может позволить частично получить выборку), ни удобные методы с обратными вызовами.

Я видел только поддержку для получения таких коллекций на страницах. Интересно, является ли это единственным способом работы с такими коллекциями?

4b9b3361

Ответ 1

Поздний ответ, но, возможно, поможет кому-то в будущем. Данные Spring не предоставляют API для обёртывания возможностей Mongo DB Cursor. Он использует его в методах find, но всегда возвращает заполненный список объектов. Варианты: использовать Mongo API напрямую или Spring Data Paging API, что-то вроде этого:

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

UPD (!) Этот метод недостаточен для больших наборов данных (см. комментарии @Shawn Bush). Пожалуйста, используйте Mongo API напрямую для таких случаев.

Ответ 2

Используйте MongoTemplate:: stream() как наиболее подходящую оболочку Java для DBCursor

Ответ 3

вы все равно можете использовать mongoTemplate для доступа к коллекции и просто использовать DBCursor:

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

Ответ 4

Другой способ:

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

}while (!page.isLastPage());

Ответ 5

Поток как курсор:

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

Итак, для большого объема данных вы можете передавать их и обрабатывать строки за строкой без ограничения памяти

Ответ 7

Возможно, вы захотите попробовать путь DBCursor следующим образом:

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