I have this Schema structure
const QuizQuestionSchema = new Schema({
course: { type: String, required: true, trim: true },
point: { type: Number, required: true, trim: true, min: 1, max: 20 },
question: { type: String, required: true, trim: true },
codeBoard: { type: String, default: null, nullable: true },
answers: { type: [String], required: true, trim: true },
correctAnswer: { type: String, required: true, trim: true }
});
from client I get array id of documents and selected answer [{id, answer}...]
.
I need to find out how many points the user has collected, comparing correctAnswer with answer if match add score. how can this be done with an aggregate ?
example
client
[
{ id: "61bc09994da5e9ffe47fccb9", answer: "1 2 4 3 5" },
{ id: "61bc0af14da5e9ffe47fccbb", answer: "1 4 3 2" },
...
];
server documents
{
_id: new ObjectId("61bc09994da5e9ffe47fccb9"),
course: 'JavaScript',
point: 10,
question: 'What will we see in the console ?',
codeBoard: '...',
answers: [ '1 2 4 3 5', '1 5 4 3 2', '2 1 4 3 5', '1 5 3 4 2' ],
correctAnswer: '2 1 4 3 5',
__v: 0
},
{
_id: new ObjectId("61bc0af14da5e9ffe47fccbb"),
course: 'JavaScript',
point: 10,
question: 'What will we see in the console ?',
codeBoard: '...',
answers: [ '1 4 3 2', '1 2 4 3', '1 2 3 4', '1 4 2 3' ],
correctAnswer: '1 4 3 2',
__v: 0
}
If the client side is sending each question id in String with the chosen answer you should map that array to:
{
id: new ObjectId("61bc09994da5e9ffe47fccb9"),
correctAnswer: "2 1 4 3 5"
}
Remenber to define ObjectId with:
const ObjectId = require('mongoose').Types.ObjectId;
Then add the full array inside an $or
operator and finally group every match adding the points.
db.collection.aggregate({
"$match": {
$or: [
{
id: new ObjectId("61bc09994da5e9ffe47fccb9"),
correctAnswer: "2 1 4 3 5"
},
{
id: new ObjectId("61bc0af14da5e9ffe47fccbb"),
correctAnswer: "1 4 3 2"
},
. . .
]
}
},
{
"$group": {
"_id": null, // This means that every document is grouped, because there is no condition to group by
"points": {
$sum: "$point"
}
}
})
You can achieve this with a pretty straight forward pipeline, using $lookup
, like so:
db.users.aggregate([
{
$match: {
user_id: 1
}
},
{
"$lookup": {
"from": "quiz",
let: {
quizId: "$id",
userAnswer: "$answer"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$$quizId",
"$_id"
]
},
{
$eq: [
"$$userAnswer",
"$correctAnswer"
]
}
]
}
}
}
],
"as": "matched"
}
},
{
$group: {
_id: null,
total: {
$sum: 1
},
correct: {
$sum: {
$size: "$matched"
}
}
}
}
])
Mongo Playground
You didn't give exact input and output required so this will require some minor changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With