Home > Mobile >  How to promote/pull a child field up one level in mongo aggregation pipeline
How to promote/pull a child field up one level in mongo aggregation pipeline

Time:04-13

I have a collection that looks like this:

[
  {
    _id: ObjectId("6255a889fb63822bd51b0356"),
    answers: {
      "6255a889fb63822bd51b0326": {
        value: ObjectId("6255a889fb63822bd51b0329"),
        
      },
      "6255a889fb63822bd51b032a": {
        value: [
          ObjectId("6255a889fb63822bd51b0321"),
          ObjectId("6255a889fb63822bd51b032d")
        ],
        
      },
      "6255a889fb63822bd51b032e": {
        value: 2,
        comment: "hello",
        
      }
    },
    createdAt: ISODate("2022-03-12T17:27:53.890Z")
  }
]

I start my pipeline with

{
  $project: {
     _id: 0,
     answers: { $objectToArray: "$answers" },
     date: { $dateToString: { format: dateFormat, date: "$createdAt" } },
   },
},

and get a result like this:

[
  {
    answers: [
      {
        k: '6255a9a60fd8f862f4bd287f',
        v: {
          value: new ObjectId("6255a9a60fd8f862f4bd2882"),
          _id: new ObjectId("6255a9a60fd8f862f4bd28b2")
        }
      },
      {
        k: '6255a9a60fd8f862f4bd2883',
        v: {
          value: [
            new ObjectId("6255a9a60fd8f862f4bd287a"),
            new ObjectId("6255a9a60fd8f862f4bd2886")
          ],
          _id: new ObjectId("6255a9a60fd8f862f4bd28b3")
        }
      },
      {
        k: '6255a9a60fd8f862f4bd2887',
        v: {
          value: 2,
          comment: 'hello',
          _id: new ObjectId("6255a9a60fd8f862f4bd28b4")
        }
      }
    ],
    date: '2022-03-12'
  }
]

I want to pull value up and replace v with value so I wind up with a result that looks like this. I was thinking maybe there's some way to do it in the first step of $objectToArray? or do I need another step afterwards?

[
  {
    answers: [
      {
        k: '6255a9a60fd8f862f4bd287f',
        v: new ObjectId("6255a9a60fd8f862f4bd2882")
      },
      {
        k: '6255a9a60fd8f862f4bd2883',
        v: [
            new ObjectId("6255a9a60fd8f862f4bd287a"),
            new ObjectId("6255a9a60fd8f862f4bd2886")
          ]
      },
      {
        k: '6255a9a60fd8f862f4bd2887',
        v: 2
      }
    ],
    date: '2022-03-12'
  }
]

CodePudding user response:

You just need one more $map to wrangle to your desired form.

db.collection.aggregate([
  {
    $project: {
      _id: 0,
      answers: {
        "$map": {
          "input": {
            $objectToArray: "$answers"
          },
          "as": "a",
          "in": {
            k: "$$a.k",
            v: "$$a.v.value"
          }
        }
      },
      date: {
        $dateToString: {
          format: "%Y-%m-%d",
          date: "$createdAt"
        }
      }
    }
  }
])

This is the Mongo playground for your reference.

  • Related