I need to retrieve the entire single object hierarchy from the database as a JSON. I'm trying aggregate for hours and can't solve how to do it with my data. So I have three collections:
form
{ "_id" : "1", "name" : "My first form" }
{ "_id" : "2", "name" : "Second one" }
{ "_id" : "3", "name" : "Another" }
question
{ "_id" : "q1", "form" : "1", "title": "What's your country?"}
{ "_id" : "q2", "form" : "1", "title": "What your favorite color?"}
{ "_id" : "q3", "form" : "1", "title": "Where do you live?"}
{ "_id" : "q4", "form" : "2", "title": "Where to go?"}
option
{ "_id" : "o1", "question" : "q1", "text" : "Brazil" }
{ "_id" : "o2", "question" : "q1", "text" : "EUA" }
{ "_id" : "o3", "question" : "q1", "text" : "China" }
{ "_id" : "o4", "question" : "q2", "text" : "Red" }
{ "_id" : "o5", "question" : "q2", "text" : "Blue" }
{ "_id" : "o6", "question" : "q2", "text" : "Green" }
I need to retrieve each form with all corresponding questions, and in each question the options for it. Like this:
[
{
_id:"q1",
name: "My first form",
questions: [
{ "_id" : "q1",
"form" : "1",
"title": "What's your country?",
"options": [
{ "_id" : "o1", "question" : "q1", "text" : "Brazil" }
{ "_id" : "o2", "question" : "q1", "text" : "EUA" },
{ "_id" : "o3", "question" : "q1", "text" : "China" }
]
},
{ "_id" : "q2",
"form" : "1",
"title": "What your favorite color",
"options": [
{ "_id" : "o4", "question" : "q2", "text" : "Red" }
{ "_id" : "o5", "question" : "q2", "text" : "Blue" },
{ "_id" : "o6", "question" : "q2", "text" : "Green" }
]
},
{ "_id" : "q3",
"form" : "1",
"title": "Where do you live?",
"options": []
}
]
},
...
]
I've tried a lot of $lookup, $unwind, another $lookup and $project, but nothing give-me that result (forms with questions inside, questions with options inside).
Please, help me! :)
I think the around is querying the question
collection, looking up their question
s and grouping by form
, and finally lookup form and project, in that order.
This should do it. Keep in mind that _id
in the output of this aggregate is the form _id
.
db.question.aggregate([
{$match: {}},
{$lookup: {
from: 'option',
localField: '_id',
foreignField: 'question',
as: 'options'
}},
{$group: {
_id: "$form",
questions: {$push: {
title: "$title",
options: "$options",
form: "$form"
}}
}},
{$lookup: {
from: 'form',
localField: "_id",
foreignField: "_id",
as: 'form'
}},
{$project: {
name: {$arrayElemAt: ["$form.name", 0]},
questions: true
}}
]);
Actually.. this seems like a better alternative. It will return form
s with no question
s too.
db.form.aggregate([
{$match: {}},
{$lookup: {
from: 'question',
localField: '_id',
foreignField: 'form',
as: 'questions'
}},
{$unwind: {
path: "$questions",
preserveNullAndEmptyArrays: true
}},
{$lookup: {
from: 'option',
localField: 'questions._id',
foreignField: 'question',
as: 'options'
}},
{$group: {
_id: "$_id",
name: {$first: "$name"},
question: {$push: {
title: "$questions.title",
form: "$questions.form",
options: "$options"
}}
}}
])
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