Jq
- interactive jq github.com/ynqa/jnv
- reference jqlang.github.io/jq/manual
- playground provided by github.com/owenthereal/jqplay
def group_with(key; value): group_by(key) | map({key: first | key, value: value});
def PI: 1 | atan * 4;
Equivalent transformations
original | simplified |
---|---|
. \| $f |
$f |
[.[] \| $f] |
map($f) |
map($f) \| map($g) |
map($f \| $g) |
Additional definitions
def group_with(key; value):
group_by(key) | map({key: first|key, value: value});
def group_with(key): group_with(key; .);
list
to map(group $key -> $value(group values))
SQL operators/Joins
main builtins
# SQL-ish operators here:
def INDEX(stream; idx_expr):
reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);
def INDEX(idx_expr): INDEX(.[]; idx_expr);
def JOIN($idx; idx_expr):
[.[] | [., $idx[idx_expr]]];
def JOIN($idx; stream; idx_expr):
stream | [., $idx[idx_expr]];
def JOIN($idx; stream; idx_expr; join_expr):
stream | [., $idx[idx_expr]] | join_expr;
def IN(s): any(s == .; .);
def IN(src; s): any(src == s; .);
some definitions for explanation purposes
- Row
is any object, e.g. column -> value
- Table as sequence
is [Row]
- Table as map
is {$id: Row}
where $id
is function of Row
, it is idx_expr
in builtin definitions
INDEX
converts Table as a sequence
to Table as map
: $table | INDEX(idx_expr)
To convert Table as map
back to Table as sequence
you just need to get all values, which can be done by making stream from object: $table | .[]
. So INDEX
allows to index or re-index any tables: seqences and maps.
Also it seems INDEX($stream, $idx_expr)
can always be replaced with $stream | INDEX($idx_expr)
, so INDEX/2
is not needed.
JOIN
actually is hash join
, that is joining Table
(which is sequence or map) with Index
by idx_expr
applied to each of the Table
rows. After that, result is [$row1, $row2]
and can be mapped using join_expr
.
IN
is just checking whether element is present in sequence in SQL fashion:
IN/2
All in all it seems simpler to have following builtins
# SQL-ish operators here:
def INDEX(idx_expr):
reduce .[] as $row ({}; .[$row|idx_expr|tostring] = $row);
def JOIN($idx; idx_expr; join_expr):
map([., $idx[idx_expr]] | join_expr);
def JOIN($idx; idx_expr): JOIN($idx, idx_expr; .);
def IN(s): any(s == .; .);
in case join with arbitary predicate is required, CROSS
may be of help (not builtin). (($left
might be changed to input stream))
def CROSS($left; $right; on_expr; join_expr):
$left
| map(. as $x | $right | map([$x, .]) | .[])
| map(select(on_expr) | join_expr);
def CROSS($left; $right; on_expr): CROSS($left; $right; on_expr; .)
def CROSS($left; $right): CROSS($left; $right; true; .);
$left
and $right
, filters with on_expr
and maps pair of rows with join_expr
e.g.