Vinita
Vinita

Reputation: 1864

How to match data in two collections in mongoose using aggregate?

I have a quiz app where the schemas are as follows: quiz schema -

const quizSchema = new mongoose.Schema({
  userID: {
    type: String,
    required: [true, 'User ID required']
  }
});

Response Schema -

const responseSchema = new mongoose.Schema({
  userID: {
    type: String,
    required: [true, 'User ID required']
  },
  quizID: {
    type: String,
    required: [true, 'Quiz ID required']
  }
});

Response schema has the user responses to the quiz i.e if a quiz is attempted then only it is stored in response schema

I can easily find out the attempted quiz by a user using

const attempted = await Response.find({userID});

Here is how I did it using basic logic: -

exports.unattemptedQuizDB = async (userID) => {
    try{
        const quizzes = await Quiz.find({});
        const filtered = [];
        for (const quiz of quizzes){
            const inResponse = await Response.find({userID:userID, quizID: quiz._id});
            if (inResponse.length === 0){
                filtered.push(quiz._id);
            }
        }
        return filtered;
    }catch(e){
        throw new Error(e);
    }
};

But how do I find unattempted quizzes using aggregation?

Upvotes: 0

Views: 197

Answers (1)

Dheemanth Bhat
Dheemanth Bhat

Reputation: 4452

Below is the aggregation query for the logic you have written:

let responses = await Quiz.aggregate([
    {
        $lookup: {
            from: "responses",
            let: { 
                userID: "$userID", 
                quizID: { $toString: "$_id" }
            },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $eq: ["$userID", "$$userID"] },
                                { $eq: ["$quizID", "$$quizID"] }
                            ]
                        }
                    }
                }
            ],
            as: "responses"
        }
    },
    {
        $match: {
            "responses": { $eq: [] }
        }
    }
]);

Upvotes: 1

Related Questions