Guilherme Borges
Guilherme Borges

Reputation: 165

Convert array of objects into an array of values from that object

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 proposal

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

Answers (2)

Wernfried Domscheit
Wernfried Domscheit

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

SuleymanSah
SuleymanSah

Reputation: 17858

You can use aggregation framework:

$unwind

$group

db.test.aggregate([
  {
    "$unwind": "$archives"
  },
  {
    "$group": {
      "_id": "$_id",
      "archives": {
        "$push": "$archives.colour"
      }
    }
  }
])

Playground

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

Related Questions