Я пытаюсь использовать структуру агрегации, чтобы развернуть массив и получить результаты, отсортированные по полю вложенного документа в массиве. Есть ли способ сделать это так, чтобы индекс мог использоваться для сортировки?
Например, предположим, у меня есть база данных таких документов:
{
name: "Alan",
attempts: [{
assessmentName: "Test 1",
score: 87
}, {
assessmentName: "Test 2",
score: 62
}]
}
и указатель на баллы, {'attempts.score': 1}
.
Мне нужен конвейер агрегации, который приводит к:
{ name: "Alan", attempts: {assessmentName: "Test 2", score: 62} }
{ name: "Alan", attempts: {assessmentName: "Test 1", score: 87} }
...
Если я поставлю $sort
сцену первой:
db.students.aggregate([
{$sort: {'attempts.score': 1}},
{$unwind: '$attempts'}
])
тогда мой индекс можно использовать, но результат, конечно, фактически не сортируется после $unwind
.
Если поставить второй этап $sort
:
db.students.aggregate([
{$unwind: '$attempts'},
{$sort: {'attempts.score': 1}}
])
тогда я получу результаты, которые хочу, но это невозможно для большой коллекции, потому что мой индекс не может быть использован. (Монго прерывается с «Сортировка превысила ограничение памяти в 104857600 байт, но не включила внешнюю сортировку. Операция прерывания. Передайте allowDiskUse: true для выбора.» Разрешение на использование диска позволит избежать этой ошибки, но не будет соответствовать моей требования к производительности.)
Основываясь на моих исследованиях, я подозреваю, что в настоящее время это невозможно с помощью структуры агрегации. Но, конечно, я надеюсь, что ошибаюсь.
Обновление для устранения некоторых комментариев:
Конечно, этой проблемы можно избежать, изменив модель данных, но давайте предположим, ради этого вопроса, что это модель данных, с которой мы застряли. (Во многих случаях изменение модели данных не является жизнеспособным решением, по крайней мере, в краткосрочной перспективе.)
Кроме того, часть того, почему я задал этот вопрос, заключается в том, что я думаю, что это то, что Mongo теоретически может поддерживать с помощью существующих структур данных. Например, если шаг $unwind
принял параметр sortBy
, он может использовать индекс многопользовательского режима, чтобы выполнить раскрутку в нужном порядке.