MongoDB newbie here.
I have a 'client' document that looks like this:
{
name: "myClient",
products: [{
name: "myProduct1",
environments: [{
name: "myEnvironment1",
changeLogs: [
{ "some": "fields21" },
{ "some": "fields22" }
]
},
{
name: "myEnvironment2",
changeLogs: [
{ "some": "fields11" },
{ "some": "fields12" }
]
}
]
},
{
name: "myProduct2",
environments: [{
name: "myEnv1",
changeLogs: [
{ "some": "fields1" },
{ "some": "fields2" }
]
},
{
name: "myEnv1",
changeLogs: [
{ "some": "fields3" },
{ "some": "fields4" }
]
}
]
}]
}
So a client has many products
, which has many environments
, which has many changeLogs
. I am looking to return a list of changeLogs
for a given environment, with only the environment._id
to go on.
I can find the correct client
document using just this _id
:
db.clients.find({'products.environments._id': ObjectId("5a1bf4b410842200043d56ff")})
But this returns the entire client
document. What I want is to return just the changeLogs
array from the environment with _id: ObjectId("5a1bf4b410842200043d56ff")
Assuming I have the _id
of the first environment
of the first product
, my desired output is the following:
[
{ "some": "fields21" },
{ "some": "fields22" }
]
What query would you recommend I use to achieve this?
Many thanks in advance for any help. The docs thus far have only been confusing, but I'm sure I'll get there in the end!
db.clients.aggregate([
{
$unwind: "$products"
},
{
$unwind: "$products.environments"
},
{
$match: { "products.environments._id": ObjectId("5a1bf4b410842200043fffff") }
},
{
$project: { _id: 0, changeLogs: "$products.environments.changeLogs" }
}
]).pretty()
Results in:
{
"changeLogs": [
{ "some": "fields21" },
{ "some": "fields22" }
]
}
For those finding that code confusing I found it very useful to just add one aggregate method at a time, look at the results, and then add then next method to the pipeline. Once the pipeline was complete I also experimented with removing intermediary steps to see if I could get the same results with less piping.