I am new to MongoDB and I’m struggling in extract a subdocument from a document.
In my case, I have the following schema:
[
{
user_id: "u1",
subscriptions: [
{
"tier": "Basic",
"requests": [
{
"name": "aaaa"
},
{
"name": "bbbb"
}
]
},
{
"tier": "Premium",
"requests": [
{
"name": "cccc"
},
{
"name": "dddd"
}
]
}
]
},
{
user_id: "u2",
subscriptions: [
{
"tier": "Premium",
"requests": [
{
"name": "eeee"
},
{
"name": "ffff"
}
]
}
]
}
]
In my case I would like to get ONLY the list of requests for user 1.
This is what I would like to get :
[
{ "name": "aaaa" },
{ "name": "bbbb" },
{ "name": "cccc" },
{ "name": "dddd" }
]
How can I fix it ?
4
Answers
Use
$unwind
and then$project
mongoplayground
A simple way will be:
As you can see on the playground
The
$unwind
separates the array elements into single documents. The$project
allows to format the documentWith the aggregation framework, you can create a pipeline that first filters out documents in the collection with the given condition using the following
a
$match
pipelineThe next pipeline will need to display the desired output using
$project
pipeline stage and the expression to achieve this will use a $reduce array operator.This operator enables you to flatten the 2d array expression
'$subscriptions.requests'
which mongo resolves from thisby concatenating the inner arrays with [
$concatArrays
] operator 3 to justwithout the need to introduce a couple of
$unwind
steps which can potentially be a huge performance cost when you have large arrays because it produces a copy of each document per array entry, which uses more memory (possible memory cap on aggregation pipelines of 10% total memory) and thus also takes time to produce/process and that’s not really necessary.The
$reduce
expression in this case becomesThus your overall aggregation operation follows:
Mongo Playground
Result will be