Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count records with missing keys using jq

Below is a sample output that is returned when calling an API:

curl "https://mywebsite.com/api/cars.json&page=1" |  jq '.' 

Using jq, how would one count the number or records where the charge key is missing? I understand that the first bit of code would include jq '. | length' but how would one filter out objects that contain or don't contain a certain key value ?

If applied to the sample below, the output would be 1

{
  "current_page": 1,
  "items": [
    {
      "id": 1,
      "name": "vehicleA",
      "state": "available",
      "charge": 100
    },
    {
      "id": 2,
      "name": "vehicleB",
      "state": "available",
    },
    {
      "id": 3,
      "name": "vehicleB",
      "state": "available",
      "charge": 50
    }
  ]
}
like image 940
the_darkside Avatar asked Nov 21 '17 19:11

the_darkside


1 Answers

Here is a solution using map and length:

.items | map(select(.charge == null)) | length

Try it online at jqplay.org

Here is a more efficient solution using reduce:

reduce (.items[] | select(.charge == null)) as $i (0;.+=1)

Try it online at jqplay.org

Sample Run (assuming corrected JSON data in data.json)

$ jq -M 'reduce (.items[] | select(.charge == null)) as $i (0;.+=1)' data.json
1

Note that each of the above takes a minor shortcut assuming that the items won't have a "charge":null member. If some items could have a null charge then the test for == null won't distinguish between those items and items without the charge key. If this is a concern the following forms of the above filters which use has are better:

.items | map(select(has("charge")|not)) | length

reduce (.items[] | select(has("charge")|not)) as $i (0;.+=1)
like image 108
jq170727 Avatar answered Sep 21 '22 10:09

jq170727