include parent field in child object array

Not entirely sure how to phrase this without confusing everyone.. i have tried with some "groups" and project" but didn't get too far.. however, given the following object:

[
    {
        "id": "61dbd1aef1eabf8d2dc9ac04",
        "name": "node01",
        "changeLog": [
            {
                "timestamp": "2014-09-27T03:00:00Z",
                "change": [
                    {
                        "type": "update",
                        "path": [
                            "node01",
                            "name"
                        ],
                        "from": "",
                        "to": "test"
                    }, 
                                {
                        "type": "update",
                        "path": [
                            "node01",
                            "size"
                        ],
                        "from": "tiny",
                        "to": "small"
                    }
                ]
            },
            {
                "timestamp": "2015-09-27T03:00:00Z",
                "change": [
                    {
                        "type": "update",
                        "path": [
                            "node01",
                            "name"
                        ],
                        "from": "test",
                        "to": "prod01"
                    }, 
                                {
                        "type": "update",
                        "path": [
                            "node01",
                            "size"
                        ],
                        "from": "",
                        "to": "medium"
                    }
                ]
            },
        ]
    }
]

How can i create an aggregate pipeline, to take the "parent" timestamp of each object into its child array, then merge that into a single array of objects.. i.e.

[
   {
      "id":"61dbd1aef1eabf8d2dc9ac04",
      "name":"node01",
      "changeLog":[
         {
            "change":[
               {
                  "timestamp":"2014-09-27T03:00:00Z",
                  "type":"update",
                  "path":[
                     "node01",
                     "name"
                  ],
                  "from":"",
                  "to":"test"
               },
               {
                  "timestamp":"2014-09-27T03:00:00Z",
                  "type":"update",
                  "path":[
                     "node01",
                     "size"
                  ],
                  "from":"",
                  "to":"sm"
               },
               {
                  "timestamp":"2015-09-27T03:00:00Z",
                  "type":"update",
                  "path":[
                     "node01",
                     "name"
                  ],
                  "from":"test",
                  "to":"prod01"
               },
               {
                  "timestamp":"2015-09-27T03:00:00Z",
                  "type":"update",
                  "path":[
                     "node01",
                     "size"
                  ],
                  "from":"small",
                  "to":"medium"
               }
            ]
         }
      ]
   }
]

Help is much appreciated!


Query

  • nested map to add the timestamp in
  • to add the updated field(timestamp) in the document, mergeObjects is used
  • reduce to concat all the arrays into 1 array with all the changes

*all changes go to 1 array, so you dont really need nested array, so query produces 1 array not nested, if you want to make it nested like 1 array with 1 element, you can do it with $set in 1 stage, i didnt do it because i think its simpler like this.

*if you want to update and not just aggregate you can use update pipeline, like
update({},[...pipeline_bellow...],{"multi" : true})

Test code here

aggregate(
[{"$set":
  {"changeLog":
   {"$map":
    {"input":"$changeLog",
     "in":
     {"$map":
      {"input":"$$log.change",
       "in":
       {"$mergeObjects":["$$ch", {"timestamp":"$$log.timestamp"}]},
       "as":"ch"}},
     "as":"log"}}}},
 {"$set":
  {"changeLog":
   {"$reduce":
    {"input":"$changeLog",
     "initialValue":[],
     "in":{"$concatArrays":["$$value", "$$this"]}}}}}])