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

1

У меня есть коллекция, в которой есть 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.]

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

Теги:
sorting
aggregation-framework
spring-data-mongodb

2 ответа

1
Лучший ответ

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

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

Если вы не можете обновлять зависимостей в библиотеке для данных allowDiskUse вас все еще есть опции для выполнения оператора агрегации и укажите параметр 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() функции .aggregate() на mongoOperations действительно так или иначе, так что это просто настройка процесса, в котором не существует вспомогательной функции.

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

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

0

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

  • 0
    В среде Spring-Data Aggregation доступна опция allowDiskUse версии 1.6.m1. не так ли? И я использую версию 1.3.2 ... я знал, что это пока невозможно. Посмотрите на это: опция для агрегации в весенних данных
  • 0
    Может быть, вы можете использовать драйвер Монго для этого. Класс DBCollection имеет метод для агрегирования с опциями. ссылка

Ещё вопросы

Сообщество Overcoder
Наверх
Меню