Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sorting, grouping and aggregation

Sorting

The order-by stage ^(...) sorts the items of a path. Sort keys are expressions evaluated against each item, and they must give numbers or strings. Strings sort by Unicode code point. A key prefixed with > sorts in descending order; <, the default, sorts in ascending order. Further keys, separated by commas, break ties. The sort is stable.

input: invoice.json
Account.Order.Product^(Price).`Product Name`
=> ["Trilby hat", "Bowler Hat", "Bowler Hat", "Cloak"]
input: invoice.json
Account.Order.Product^(>Price, <Quantity).{"name": `Product Name`, "qty": Quantity}
=> [
  {"name": "Cloak", "qty": 1},
  {"name": "Bowler Hat", "qty": 2},
  {"name": "Bowler Hat", "qty": 4},
  {"name": "Trilby hat", "qty": 1}
]
input: invoice.json
Account.Order.Product^(Price * Quantity).(Price * Quantity)
=> [21.67, 68.9, 107.99, 137.8]

$sort sorts an array with a comparison function, for orders that keys cannot express.

Grouping

An object constructor directly after a path (without .) groups the items: it evaluates the key for each item, and items with the same key fall into the same group. Then it evaluates the value once per group, with the group’s items as context. Aggregations therefore work per group:

input: invoice.json
Account.Order.Product{`Product Name`: Price}
=> {"Bowler Hat": [34.45, 34.45], "Trilby hat": 21.67, "Cloak": 107.99}
input: invoice.json
Account.Order.Product{`Product Name`: $round($sum($.(Price * Quantity)), 2)}
=> {"Bowler Hat": 206.7, "Trilby hat": 21.67, "Cloak": 107.99}

The value expression runs against the whole group. A path in it therefore collects values from all the group’s items. To build one object per item, map over the group with $.:

input: invoice.json
Account.Order.Product{`Product Name`: {"price": Price, "qty": Quantity}}
=> {
  "Bowler Hat": {"price": [34.45, 34.45], "qty": [2, 4]},
  "Trilby hat": {"price": 21.67, "qty": 1},
  "Cloak": {"price": 107.99, "qty": 1}
}
input: invoice.json
Account.Order.Product{`Product Name`: $.{"price": Price, "qty": Quantity}}
=> {
  "Bowler Hat": [{"price": 34.45, "qty": 2}, {"price": 34.45, "qty": 4}],
  "Trilby hat": {"price": 21.67, "qty": 1},
  "Cloak": {"price": 107.99, "qty": 1}
}

Keys must be strings (error T1003). Several key/value pairs can group the same items in different ways, and a group that evaluates to nothing is left out.

input: library.json
library.books{
  "cheap": $count($[price < 30]),
  "expensive": $count($[price >= 30]),
  "unpriced": $count($[$not($exists(price))])
}
=> {"cheap": 1, "expensive": 2, "unpriced": 1}

Aggregation

Aggregation functions reduce an array to one value:

input: invoice.json
$sum(Account.Order.Product.(Price * Quantity))
=> 336.36
input: invoice.json
{
  "orders": $count(Account.Order),
  "dearest": $max(Account.Order.Product.Price),
  "average quantity": $average(Account.Order.Product.Quantity)
}
=> {"orders": 2, "dearest": 107.99, "average quantity": 2}
input: invoice.json
$join(Account.Order.Product.`Product Name`, ", ")
=> "Bowler Hat, Trilby hat, Bowler Hat, Cloak"