Am trying to create a poll results aggregation
I have two collections
poll – here is one document
{
"_id": {
"$oid": "636027704f7a15587ef74f26"
},
"question": "question 1",
"ended": false,
"options": [
{
"id": "1",
"option": "option 1"
},
{
"id": "2",
"option": "option 2"
},
{
"id": "3",
"option": "option 3"
}
]
}
Vote – here is one document
{
"_id": {
"$oid": "635ed3210acbf9fd14af8fd1"
},
"poll_id": "636027704f7a15587ef74f26",
"poll_option_id": "1",
"user_id": "1"
}
and i want to perform an aggregate query to get poll results
so am doing the following query
db.vote.aggregate(
[
{
$addFields: {
poll_id: { "$toObjectId": "$poll_id" }
},
},
{
$lookup: {
from: "poll",
localField: "poll_id",
foreignField: "_id",
as: "details"
}
},
{
$group:
{
_id: { poll_id: "$poll_id", poll_option_id: "$poll_option_id" },
details: { $first: "$details" },
count: { $sum: 1 }
}
},
{
$addFields: {
question: { $arrayElemAt: ["$details.question", 0] }
}
},
{
$addFields: {
options: { $arrayElemAt: ["$details.options", 0] }
}
},
{
$group: {
_id: "$_id.poll_id",
poll_id: { $first: "$_id.poll_id" },
question: { $first: "$question" },
options: { $first: "$options" },
optionsGrouped: {
$push: {
id: "$_id.poll_option_id",
count: "$count"
}
},
count: { $sum: "$count" }
}
}
]
)
That is giving me this form of results
{ _id: ObjectId("636027704f7a15587ef74f26"),
poll_id: ObjectId("636027704f7a15587ef74f26"),
question: 'question 1',
options:
[ { id: '1', option: 'option 1' },
{ id: '2', option: 'option 2' },
{ id: '3', option: 'option 3' } ],
optionsGrouped:
[ { id: '1', count: 2 },
{ id: '2', count: 1 } ],
count: 3 }
So what am interested in i want to have the results looking like ( like merging both options & options Group)
{ _id: ObjectId("636027704f7a15587ef74f26"),
poll_id: ObjectId("636027704f7a15587ef74f26"),
question: 'question 1',
optionsGrouped:
[ { id: '1', option: 'option 1', count: 2 },
{ id: '2', option: 'option 2', count: 1 },
{ id: '3', option: 'option 3', count: 0 } ],
count: 4 }
Another question is the DB structure acceptable overall or i can represent that in a better way ?
2
Answers
I had reworked the query to match my desires
and this query is achieving the question i have asked
One option is to group first and use the
$lookup
later, in order to fetch less data from thepoll
collection. After the$lookup
, use$map
with$cond
to merge the arrays:See how it works on the playground example