If you want to $slice the first array element only from the "inner" array of each member, then you apply it as such within a $map on the "outer" array:
db.collection.aggregate([
{ "$addFields": {
"posts": {
"$map": {
"input": "$posts",
"as": "p",
"in": {
"_id": "$$p._id",
"content": "$$p.content",
"comments": { "$slice": [ "$$p.comments", 1 ] }
}
}
}
}}
])
Which would return:
/* 1 */
{
"_id" : 1.0,
"name" : "Bob",
"posts" : [
{
"_id" : 1.0,
"content" : "the first post",
"comments" : [
{
"_id" : "1a",
"content" : "first comment on first post"
}
]
},
{
"_id" : 2.0,
"content" : "the second post",
"comments" : [
{
"_id" : "2a",
"content" : "first comment on second post"
}
]
}
]
}
If you just wanted the "element" instead of returning an array, then it's the same thing, but using $arrayElemAt instead:
db.collection.aggregate([
{ "$addFields": {
"posts": {
"$map": {
"input": "$posts",
"as": "p",
"in": {
"_id": "$$p._id",
"content": "$$p.content",
"comments": { "$arrayElemAt": [ "$$p.comments", 1 ] }
}
}
}
}}
])
Which would return:
/* 1 */
{
"_id" : 1.0,
"name" : "Bob",
"posts" : [
{
"_id" : 1.0,
"content" : "the first post",
"comments" : {
"_id" : "1a",
"content" : "first comment on first post"
}
},
{
"_id" : 2.0,
"content" : "the second post",
"comments" : {
"_id" : "2a",
"content" : "first comment on second post"
}
}
]
}
Noting that the main difference there ( aside from element vs array ) is in the usage, where $slice can be called asking just for the "length" of items to return, and optionally a starting index position, but here we just use the length.
For $arrayElemAt it is always just the "index", which is n-1 and always just a "singular element" as opposed to anything that could be a "list" or "array".
The whole point is that it is the "posts" array that you are doing the primary "reshaping" on, and to "reshape" an array you use $map and apply any transitions to each element.
I might add here that "current aggregation result" quite usually gives way to that there may well have been an opportunity to actually restrict the result before you actually got to that state. So it's quite often a good idea to go back and look at how your result was constructed to this point and look for the opportunity to return less if that is your actual intent.