Reputation: 13
I have a query that returns json like this:
{
"hostname": "seapr1pgdb032",
"ip": "10.215.0.6",
"dataCenter": "seapr1"
}
{
"hostname": "seapr1cpndb001",
"ip": "10.203.0.41",
"dataCenter": "seapr1"
}
{
"hostname": "seapr1dhcp01",
"ip": "10.205.3.212",
"dataCenter": "seapr1"
}
The dataCenter can vary, I would like to collect all the hosts for each dataCenter into a single object like this:
{
"dataCenter": "seapr1",
"hosts": [
"seapr1pgdb032",
"seapr1cpndb001",
"seapr1dhcp01"
]
}
Working from Reshaping JSON with jq I thought this would do it:
{dataCenter: .dataCenter, hosts: [.hostname] }
but I get three dataCenter objects, not the single consolidated one I expected:
{
"dataCenter": "seapr1",
"hosts": [
"seapr1pgdb032"
]
}
{
"dataCenter": "seapr1",
"hosts": [
"seapr1cpndb001"
]
}
{
"dataCenter": "seapr1",
"hosts": [
"seapr1dhcp01"
]
}
Upvotes: 0
Views: 74
Reputation: 116670
Here is a jq solution that avoids the built-in group_by
filter for the reasons explained in the comments below.
# This stream-oriented variant of the built-in `group_by` emits a stream of arrays,
# each array representing a group. The main advantages over `group_by` are
# that no sorting is required, and the ordering of items within a group is preserved.
# There are no restrictions on f or the items in the stream;
# in particular, f may evaluate to any number of values,
# but if f evaluates to empty at any item in the stream, then that item will in effect be discarded.
# Example:
# GROUPS_BY( 4,3,2,1; . % 2 ) => [4,2] [3,1]
def GROUPS_BY(stream; f):
reduce stream as $x ({};
reduce [$x|f][] as $s (.;
($s|type) as $t
| (if $t == "string" then $s
else ($s|tojson) end) as $y
| .[$t][$y] += [$x] ) )
| .[][] ;
Using the -n command-line option, we can avoid "slurping" the input by writing the solution as follows:
GROUPS_BY(inputs; .dataCenter)
| {dataCenter: .[0].dataCenter, hosts: map(.hostname) }
Upvotes: 3