Mongodb Aggregation Framework Сортировка огромных данных

у меня есть коллекция с 2 миллионами записей. Когда я использую:

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

что я могу сделать, когда мне нужно отсортировать большие данные? Я искал много документов, но я не мог найти ничего, что работало бы нормально.


person AknKplnoglu    schedule 12.08.2014    source источник


Ответы (2)


В общем случае вам следует рассмотреть реализацию $match< /a> в качестве первого этапа конвейера агрегации для ограничения обрабатываемых результатов. Даже если это не фильтрует «все», что было бы отфильтровано с помощью совпадения после раскрутки (которое, конечно, вы сохраняете), оно, по крайней мере, удаляет любые документы, которые не могут совпадать.

Таким образом, начальное совпадение может не удалить какие-либо элементы массива, соответствующие условию, но, по крайней мере, оно удалит все документы, которые не содержат ни одного элемента массива, удовлетворяющего условию. Это полезно сделать, даже если это все еще не меняет результаты общей сортировки.

Если вы не можете обновить зависимости своей библиотеки для данных 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().

На самом деле это все, что делает помощник .aggregate() в mongoOperations, так что это просто настройка процесса, в котором не существует вспомогательной функции.

Как уже говорилось, до тех пор, пока параметры поддерживаются на сервере, тогда базовые методы, такие как .executeCommand(), просто отправляют инструкции на сервер, как возвращают результат, и в той форме, в которой вы их укажете.

Также см. «командную форму» для "aggregate" в официальной документации для подробнее о том, как должен выглядеть командный документ.

person Neil Lunn    schedule 18.08.2014

Как упоминалось в сообщении об ошибке, попробуйте передать allowDiskUse : true в качестве дополнительной опции для функции агрегации.

person Piotr Chowaniec    schedule 12.08.2014
comment
в структуре Spring-data Aggregation опция allowDiskUse доступна в версии 1.6.m1. не так ли? И я использую версию 1.3.2... я знал, что пока это невозможно. см. это: опция для агрегирования данных Spring - person AknKplnoglu; 12.08.2014
comment
Возможно, вы можете использовать драйвер mongo для этого. Класс DBCollection имеет метод для агрегирования с параметрами. ссылка - person Piotr Chowaniec; 12.08.2014