AQL Manual
Description
API Query Language (AQL) is a filtering language designed for use in URIs with JSON data structures.
Usage
The strings used for filtering, e.g. 'eq(age,25)'
must be URI-encoded since this is designed for usage in the query string of a URI.
Paths are defined as JSONPath to look inside JSON objects.
const { filter, Operator } = require('@openreply/aql');
const customOperators = ({
hasKey: new Operator((evaluateSubexpression, collection, options, key) =>
collection.filter(item => Object.keys(item).includes(key))),
eq: new Operator((evaluateSubexpression, collection, options, path, value) =>
collection.filter(item =>
item[path] === value))
});
const collection = [
{
name: 'Isom Hamill',
age: 25,
phones: [
{ type: 'work', number: '012345' },
{ type: 'home', number: '012345' }
],
address: {
street: '7264 Kade Alley'
}
},
{
name: 'Lonzo Dooley',
age: 30,
phones: [
{ type: 'mobile', number: '032345' },
{ type: 'home', number: '042346' }
]
},
{
name: 'Bertrand Mertz',
age: 35
}
]
const result1 = filter('eq(name,Isom Hamill)')(collection);
const result2 = filter('includes(address.street,Kade)')(collection);
const result3 = filter('hasKey(phones)', customOperators)(collection);
const result4 = filter('all(phones.*,phone,startsWith(phone.number,01))')(collection)
const result5 = filter('any(phones.*,phone,eq(phone.type,home))')(collection)
Operators
These operators are defined by default:
eq(path, value)
: The item at path
must have the value value
.
ne(path, value)
: The item at path
must have a value different from value
.
in(path, value1, value2, ...)
: The item at path
must have one of the specified values.
out(path, value1, value2, ...)
: The item at path
must not equal to any the specified values.
gt(path, value)
: The item at path
must be greater than value
.
ge(path, value)
: The item at path
must be greater than or equal to value
.
lt(path, value)
: The item at path
must be less than value
.
le(path, value)
: The item at path
must be less than or equal to value
.
startsWith(path, prefix)
: The item at path
must have the prefix prefix
.
endsWith(path, suffix)
: The item at path
must have the suffix suffix
.
includes(path, value)
: The string/number item at path
must include the infix value
OR the array at path
must contain the value value
.
and(condition1, condition2, ...)
: All the conditions must hold.
Example: and(includes(name,o),ge(age,30))
filters items that include an o
in the name and with age greater than or equal to 30.
or(condition1, condition2, ...)
: At least one of the conditions must hold.
Example: or(eq(phones.0.type,work),eq(phones.0.type,mobile))
filters items that either have a work phone or a mobile phone as the first phones entry.
all(path, binding, condition)
: For all of the items binding
that match path
, the condition
must hold and there must be at least one item that matches path
.
Example: all(phones.*,phone,startsWith(phone.number,01))
filters items that have at least one phone number and all of the existing phone numbers of the item must start with 01
.
any(path, binding, condition)
: For at least one of the items binding
that match path
, the condition
must hold.
Example: any(phones.*,phone,eq(phone.type,home))
filters items that have at least one phone that has the type home
.
If the actual value at path
is a number, value
(or value*
) is coerced to a number.
Extensions
New AQL operators can be added by providing a customOperators
function to the filter function:
const { filter, Operator } = require('@openreply/aql');
const customOperators = collection => ({
hasKey: new Operator((evaluateSubexpression, collection, options, key) =>
collection.filter((item) => Object.keys(item).includes(key))),
});
const filteredCollection = filter('hasKey(phones)', customOperators)(fullCollection);
The customOperators
function takes the collection as its only argument and returns an object with the operators.
The keys this object define the name of the operator.
If a key is used that is already defined in the default set of operators, the default will be overridden.
Each operator takes an options
object as the first argument. It contains information on how the operator should be modified.
The other arguments of the operator are free and can be defined and used by the operator itself.
The return value of an operator is expected to be an Array that has the filter condition applied.
Acknowledgement
Special thanks to persvr for creating the RQL. This package is heavily insprired by it.
The main difference is that AQL is using JSONPath instead of a custom path language and AQL does not sort nor aggregate.
License
This project is licensed under the MIT license.