Mongodb聚合框架对巨大的数据进行排序

时间:2014-08-12 11:54:11

标签: java mongodb sorting aggregation-framework spring-data-mongodb

我有一个拥有200万条记录的集合。当我使用时:

Aggregation aggregation = newAggregation(
                project("y", "x"),sort(Direction.ASC, "x"), unwind("y"),
                match(criteria),limit(maxElements),skip(elementsToSkip));

它出现了您预期的错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Command execution failed:  Error [exception: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.]

当我需要对大数据进行排序时,我该怎么办?我搜索了很多文档,但我找不到任何正常的文件。

2 个答案:

答案 0 :(得分:1)

作为一般情况,您应该将实施$match视为聚合管道的第一阶段,以限制处理的结果。即使这不过滤所有的一切"在展开之后使用匹配过滤(当然你保留)它至少会删除任何不可能匹配的文档。

因此,初始匹配可能无法删除满足条件的任何数组元素,但至少它会删除任何不包含任何数组元素的文档。即使它仍然没有改变整体排序的结果,这也很有用。

如果无法升级spring数据库的库依赖项,那么仍然可以选择执行聚合语句并指定allowDiskUse选项。您正在连接的服务器显然支持它,如从服务器获取的错误所示。

    Aggregation aggregation = newAggregation(
        project("y","x"),
        sort(Sort.Direction.ASC,"x"),
        unwind("y"),
        match(criteria),
        limit(maxElements),
        skip(elementsToSkip)
    );

    BasicDBObject context =
       (BasicDBObject)aggregation.toDbObject("collection",DEFAULT_CONTEXT);
    context.append("allowDiskUse",true);
    System.out.println(context);

    CommandResult commandResult = mongoOperation.executeCommand(context);
    System.out.println(commandResult);

因此,您仍然可以使用相同的构建器操作,而只是从聚合语句中提取命令上下文。然后附加帮助程序不支持的其他信息,最后只通过.executeCommand()发出。

实际上,mongoOperations上的所有.aggregate()帮助器实际上都在做,所以这只是自定义没有辅助函数的进程。

如前所述,只要服务器上支持这些选项,那么基本方法(例如.executeCommand())只会将指令发送到服务器,并返回结果,并以您指定的形式发送。

另请参阅"命令表单"有关命令文档应该是什么样子的更多详细信息,请参阅官方文档中的"aggregate"

答案 1 :(得分:0)

如错误消息中所述,尝试传递allowDiskUse:true作为聚合函数的附加选项。