Home > Mobile >  JQ: group by into single object with groups as keys
JQ: group by into single object with groups as keys

Time:05-06

I have the following data:

[
  {
    "company.u_ats_region": "Region1",
    "hostname": "host1",
    "install_status": "1",
    "os": "Windows",
    "os_domain": "test.com"
  },
  {
    "company.u_ats_region": "Region2",
    "hostname": "host2",
    "install_status": "1",
    "os": "Windows",
    "os_domain": "test.com"
  },
  {
    "company.u_ats_region": "Region3",
    "hostname": "host3",
    "install_status": "7",
    "os": "Windows",
    "os_domain": "test.com"
  }
]

And I've been using this query

{count: length,
 regions: [group_by(."company.u_ats_region")[] | 
          {( [0]."company.u_ats_region"): [.[] | 
          {name: (.hostname "." .os_domain), 
      os: .os}]}]}

to convert the data into the following:

{
  "count": 3,
  "regions": [
    {
      "Region1": [
        {
          "name": "host1.test.com",
          "os": "Windows"
        }
      ]
    },
    {
      "Region2": [
        {
          "name": "host2.test.com",
          "os": "Windows"
        }
      ]
    },
    {
      "Region3": [
        {
          "name": "host3.test.com",
          "os": "Windows"
        }
      ]
    }
  ]
}

This is close to what I'm trying to achieve but I would like 'regions' to be a single object with each region being a key within that object like this:

{
  "count": 3,
  "regions": {
      "Region1": [
        {
          "name": "host1.test.com",
          "os": "Windows"
        }
      ],
      "Region2": [
        {
          "name": "host2.test.com",
          "os": "Windows"
        }
      ],
      "Region3": [
        {
          "name": "host3.test.com",
          "os": "Windows"
        }
      ]
    }
}

I have tried playing around with 'add' but that still didn't bring me any closer to the result I'm trying to achieve. Any help is appreciated!

CodePudding user response:

Creating an object with key and value fields, then using from_entries would be one way:

{
  count: length,
  regions: group_by(."company.u_ats_region")
  | map({
      key: .[0]."company.u_ats_region",
      value: map({name: "\(.hostname).\(.os_domain)", os})
    })
  | from_entries
}
{
  "count": 3,
  "regions": {
    "Region1": [
      {
        "name": "host1.test.com",
        "os": "Windows"
      }
    ],
    "Region2": [
      {
        "name": "host2.test.com",
        "os": "Windows"
      }
    ],
    "Region3": [
      {
        "name": "host3.test.com",
        "os": "Windows"
      }
    ]
  }
}

Demo

CodePudding user response:

Using reduce to iteratively build up the arrays would be another way:

{
  count: length,
  regions: (
    reduce .[] as $i ({};
      .[$i."company.u_ats_region"]  = [$i | {name: "\(.hostname).\(.os_domain)", os}]
    )
  )
}
{
  "count": 3,
  "regions": {
    "Region1": [
      {
        "name": "host1.test.com",
        "os": "Windows"
      }
    ],
    "Region2": [
      {
        "name": "host2.test.com",
        "os": "Windows"
      }
    ],
    "Region3": [
      {
        "name": "host3.test.com",
        "os": "Windows"
      }
    ]
  }
}

Demo

  • Related