To achieve this you would need to first unwind the comments, and then use a group with a little trick. If you want to omit the _id, then you would also need to do a simple project. Here is the full aggregation pipeline:
db.posttest.aggregate([
{ $unwind : "$comments" },
{ $group : {
_id : "$_id",
username : { $first : "$username" },
text : { $first : "$text" },
comments : { $push : "$comments" },
hasComments : { $max : { $eq : [ "$comments.username", "User1" ] } }
}},
{ $project : { _id : false } }
])
An explanation is following.
First, we need to get rid of an array (comments). To do this we unwind the record; it gives us four records:
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User1",
"text" : "hi"
}
},
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User2",
"text" : "hi1"
}
},
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User3",
"text" : "hi2"
}
},
{
"_id" : 21353456,
"username" : "xy",
"text" : "asdf",
"comments" : {
"username" : "User4",
"text" : "hi3"
}
}
Now we can group all the records into one applying a function to each field. First, we need to give criteria, the 'group by' field (or set of fields). In our case, it is simply the id: _id: "$_id".
Then, for each field, we need to make a decision on how to include it into the resulting record. We have few fields: username, text, and comments. For each four records the username and text are the same, so we can easily pick any of them, namely $first or $last.
comments, however, are different. We want to preserve all of them so that we $push each one back.
The hasComments is a bit tricky here: we need to check if at least one comment.username contains the username. We can use $eq: [...] here, it will give us some array, e.g. [true, false, false, false] or [false, false, true, false]. We would need to pick which value goes into the resulting record. In this case, we can use neither $first nor $last. However, $max will give us an appropriate result.