2

I have the following resolver:

        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' });

The problem is that I need to populate 'userPassageStatsId' and return it but it's not working well returning the following error:

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

does anyone knows what I am doing wrong?

1 Answer 1

2

$group can only contain _id or accumulator objects like $first, $last, $sum etc. In your case your building nested object and that syntax is not allowed - accumulator has to be on a top level. You can try two approaches, either return flat structure from $group and then reshape using $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",
                ...
            }
        }
    }
}

or use $$ROOT to capture first object for every group and reshape it using $project:

{
    $group: {
        _id: '$level',
        d: { $first: "$$ROOT" }
    }
},
{
    $project: {
        _id: 1,
        level: "$d.level",
        ...,
        userPassageStatsId: {
            _id: "$d._id",
            stats: {
                readingTime: "$d.readingTime",
                ...
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Hi @mickl! thanks for your reply! Now I am getting the following error after apply your recommendation:
"message": "Cannot return null for non-nullable field UserPassageStats._id.", do you have any idea what could be wrong?
I am populating userPassageStats with: UserPassageStats.populate(result, { path: 'userPassageStatsId' });
@GuilhermeRamos the name ends with dot which is not allowed
ohh not actually just the error message includes the dot by the end of it
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.