squinlan
squinlan

Reputation: 1805

How to use $map over an array of objects in an aggregation?

Given the following example collection:

{ _id: 1, name: 'One', attribute_bag: { lights: { type: 'basic', value: '8' }, doors: { type: 'basic', value: '7' } } }
{ _id: 2, name: 'Two', attribute_bag: { switches: { type: 'basic', value: '2' } } }
{ _id: 3, name: 'Three', attribute_bag: { windows: { type: 'basic', value: '8' }, color: { type: 'descriptive', value: 'blue' } } }

I've been trying to end up with the following:

{ _id: 1, name: 'One', lights: '8', doors: '7' }
{ _id: 2, name: 'Two', switches: '2' }
{ _id: 3, name: 'Three', windows: '8', color: 'blue' }

Using the aggregation framework I've tried:

      $replaceRoot: {
        newRoot: {
          $arrayToObject: {
            $map: {
              input: {$objectToArray: "$attribute_bag"},
              as: "attribute",
              in: ["$attribute.k", "$attribute.v.value"], 
    // alternatively {k: $attribute.k, v: $attribute.v}
            }
          }
        }
      }

And using $addFields + $unwind + $group. In both cases, I'm unable to pull off the combination of adding dynamic keys to the root document and pulling the 'value' field out of the embedded documents.

Upvotes: 2

Views: 5949

Answers (1)

mickl
mickl

Reputation: 49975

You need to use double dollar sign to refer to a variable, working example:

{
    $replaceRoot: {
        newRoot: {
            $mergeObjects: [
                { _id: "$_id", name: "$name" },
                {
                    $arrayToObject: {
                        $map: {
                            input: { $objectToArray: "$attribute_bag" },
                            in: [ "$$this.k", "$$this.v.value" ]
                        }
                    }
                }
            ]
        }
    }
}

Mongo Playground

Upvotes: 2

Related Questions