jq group by property in array

2019-08-08 08:20发布

问题:

I have an input json document as so:

[
  {
    "Name": "one",
    "Tags": [
      {
        "Key": "Name",
        "Value": "important"
      },
      {
        "Key": "OtherTag",
        "Value": "irrelevant"
      }
    ]
  },
  {
    "Name": "two",
    "Tags": [
      {
        "Key": "OtherTag",
        "Value": "irrelevant2"
      },
      {
        "Key": "Name",
        "Value": "important"
      }
    ]
  },
  {
    "Name": "three",
    "Tags": [
      {
        "Key": "Name",
        "Value": "important2"
      },
      {
        "Key": "OtherTag",
        "Value": "irrelevant3"
      }
    ]
  }
]

I want to use jq to group the three records by tag Value where the Key = "Name". The result would be two arrays, one with two records in it and one with one. The array with two records would have two because both records share the same tag with a value of "important". Here is what the result would look like:

[
  [
    {
      "Name": "one",
      "Tags": [
        {
          "Key": "Name",
          "Value": "important"
        },
        {
          "Key": "OtherTag",
          "Value": "irrelevant"
        }
      ]
    },
    {
      "Name": "two",
      "Tags": [
        {
          "Key": "OtherTag",
          "Value": "irrelevant2"
        },
        {
          "Key": "Name",
          "Value": "important"
        }
      ]
    },
  ],
  [
    {
      "Name": "three",
      "Tags": [
        {
          "Key": "Name",
          "Value": "important2"
        },
        {
          "Key": "OtherTag",
          "Value": "irrelevant3"
        }
      ]
    }
  ]
]

I just can't figure out how to do this with jq. Does anyone have any ideas?

回答1:

Your proposed solution is fine, but if you don't mind converting the arrays of Key-Value pairs into objects, then the following can be used:

map( .Tags |= from_entries ) | group_by(.Tags.Name) 

This at least makes the "group_by" easy to understand; furthermore, it would be easy to convert the .Tags objects back to key-value pairs (with lower-case "key" and "value"):

map( .Tags |= from_entries ) | group_by(.Tags.Name)
| map(map( .Tags |= to_entries))

Key/Value capitalization

One way to recover the capitalized Key/Value tags would be to tweak the above as follows:

def KV: map( {Key: .key, Value: .value} );

map( .Tags |= from_entries ) | group_by(.Tags.Name)
| map(map( .Tags |= (to_entries | KV)))


标签: json bash shell jq