I want to select some specific fields from a particular object in a nested array, achieved through mongoose/mongo.
Consider the data:
[
{
"_id": ObjectId("5ff4b728b6af610f0851d2a6"),
"totalScore": 500,
"totalCompleted": 100,
"monthly": [
{
year: 2021,
month: 8,
attempted: 10,
completed: 5,
score: 20,
}
],
},
]
I want to first get all the documents, and then inside the "monthly", I want to select only the ones which match month = 8, and return only the "score" field and ignore rest of the fields like "attempted", "completed", etc.
I have tried the following query so far:
db.collection.find({},
{
totalScore: 1,
"monthly": {
$elemMatch: {
year: 2021,
month: 8,
},
},
})
It returns all the keys of the entire "monthly" object. Like so:
[
{
"_id": ObjectId("5ff4b728b6af610f0851d2a6"),
"monthly": [
{
"attempted": 10,
"completed": 5,
"month": 8,
"score": 20,
"year": 2021
}
],
"totalScore": 500
},
]
But, what I want, is to only select the "score" field from the "monthly". So the result data would be:
[
{
"_id": ObjectId("5ff4b728b6af610f0851d2a6"),
"monthly": [
{
"score": 20,
}
],
"totalScore": 500
},
How should I approach this problem?
CodePudding user response:
This can be done with a simple aggregation using $map
and $filter
:
db.collection.aggregate([
{
$project: {
totalScore: 1,
monthly: {
$map: {
input: {
$filter: {
input: "$monthly",
as: "item",
cond: {
$eq: [
"$$item.month",
8
]
}
}
},
as: "item",
in: {
score: "$$item.score"
}
}
}
}
}
])
Example on mongoplayground: https://mongoplayground.net/p/5PbR49Ufxb5