OpenAF processor filters

The OpenAF processor filters are applied in the following order:

input data -> path=… -> apply transformers to data -> from=… -> sql=… -> output data


For more advanced cases they can also be applied in the following order:

input data -> ifrom=… -> isql=… -> path=… -> apply transformers to data -> from=… -> sql=… -> opath=… -> output data

🪚 Path

The path= filter tool is based on the JMESPath library. To see all the available options please refer to http://jmespath.org. Here are some examples:

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

  • “[0:5]”
  • “[5:10]”
  • ”[:5]”
  • ”[::2]”
  • ”[::-1]”

Projections

As with projections it’s also possible to “project” multiple fields.

  • “a[*].first”
  • “a.*.b”
  • ”[]”

Filters

It’s possible to apply simple conditions (including using functions) to query an array.

  • “a[?b==’xyz’].c”
  • “a[?b>1].x”

MultiSelect

As with projections it’s also possible to “project” multiple fields.

  • “a[].[x, y]”
  • “a[].{ x: x, y: y }”

Pipe

Using the same unix “pipe” mechanism it’s possible to apply different categories of queries in sequence.

  • “a[*].b [0]”

Functions

Function OpenAF Description Example      
a2m(arrFields, arrValues) 20240209 Builds a map given an array of fields and values a2m(k, v)      
a4m(arr, ‘key’, dontRemove) 20240209 Converts an array into a map a4m([], ‘name’, `true`)      
abs(number) base The absolute value of a numeric field [].{y:abs(y)}      
add(number, number) 20240217 Adds two numbers add(1, 2)      
amerge(x, y) 20240215 OpenAF’s merge with support for arrays amerge([], from_slon(‘(stamp:123)’))      
avg(arrayNumber) base The average value of an array of numeric fields avg([].y)      
ceil(number) base Returns the smallest integer that is equal or less than a specific numeric field value [].ceil(y)      
concat(x, y) 20240209 Concats arrays or strings concat(‘abc’, ‘123’)      
contains(string/array, any) base Returns true of false if a string field contains a specific value files[?contains(filename, ‘openaf.jar’) == true      
count_by(arr, ‘field’) all Returns a count by array with the ‘_count’ per value of the provided ‘field’ count_by([], ‘isFile’)      
date_diff(field, ‘unit’, nullval) 20240228 Given a date field will return the numeric difference to now for the provided unit (e.g. seconds, minutes, hours, days, months, weeks, years). Optionally a nullval will be used if no difference can be calculated date_diff(modifiedDate, ‘days’, ‘-1’)      
delete(map, ‘field’) all Remove a field from the provided map delete(data, ‘timestamp’)      
div(a, b) 20240217 Divides two numbers. div(6, 2)      
ends_with(string, array) base Returns true if a field has the provided suffix files[?ends_with(filename, ‘.jar’)]      
flat_map(x) all Returns a flat, one level, version of the provided map. flat_map(data)      
floor(number) base Returns the greatest integer that is equal or greater than a specific numeric field value [].floor(y)      
format(x, ‘format’) 20240209 OpenAF’s function $f (similar to printf) with type conversion format(to_number(123.12), ‘%05.0f’)      
formatn(x, ‘format’) 20240209 OpenAF’s function $ft (similar to printf) without type conversion format(string, ‘%10s’)      
from_bytesAbbr(x) 20240209 Given a string with a byte abbreviation will convert to bytes from_bytesAbbr(‘12GB’)      
from_datef(date, ‘format’) 20240228 Converts a date type into a string given a ‘format’ (equivalent to OpenAF’s ow.format.fromDate) from_datef(to_datef(‘20240202’, ‘yyyyMMdd’), ‘yyyy’)      
from_json(str) 20240215 Converts a json string representation into an object from_json(‘{a:123}’)”      
from_ms(x, ‘format’) 20240209 Shortcut for OpenAF’s ow.format.elapsedTime4ms function. The format is represented as a SLON/JSON string from_ms(12000,’(abrev:true)’)      
from_siAbbr(x) 20240209 Given a string with SI numeric abbreviation will convert it to the absolute value from_siAbbr(‘100m’)      
from_slon(obj) 20240215 Converts a slon string representation into an object from_slon(‘(abc: 123)’)      
from_timeAbbr(x) 20240209 Converts a time abbreviation into ms from_timeAbbr(‘12s’)      
get(nameOrPath) 20240305 Given a path to the original object or a name set by ‘set’ or ‘setp’ returns the corresponding value packages[].{name: name, version: version, parentVersion: get(‘version’) }      
group(arr, ‘field’) all Given an array will return a new array grouping the entries for each value of the provided field group(files, ‘isDirectory’)      
group_by(arr, ‘field1,field2’) all Given ar array will return a multi-level array grouping entries for each value of the provided fields (comma delimited) group_by(files, ‘isFile, permissions’)      
index_of(str, ‘search’) 20240209 Given a string will return the first index where the word ‘search’ occurs index_of(‘This is a test’, ‘test’)      
insert(obj, ‘field’, value) 20240302 Adds a ‘field’ with the corresponding value to the object.        
join(string, arrayString) base Returns a delimited list with the values of a specific array field join(‘, ‘, files[].filename)      
keys(object) base Returns a list of fields for a corresponding map keys(files[0])      
last_index_of(str, ‘search’) 20240209 Given a string will return the last index where the word ‘search’ occurs last_index_of(‘Test of a test’, ‘test’)      
length(string/array/object) base Returns the size of any array or list length(keys(files[0]))      
lower_case(str) 20240209 Given a string returns the lowercase converted version lower_case(‘AbC’)      
m2a(arrFields, obj) 20240209 Given an array of fields returns an array with the corresponding values of the provided object map. m2a(from_slon(‘[name size]’), @)    
m4a(obj, ‘key’) 20240209 Given an object map where each entry corresponds to a map will return an array of maps with the extra field ‘key’ representing the corresponding map entry. m4a(obj, ‘key’)      
map(expression, array) base Returns an array mapping map(&filename == ‘openaf.jar’, files[])      
match(str, ‘re’, ‘flags’) 20240209 Equivalent to javascript’s match function return a boolean value if a regular expression is matched to a string with optional flags match(‘abc 123’, ‘\d+’, ‘g’)      
max(number) base Returns the maximum of a numeric field max(files[].size)      
max_by(array, expression) base Returns the element for which the expression is the maximum max_by(files[], &size)      
merge(object, object) base Returns the merge of two objects merge([0],[1])      
min(number) base Returns the minimum of a numeric field min(files[].size)      
min_by(array, expression) base Returns the element for which the expression is the minimum min_by(files[], &size)      
mod(a, b) 20240217 Returns the modular of two numbers mod(5, 2)      
mul(a, b) 20240217 Multiplies two numbers mul(5, 2)      
not_null(any) base Returns the non-null value between the provided fields [].not_null(a,b)      
now(diff) 20240302 Returns the current unix timestamp number with a negative diff (or positive for dates in the future)        
nvl(field, value) 20240216 Returns the provided value in case a field value is undefined or null nvl(nullField, ‘n/a’)      
replace(str, ‘re’, ‘flags’, ‘replaceText’) 20240209 Equivalent to Javascript’s replace function that given a string will search for a regular expression, with the optional flags, a replace with the provided text replace(‘This is a test’, ‘ a’, ‘i’, ‘ not a’)      
reverse(array) base Reverse the provided array “reverse(@)”      
search_keys(arr, ‘text’) all Returns an array of entries where ‘text’ was found as part of an object property. search_keys(files, ‘filename’)      
search_values(arr, ‘text’) all Returns an array of entries where ‘text’ was found as part of an object property value. search_values(files, ‘.git’)      
set(obj, path) 20240305 Given an object will set the value to a name that it’s equal to it’s path set(@, ‘version’).packages[].{ name: name, parentVersion: get(‘version’) }      
setp(obj, path, name) 20240305 Given an object will set the value to a name given the provided path set(@, ‘version’, ‘ver’).packages[].{ name: name, parentVersion: get(‘ver’) }      
sort(array) base Sorts the provided array “sort(@)”      
sort_by(array, expression) base Sorts the provided array by the provided expression sort_by(files[], &size)      
split(str, ‘sep’) 20240209 Equivalent to the split Javascript’s function for a string given a separator split(@, ‘\n’)      
split_re(str, ‘re’) 20240228 Equivalent to the split Javascript’s function for a string given a regular expression separator split_re(@, ‘\s+’)      
split_sep(str, sep, arrEnc) 20240217 Given a string, a separator regexp and an array of pairs of enclosure chars split_sep(@, ‘\s+’, from_slon(‘[[’{‘ ’}’] [’(‘ ’)’]]’))
starts_with(string, array) base Returns true if a field has the provided prefix files[?starts_with(filename, ‘openaf.jar’)]      
sub(a, b) 20240217 Substracts two numbers sub(2, 2)      
substring(str, ini, end) all Given a string will return a sub-string starting on the initial index until the ending index substring(@, index_of(‘test’), 5)      
sum(array) base Sums the numberic field of a provided array sum(files[].size)      
t(obj, ‘template’) 20240228 Applies the Handlebars ‘template’ to the provided array or map t(@, ‘ ()’)      
tF(obj, ‘template’) 20240228 Applies the Handlebars ‘template’, with all OpenAF helpers, to the provided array or map tF(@, ‘: ‘)      
template(a, ‘template’) 20240209 Applies the Handlebars ‘template’ to the provided array or map t(@, ‘ ()’)      
templateF(x, ‘template’) 20240209 Applies the Handlebars ‘template’, with all OpenAF helpers, to the provided array or map tF(@, ‘: ‘)      
timeago(num) 20240209 Given a ms timestamp will return a human readable string of how log ago that timestamp occurred. files[].{path:filepath,howLongAgo:timeago(lastModified)}      
to_array(any) base Transforms any input into an array to_array(true)      
to_bytesAbbr(x) 20240209 Given an absolute number of bytes will return a string with unit abbreviation. to_bytesAbbr(12345678)      
to_date(x) 20240209 Tries to convert a value to a date to_date(createDate)      
to_datef(str, ‘pattern’) 20240228 Uses a Java date format to convert a string into a date to_datef(createDate, ‘yyyyMMdd’)      
to_isoDate(x) 20240209 Tries to convert a string into an ISO date format string to_isoDate( to_datef(createDate, ‘yyyyMMdd’) )      
to_json(obj, ‘space’) 20240215 Given an object will return the JSON string representation of it with the provided spacing to_json(@, ‘’)      
to_map(arr, ‘field’) all Given an array it will return a map where each entry is a property using the provided field with a map as value. to_map(files, ‘filename’)      
to_numAbbr(num) 20240209 Given an absolute number will return a string with SI abbreviation to_numAbbr(12345678)      
to_number(any) base Transforms any input into a number to_number(123)      
to_slon(obj) 20240215 Given an object will return the SLON representation of it. to_slon(@)      
to_string(any) base Transforms any input into a string to_string(123)      
trim(str) 20240209 Given a string will return a trimmed version of it trim(@)      
type(any) base Returns the type of any input type(to_number(123))      
unique(arr) all Given an array will return a new de-duplicated array. unique([])      
upper_case(str) 20240209 Given a string returns the uppercase converted version upper_case(‘AbC’)      
values(a) base Returns an array with all the values of a map values(files[0])      

Example:

# Given all AWS EC2 instances in an account produces a table with name, type, vpc and private ip sorted by vpn

aws ec2 describe-instances | ./oafp path="Reservations[].Instances[].{name:join('',Tags[?Key=='Name'].Value),type:InstanceType,vpc:VpcId,ip:PrivateIpAddress} | sort_by(@, &vpc)" output=ctable

🏹 From

Function
all
and
andBegin
andBetween
andBetweenEquals
andContains
andEmpty
andEnds
andEquals
andGreater
andGreaterEquals
andIs
andLess
andLessEquals
andMatch
andNot
andNotBetween
andNotBetweenEquals
andNotContains
andNotEmpty
andNotEnds
andNotEquals
andNotGreater
andNotGreaterEquals
andNotIs
andNotLess
andNotLessEquals
andNotMatch
andNotStarts
andNotType
andNotWhere
andStarts
andType
andWhere
any
apply
assign
at
attach
average
averageBy
begin
between
betweenEquals
cartesian
contains
count
countBy
define
detach
distinct
each
empty
end
ends
equals
except
filter
first
fnBy
greater
greaterEquals
group
groupBy
head
ignoreCase
intersect
is
join
last
less
lessEquals
limit
match
max
maxBy
min
minBy
mselect
none
not
notBetween
notBetweenEquals
notContains
notEmpty
notEnds
notEquals
notGreater
notGreaterEquals
notIs
notLess
notLessEquals
notMatch
notStarts
notType
notWhere
or
orBegin
orBetween
orBetweenEquals
orContains
orEmpty
orEnds
orEquals
orGreater
orGreaterEquals
orIs
orLess
orLessEquals
orMatch
orNot
orNotBetween
orNotBetweenEquals
orNotContains
orNotEmpty
orNotEnds
orNotEquals
orNotGreater
orNotGreaterEquals
orNotIs
orNotLess
orNotLessEquals
orNotMatch
orNotStarts
orNotType
orNotWhere
orStarts
orType
orWhere
pselect
query
removed
reverse
select
setWhere
skip
skipTake
skipWhile
sort
starts
stream
streamFn
sum
sumBy
tail
take
takeWhile
toDate
type
union
useCase
where

🤔 SQL

You can use simple SQL or H2 SQL. Althought you don’t need to refer the table the data can be refered from the ‘_TMP’ table.

Examples

# Simple SQL getting specific fields and ordering by one of them

curl -s https://api.github.com/repos/openaf/openaf/releases | oafp sql="select name, tag_name, published_at order by published_at" output=ctable

Using Path, From and/or SQL at the same time

Using path and from

# Using "path" to rename fields and then using "from" to limit the number of records

curl -s https://api.github.com/repos/openaf/openaf/releases | oafp path="[].{version:name, description:body}" from="limit(3)"

Use path to select a markdown field and parse it

# Get just the markdown body of the latest release and parsing it

curl -s https://api.github.com/repos/openaf/openaf/releases | oafp path="[0].body" output=md

Use path projections and SQL aggregation

# Use path to rename fields and the SQL to group by category of drink

curl -s "https://www.thecocktaildb.com/api/json/v1/1/search.php?s=martini" | oafp path="drinks[].{drink:strDrink,category:strCategory,alchool:strAlcoholic}" sql="select \"category\", count(1) \"count\" group by \"category\"" output=ctable