Итерацию над большой коллекцией в MongoDB через spring -data
Друзья!
Я использую MongoDB в проекте java через spring -data. Я использую интерфейсы репозитория для доступа к данным в коллекциях. Для некоторой обработки мне нужно перебрать все элементы коллекции. Я могу использовать метод репозитория fetchAll, но он всегда возвращает ArrayList.
Однако предполагается, что одна из коллекций будет большой - до 1 миллиона записей по меньшей мере на несколько килобайт. Я полагаю, что я не должен использовать fetchAll в таких случаях, но я не мог найти ни удобные методы, возвращающие некоторый итератор (который может позволить частично получить выборку), ни удобные методы с обратными вызовами.
Я видел только поддержку для получения таких коллекций на страницах. Интересно, является ли это единственным способом работы с такими коллекциями?
Ответы
Ответ 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();
Итак, для большого объема данных вы можете передавать их и обрабатывать строки за строкой без ограничения памяти
Ответ 6
Проверить новый метод обработки результатов на основе документа.
http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html#executeQuery-org.springframework.data.mongodb.core.query.Query-java.lang.String-org.springframework.data.mongodb.core.DocumentCallbackHandler-
Ответ 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.
}