This little task turned out to be harder than I thought.
Consider the following very simple Posts collection. Suppose I want to display all the posts, coupled with o
I'll TL;DR since this turned out to be a hell of a ride. I've tried $elemMatch
, I've tried $redact
(also with $$CURRENT and $$ROOT), I've tried $map
, I've tried the aggregation framework, I've tried $project
.
You can read all about it here: https://www.devsbedevin.net/mongodb-find-findone-with-nested-array-filtering-finally/
The solution seems to be to use the aggregation framework to filter the array and override the comments property with the results. This is simpler than it sounds:
db.getCollection('posts').aggregate(
{$match: {"author.id": authorId}},
{$addFields : {"comments":{$filter:{ // We override the existing field!
input: "$comments",
as: "comment",
cond: {$eq: ["$$comment.state.deleted", false]}
}}}}
);
The result:
{
"author": {},
"message": "This is post1",
"comments": [
{
"message": "Im number 1!!!",
"state": {
"deleted": false
}
},
{
"message": "tHIS IS GREAT!",
"state": {
"deleted": false
}
},
{
"message": "I can type better than you guys",
"state": {
"deleted": false
}
}
]
},
{
"author": {},
"message": "This is post 2",
"comments": [
{
"message": "I wanna have your children",
"state": {
"deleted": false
}
}
]
}