$path
There are several “helpers” in OpenAF to help to “query” array of maps that help to make code cleaner. For a complete list (like $from) see on the end of this document.
$path is based on JMESPath library that makes it pratical to perform queries with just a string query but can be difficult to “read”. To help understanding JMESPath where is a quick guide.
Input
$path can be used to query both javascript maps and arrays. Let’s use an example of a map with an array that you can easily replicate:
var obj = io.listFiles(getOpenAFPath())
Now you can access the files array of the resulting map obj as well as any of the maps inside the files array:
isMap( obj )
// true
isArray( $path(obj, "files") )
// true
isMap( $path(obj, "files[0]") )
// true
$path(obj, "files[0].filename")
// openaf-sb
Queries
There are 6 main categories of queries:
Category | Description |
---|---|
Slicing | When querying arrays it’s possible to “slice” them in different ways (examples: the first five; from the third to the fifth; the first two; the last element; etc.). |
MultiSelect | As with projections it’s also possible to “project” multiple fields. |
Filters | It’s possible to apply simple conditions (including using functions) to query an array. |
Projections | Given the inputs it’s possible to “project” any fields necessary even if in keys. |
Pipe | Using the same unix “pipe” mechanism it’s possible to apply different categories of queries in sequence. |
Functions | It’s possible to apply a set of built-in functions over the queried fields and use the result also to build “filters” |
Slicing
Slicing arrays makes it easy to filter for specific records on an array:
$path([1,2,3,4,5,6,7,8,9,10], "[0:5]")
// [1, 2, 3, 4, 5]
$path([1,2,3,4,5,6,7,8,9,10], "[::2]")
// [1, 3, 5, 7, 9]
$path([1,2,3,4,5,6,7,8,9,10], "[::3]")
// [1, 4, 7, 10]
$path([1,2,3,4,5,6,7,8,9,10], "[::-1]")
// [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
$path([1,2,3,4,5,6,7,8,9,10], "[::-2]")
// [10, 8, 6, 4, 2]
$path([1,2,3,4,5,6,7,8,9,10], "[-1]")
// 10
$path([1,2,3,4,5,6,7,8,9,10], "[-5::]")
// [6, 7, 8, 9, 10]
$path([1,2,3,4,5,6,7,8,9,10], "[-5::2]")
// [6, 8, 10]
$path(obj, "files[0:5]") // or $path(obj.files, "[0:5]")
// An array with the first 5 elements
$path(obj, "files[:5]")
// Again, the same array with the first 5 elements
Multi-select
Given an input if nothing is specified all fields will be output. If you provide a specific field, only that one will be output. But it’s possible to specify multi-fields:
$path(obj, "files[].[filename, size]")
// an array where each element is another array where the first value is _filename_ and the second is _size_
$path(obj, "files[].{f: filename, s: size}")
// an array where each element is a map where _f_ is the value of 'filename' and _s_ is the value of 'size'
Filter
Given an input it’s possible to use the existing fields to filter the result:
$path(obj, "files[?size>`1000000`]")
// an array with the files whose size is bigger than 1MB
$path(obj, "files[?filename=='openaf.jar']")
// an array with one entry where filename is "openaf.jar"
$path(obj, "files[?filename=='openaf.jar'].size")
// an array with one entry with the size value of the filename is "openaf.jar"
Projections
Projecting specific fields from an array of maps:
$path(obj, "files[].filename")
// An array of each value of "filename" on the "files" array
$path([ { x: 1, y: -1 }, {x: 2, y: 2 } ], "[].x")
// [1, 2]
$path({ x: 1, y: -1, z: 0 }, "*")
// [1, -1, 0]
$path([ { point: { x: 1,y: -1 }, level: { x: -99, y: 99 } }, { point: {x: 2, y: 2 } } ], "[].*.x")
// [[ 1, -99], [ 2 ]]
Pipe
Very quickly you might need to apply a sequence of filters, slicing, multi-selects and projections:
$path(obj, "files[?size>`1000000`] | [?filename=='openaf.jar']")
// An array with the element whose 'filename' is "openaf.jar" and whose 'size' is bigger than 1MB
$path(obj, "files[?size>`1000000`] | [?filename=='openaf.jar'] | [0]")
// The first element of an array with the element whose 'filename' is "openaf.jar" and whose 'size' is bigger than 1MB
$path(obj, "files[?size>`1000000`] | [?filename=='openaf.jar'] | [0].filename")
// The 'filename' of the first element of an array with the element whose 'filename' is "openaf.jar" and whose 'size' is bigger than 1MB
$path(obj, "files[?size>`1000000`] | [?filename=='openaf.jar'] | [0] | @.filename")
// Same as the previous result
Functions
It’s possible to apply functions to fields and arrays on the expression used in $path:
Function | Description | Example |
---|---|---|
abs(number) | The absolute value of a numeric field | $path([{x:1,y:-1},{x:2,y:2}], "[].{y:abs(y)}") |
avg(arrayNumber) | The average value of an array of numeric fields | $path([ {x:1,y:-1}, {x:2,y:2} ], "avg([].y)") |
contains(string/array, any) | Returns true of false if a string field contains a specific value | $path(obj, "files[?contains(filename, 'openaf.jar') == `true`") |
ceil(numer) | Returns the smallest integer that is equal or less than a specific numeric field value | $path([{x: 1.2, y: -1.8},{x: 2.2, y: 2.0}], "[].ceil(y)") |
ends_with(string, array) | Returns true if a field has the provided suffix | $path(obj, "files[?ends_with(filename, '.jar')]") |
floor(number) | Returns the greatest integer that is equal or greater than a specific numeric field value | $path([ {x:1.2,y:-1.8}, {x:2.2,y:2.0} ], "[].floor(y)") |
join(string, arrayString) | Returns a delimited list with the values of a specific array field | $path(obj, "join(', ', files[].filename)") |
keys(object) | Returns a list of fields for a corresponding map | $path(obj, "keys(files[0])") |
length(string/array/object) | Returns the size of any array or list | $path(obj, "length(keys(files[0]))") |
map(expression, array) | Returns an array mapping | $path(obj, "map(&filename == 'openaf.jar', files[])" |
max(number) | Returns the maximum of a numeric field | $path(obj, "max(files[].size)") |
max_by(array, expression) | Returns the element for which the expression is the maximum | $path(obj, "max_by(files[], &size)") |
merge(object, object) | Returns the merge of two objects | $path([{x:1},{y:0}], "merge([0],[1])) |
min(number) | Returns the minimum of a numeric field | $path(obj, "min(files[].size)") |
min_by(array, expression) | Returns the element for which the expression is the minimum | $path(obj, "min_by(files[], &size)") |
not_null(any) | Returns the non-null value between the provided fields | $path([{a:null,b:1}, {a:2,b:null}], "[].not_null(a,b)") |
reverse(array) | Reverse the provided array | $path([1,2,3], "reverse(@)") |
sort(array) | Sorts the provided array | $path([3,1,2], "sort(@)") |
sort_by(array, expression) | Sorts the provided array by the provided expression | $path(obj, "sort_by(files[], &size)") |
starts_with(string, array) | Returns true if a field has the provided prefix | $path(obj, "files[?starts_with(filename, 'openaf.jar')]") |
sum(array) | Sums the numberic field of a provided array | $path(obj, "sum(files[].size)") |
to_array(any) | Transforms any input into an array | $path(obj, "to_array(`true`)") |
to_string(any) | Transforms any input into a string | $path(obj, "to_string(`123`)") |
to_number(any) | Transforms any input into a number | $path(obj, "to_number(`123`)") |
type(any) | Returns the type of any input | $path(obj, "type(to_number(`123`))") |
values(a) | Returns an array with all the values of a map | $path(obj, "values(files[0])") |
Other libraries in OpenAF
- $from - See more in $from
- $stream - Based on the old StreamJS library