пн goose агрегация $ группа с вложенным объектом - PullRequest
2 голосов
/ 28 февраля 2020

У меня есть следующий преобразователь:

        const result = await UserPassage.aggregate([
      { $sort: { createdAt: -1 } },
      {
        $group: {
          _id: '$level',
          level: { $first: '$level' },
          passageId: { $first: '$passageId' },
          userId: { $first: '$userId' },
          type: { $first: '$type' },
          category: { $first: '$category' },
          score: { $first: '$score' },
          completedStage: { $first: '$completedStage' },
          userPassageStatsId: {
            _id: { $first: '$_id' },
            stats: {
              readingTime: { $first: '$readingTime' },
              qtdVocab: { $first: '$qtdVocab' },
              qtdTestDone: { $first: '$qtdTestDone' },
              totalQuiz: { $first: '$totalQuiz' },
              progress: { $first: '$progress' },
            },
          },
        },
      },
      { $sort: { level: 1 } },
    ]);

    await UserPassageStats.populate(result, { path: 'userPassageStatsId' });

Проблема в том, что мне нужно заполнить 'userPassageStatsId' и вернуть его, но он не работает должным образом, возвращая следующую ошибку:

 MongoError: The field 'userPassageStatsId' must be an accumulator object

кто-нибудь знает, что я делаю не так?

1 Ответ

2 голосов
/ 28 февраля 2020

$group может содержать только _id или объекты-аккумуляторы, такие как $first, $last, $sum et c. В вашем случае ваш вложенный объект здания и этот синтаксис не допускается - аккумулятор должен быть на верхнем уровне. Вы можете попробовать два подхода: либо вернуть плоскую структуру из $group, а затем изменить форму, используя $project:

{
    $group: {
        _id: '$level',
        level: { $first: '$level' },
        passageId: { $first: '$passageId' },
        userId: { $first: '$userId' },
        type: { $first: '$type' },
        category: { $first: '$category' },
        score: { $first: '$score' },
        completedStage: { $first: '$completedStage' },
        userPassageStatsId_id: { $first: '$_id' },
        readingTime: { $first: '$readingTime' },
        qtdVocab: { $first: '$qtdVocab' },
        qtdTestDone: { $first: '$qtdTestDone' },
        totalQuiz: { $first: '$totalQuiz' },
        progress: { $first: '$progress' }
    }
},
{
    $project: {
        _id: 1,
        level: 1,
        ...,
        userPassageStatsId: {
            _id: "$userPassageStatsId_id",
            stats: {
                readingTime: "$readingTime",
                ...
            }
        }
    }
}

, или использовать $$ROOT, чтобы захватить первый объект для каждой группы и изменить его, используя $project :

{
    $group: {
        _id: '$level',
        d: { $first: "$$ROOT" }
    }
},
{
    $project: {
        _id: 1,
        level: "$d.level",
        ...,
        userPassageStatsId: {
            _id: "$d._id",
            stats: {
                readingTime: "$d.readingTime",
                ...
            }
        }
    }
}
...