'JQ: group by into single object with groups as keys

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!



Solution 1:[1]

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

Solution 2:[2]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 pmf
Solution 2 pmf