Search code examples
arraysmongodbaggregation-frameworkdata-sciencedata-analysis

mongodb - transform an array of objects (key: 'keyname', value:'value') into fields named 'keyname' with corrresponding value


The current structure of my mongodb documents is:

{
  "_id": "5c9376110a32bd172c0c5a28",
  "timestamp": 1553168075444,
  "content": [
    {
      "name": "temperature_x",
      "value": 2
    },
    {
      "name": "temperature_y",
      "value": 2
    },
    {
      "name": "temperature_z",
      "value": 0
    }
  ]
},
{
  "_id": "5c9376110a32bd172c0c5a28",
  "timestamp": 1553168075444,
  "content": [
    {
      "name": "temperature_x",
      "value": 2
    },
    {
      "name": "vibration_x",
      "value": 21
    },
    {
      "name": "vibration_z",
      "value": 10
    }
  ]
}

I'd like to obtain a queryable shortcut (a view?), that I'll query with python to make data-analysis/data-science, where the desired document structure is:

{
  "_id": "5c9376110a32bd172c0c5a28",
  "timestamp": 1553168075444,
  "temperature_x": 1,
  "temperature_y": 2,
  "temperature_z": 0
},
{
  "_id": "5c9376110a32bd172c0c5a28",
  "timestamp": 1553168075444,
  "temperature_x": 2,
  "vibration_y": 21,
  "vibration_z": 10
}

Any help is welcome

Thank you

A


Solution

  • You can use below aggregation

    db.collection.aggregate([
      { "$replaceRoot": {
        "newRoot": {
          "$mergeObjects": [
            "$$ROOT",
            { "$arrayToObject": {
              "$map": {
                "input": "$content",
                "in": {
                  "k": "$$this.name",
                  "v": "$$this.value"
                }
              }
            }}
          ]
        }
      }},
      { "$project": { "content": 0 }}
    ])
    

    Output

    [
      {
        "_id": ObjectId("5a934e000102030405000000"),
        "temperature_x": 2,
        "temperature_y": 2,
        "temperature_z": 0,
        "timestamp": 1.553168075444e+12
      },
      {
        "_id": ObjectId("5a934e000102030405000001"),
        "temperature_x": 2,
        "timestamp": 1.553168075444e+12,
        "vibration_x": 21,
        "vibration_z": 10
      }
    ]