Home > other >  How to count occurrences of a key-value pair per individual object in JQ?
How to count occurrences of a key-value pair per individual object in JQ?

Time:10-04

I could not find how to count occurrence of "title" grouped by "member_id"... The json file is:

[
 {
  "member_id": 123,
  "loans":[
   {
    "date": "123",
    "media": [
     { "title": "foo" },
     { "title": "bar" }
    ]
   },
   {
    "date": "456",
    "media": [
     { "title": "foo" }
    ]
   }
  ]
 },
 {
  "member_id": 456,
  "loans":[
   {
    "date": "789",
    "media": [
     { "title": "foo"}
    ]
   }
  ]
 }
]

With this query I get loan entries for users with "title==foo"

 jq '.[] | (.member_id) as $m | .loans[].media[] | select(.title=="foo") | {id: $m, title: .title}' member.json
{
  "id": 123,
  "title": "foo"
}
{
  "id": 123,
  "title": "foo"
}
{
  "id": 456,
  "title": "foo"
}

But I could not find how to get count by user (group by) for a title, to get a result like:

{
  "id": 123,
  "title": "foo",
  "count": 2
}
{
  "id": 456,
  "title": "foo",
  "count": 1
}

I got errors like jq: error (at member.json:31): object ({"title":"f...) and array ([[123]]) cannot be sorted, as they are not both arrays or similar...

CodePudding user response:

You don't need group_by here. Just aggregate all media where title is foo in an array and use its length as count.

"foo" as $title | .[] | {
  id: .member_id,
  $title,
  count: [.loans[].media[] | select(.title == $title)] | length
}

Online demo

CodePudding user response:

Using group_by :

jq  'map(
         (.member_id) as $m
        | .loans[].media[]
        | select(.title=="foo")
        | {id: $m, title: .title}
        )
    |group_by(.id)[]
    |.[0]   { count: length }
' input-file
  • Related