Reputation: 165
I have the following documents in my collection:
{
"archives" : [
{ "colour" : "red", "default" : true },
{ "colour" : "green", "default" : false }
]
}
{
"archives" : [
{ "colour" : "yellow", "default" : true }
]
}
I want to project the colour value from the archive objects as follows:
{
"archives" : [ "red", "green" ]
}
{
"archives" : [ "yellow" ]
}
My best attempt at this has been this query:
db.test.find({}, {
'archives': {
'$map': {
'input': '$archives',
'in': '$archives.colour'
}
}
})
But it's returning an array of arrays with redundant information, like so:
{ "archives" : [ [ "red", "green" ], [ "red", "green" ] ] }
{ "archives" : [ [ "yellow" ] ] }
So what would be the correct query to give the result I need, preferably on the database side, and as efficient as possible?
Upvotes: 1
Views: 487
Reputation: 59436
Why not simply this:
db.test.aggregate([
{ $set: { archives: "$archives.colour" } }
])
If you like to use $map
, then is would be this one. You missed the $$this
variable:
db.test.aggregate([
{
$set: {
archives: {
"$map": {
"input": "$archives",
"in": "$$this.colour"
}
}
}
}
])
or
db.test.aggregate([
{
$set: {
archives: {
"$map": {
"input": "$archives.colour",
"in": "$$this"
}
}
}
}
])
Upvotes: 2
Reputation: 17858
You can use aggregation framework:
db.test.aggregate([
{
"$unwind": "$archives"
},
{
"$group": {
"_id": "$_id",
"archives": {
"$push": "$archives.colour"
}
}
}
])
And if you don't want the _id in the output, you can exclude it by adding an additional $project stage:
db.test.aggregate([
{
"$unwind": "$archives"
},
{
"$group": {
"_id": "$_id",
"archives": {
"$push": "$archives.colour"
}
}
},
{
"$project": {
_id: 0
}
}
])
Upvotes: 2