При использовании Spring-data-mongodb MongoTemplate для выполнения операции уменьшения карты метод возвращает объект MapReduceResults.
В моем случае использования этот объект (и его содержимое) не используется (результаты объединены с существующей коллекцией в базе данных).
Похоже, что драйвер MongoDB возвращает курсор (без данных) к результату, но библиотеки весны разрешают этот курсор для реальных объектов базы данных.
Это приводит к тому, что большие объемы данных передаются по сети, а вызывающее задание - сбой из-за OutOfMemoryError.
Есть ли какой-либо способ (не отступая непосредственно от драйвера MongoDB), чтобы ограничить количество объектов базы данных, возвращаемых слоем Spring, вызывающему методу?
ОБНОВЛЕНИЕ: По-моему, мое предположение о том, что это был довольно общий вопрос, было неверным.
Вот код, который я запускаю. 3 функции JS хранятся в файлах и загружаются в виде строк методом loadFile().
Я добавил RHS для задания результатов здесь (его не в моем коде, поскольку мне не нужны/использовать результаты). Мне бы понравилась версия метода mapRecuce, которая ничего не возвращает.
MapReduceOptions options = MapReduceOptions.options();
options.outputTypeReduce();
options.finalizeFunction(loadFile(finalizeFunctionFilename));
options.outputCollection(output_collection_name);
List<DBObject> results = mongoTemplate.mapReduce(query,
input_collection_name,
loadFile(mapFunctionFilename),
loadFile(reduceFunctionFilename),
options,
DBObject.class);
Не нужно спускаться к драйверам.
Эта проблема может быть решена путем расширения класса MongoTemplate и переопределения метода mapReduce.
Очевидно, что при обновлении библиотек следует позаботиться о переносе любых изменений в этот новый класс.
Новый метод выглядит следующим образом:
@Override
public <T> MapReduceResults<T> mapReduce(Query query, String inputCollectionName, String mapFunction,
String reduceFunction, MapReduceOptions mapReduceOptions, Class<T> entityClass) {
if (mapReduceOptions.getOutputType() == OutputType.INLINE) {
// if output type is inline then no need to suppress results
return super.mapReduce(query, inputCollectionName, mapFunction, reduceFunction, mapReduceOptions, entityClass);
}
String mapFunc = replaceWithResourceIfNecessary(mapFunction);
String reduceFunc = replaceWithResourceIfNecessary(reduceFunction);
DBCollection inputCollection = getCollection(inputCollectionName);
MapReduceCommand command = new MapReduceCommand(inputCollection, mapFunc, reduceFunc,
mapReduceOptions.getOutputCollection(), mapReduceOptions.getOutputType(), null);
DBObject commandObject = copyQuery(query, copyMapReduceOptions(mapReduceOptions, command));
if (logger.isDebugEnabled()) {
logger.debug("Executing MapReduce on collection [{}], mapFunction [{}], reduceFunction [{}]",
command.getInput(), mapFunc, reduceFunc);
}
CommandResult commandResult = executeCommand(commandObject);
handleCommandError(commandResult, commandObject);
if (logger.isDebugEnabled()) {
logger.debug("MapReduce command result = [{}]", serializeToJsonSafely(commandObject));
}
return new MapReduceResults<>(new ArrayList<T>(), commandResult);
}
Вам также необходимо будет перенести несколько частных методов из исходного класса MongoTemplate, чтобы этот новый класс имел к ним доступ.