Count records with missing keys using jq Count records with missing keys using jq bash bash

Count records with missing keys using jq


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.json1

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)) | lengthreduce (.items[] | select(has("charge")|not)) as $i (0;.+=1)


Here is a solution that uses a simple but powerful utility function worthy perhaps of your standard library:

def sigma(stream): reduce stream as $s (null; . + $s);

The filter you'd use with this would be:

sigma(.items[] | select(has("charge") == false) | 1)

This is very efficient as no intermediate array is required, and no useless additions of 0 are involved. Also, as mentioned elsewhere, using has is more robust than making assumptions about the value of .charge.

Startup file

If you have no plans to use jq's module system, you can simply add the above definition of sigma to the file ~/.jq and invoke jq like so:

jq 'sigma(.items[] | select(has("charge") == false) | 1)'

Better yet, if you also add def count(s): sigma(s|1); to the file, the invocation would simply be:

jq 'count(.items[] | select(has("charge") | not))'

Standard Library

If for example ~/.jq/jq/jq.jq is your standard library, then assuming count/1 is included in this file, you could invoke jq like so:

jq 'include "jq"; count(.items[] | select(has("charge") == false))'