Let's say I have a document like this:
{
_id: ObjectId("1234567890"),
author: "ABC1",
text:"this is a Post",
details: {
time: "14/05/2015",
Edit: "none"
},
comments: [
{
comment_text: "Hello",
user: "alan",
time:"20/05/2014 20:44"
},
{
comment_text: "Hi Every One",
user: "bob",
time:"20/05/2014 20:44"
},
{
comment_text: "Good morning , Alan",
user: "Alan",
time:"20/05/2014 20:44"
},
{
comment_text: "I'm bob",
user: "bob",
time:"20/05/2014 20:44"
},
],
category: "IT"
}
I want to build a query that returns this object but with only Bob's comments in the comments array.
{
author: "ABC1",
text:"this is a Post",
details: {
time: "14/05/2015",
Edit: "none"
},
comments: [
{
comment_text: "Hi Every One",
user: "bob",
time:"20/05/2014 20:44"
},
{
comment_text: "I'm bob",
user: "bob",
time:"20/05/2014 20:44"
},
],
category: "IT"
}
How can this be done?
- Using
$unwind
(and$match
) in an aggregation pipeline will get me the correct subdocuments, but not as an array of objects within the original document. - Using
$elemMatch
within a projection (withfind()
orfindOne()
) only returns the first matching comment (subdocument).
CodePudding user response:
You can use the $filter
operator in the $project
stage of an aggregation pipeline:
db.collection.aggregate([
{
$project: {
_id: 0,
author: 1,
text: 1,
details: 1,
category: 1,
comments: {
$filter: {
input: "$comments",
as: "comment",
cond: {
$eq: [
"$$comment.user",
"bob"
]
}
}
}
}
}
])