如何限制Spring数据Mongo的map reduce方法返回的MapReduceResults的大小

时间:2014-08-04 16:01:31

标签: java mongodb spring-data-mongodb

当使用spring-data-mongodb的MongoTemplate执行map reduce操作时,该方法返回一个MapReduceResults对象。

在我的用例中,不使用此对象(及其内容)(结果与数据库上的现有集合合并)。

MongoDB驱动程序似乎向结果返回游标(无数据),但弹出库将此游标解析为实际的数据库对象。

这会导致大量数据通过网络传递,并且由于OutOfMemoryError而导致调用作业失败。

有没有办法(不直接下载到MongoDB驱动程序)来限制Spring层返回给调用方法的数据库对象的数量?

  • mongo-java-driver-2.12.1
  • 弹簧数据的mongodb-1.5.1.RELEASE

更新 : 似乎我的假设是这是一个相当普遍的问题是不正确的。

这是我正在运行的代码。 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);

1 个答案:

答案 0 :(得分:2)

无需下载给司机。

可以通过扩展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类中移植一些私有方法,以便这个新类可以访问它们。