Home > Enterprise >  MongoDB - Move top field into each element of array
MongoDB - Move top field into each element of array

Time:10-07

I have the following MongoDB query:

db['foo'].aggregate([
{ $project: {
    frame: {
        frame_id: "$frameProfileId",
        sections: {
            $filter: {
                input: "$sections",
                cond: { $eq: [ "$$frameSection.metadata.subType", "Quaternion"] },
                as: "frameSection"
                }
            }
        }
    }
},
{ $unwind: "$frame"},
{ $replaceRoot: { newRoot: "$frame"}}
])

which produces:

[
  {
    frame_id: '366',
    sections: [
      {
        title: 'This is a bogus title',
        count: 1,
        metadata: {
          subType: 'Quaternion',
          edgeCount: 1
        }
      },
      {
        title: 'Plan b',
        count: 6,
        metadata: {
          subType: 'Quaternion',
          edgeCount: 1
        }
      }
    ]
  },
  { 
    frame_id: '388',
    sections: [
      {
        title: 'Another title',
        count: 14,
        metadata: {
          subType: 'Quaternion',
          edgeCount: 1
        }
      }
    ]
  }
]

What I want to accomplish is to move the frame_id inside the elements like so:

[
  {
    sections: [
      {
        frame_id: '366',
        title: 'This is a bogus title',
        count: 1,
        metadata: {
          subType: 'Quaternion',
          edgeCount: 1
        }
      },
      {
        frame_id: '366',
        title: 'Plan b',
        count: 6,
        metadata: {
          subType: 'Quaternion',
          edgeCount: 1
        }
      }
    ]
  },
  { 
    sections: [
      {
        frame_id: '388',
        title: 'Another title',
        count: 14,
        metadata: {
          subType: 'Quaternion',
          edgeCount: 1
        }
      }
    ]
  }
]

I had a go at $addField, $set, $push and $[] but I can't quite accomplish it in the context of a query like this.

CodePudding user response:

  1. $map - Iterate each document in filtered sections array and return a new array.

    1.1. $mergeObjects - Merge current iterated document with the document contains frame_id field.

db.collection.aggregate([
  {
    $project: {
      sections: {
        $map: {
          input: {
            $filter: {
              input: "$sections",
              as: "frameSection",
              cond: {
                $eq: [
                  "$$frameSection.metadata.subType",
                  "Quaternion"
                ]
              }
            }
          },
          in: {
            $mergeObjects: [
              "$$this",
              {
                frame_id: "$frameProfileId"
              }
            ]
          }
        }
      }
    }
  }
])

Demo @ Mongo Playground

  • Related