Construction and Reduce

Object Construction, Reduce and Group-By

{title, price} builds an object from fields of the input; {(expr): value} computes a key. reduce folds a stream into one value without holding it in memory, and with -n plus inputs it reads JSON Lines one record at a time. group_by(f) sorts an array and splits it into arrays of equal f, which needs the whole array in memory. The first command totals revenue by channel over all 100,000 sample orders; the second joins line items to titles loaded with --slurpfile and reports units and list-price revenue (before coupons) per book.

Revenue by channel with reduce, and per-book sales with group_by
jq -n 'reduce inputs as $o ({}; .[$o.channel] += $o.total) | map_values(. * 100 | round / 100)' \
  -c data/orders.jsonl
jq -n -c --slurpfile cat data/books.json '
  ($cat[0].books | map({(.id | tostring): .title}) | add) as $titles
  | [inputs | .items[]] | group_by(.book_id)[]
  | {title: $titles[.[0].book_id | tostring], units: (map(.qty) | add),
     revenue: (map(.qty * .unit_price) | add | . * 100 | round / 100)}' data/orders.jsonl
Output
{"ios":1557143.92,"android":1213501.62,"web":703849.87}
{"title":"The Quiet Harbor","units":49071,"revenue":735574.29}
{"title":"Patterns of the Deep Web","units":25168,"revenue":994136}
{"title":"Salt and Saffron","units":31730,"revenue":761520}
{"title":"Small Steps to Big Summits","units":5140,"revenue":96375}
{"title":"The Clockmaker's Paradox","units":35003,"revenue":567048.6}
{"title":"Gardens in Glass","units":16681,"revenue":355305.3}

. * 100 | round / 100 rounds to cents, because jq 133,477 's arithmetic is in doubles (Numbers and Precision): without it the channel totals print with long binary tails. as $titles binds a variable for the rest of the pipeline, the usual way to build a lookup table for a join.