objql-object-query-language

3.2.0 • Public • Published

npm

ObjQL

ObjQL is a helpful library allowing you to select particular entries from a collection, i.e., an array of objects. An example of code using that is below:

const collection = [
    {name: 'Adam', age: 18},
    {name: 'Adam', age: 42},
    {name: 'Mark', age: 19},
    {name: 'Joseph', age: 34},
    {name: 'Jack', age: 42},
    {name: 'Michael', age: 24}
];

const results = ObjQL
    .from(collection)
    .select('*')
    .where({
        age: 18
    })
    .sort('name')
    .limit(2,3);

// => [{name: 'Adam', age: 18}]

Currently, the select() method only supports '*' as a first parameter.
It will change in one of the future releases.

Methods must be called in the following order: from(), select(), where(), sort() and limit(). The last two may be omitted, however.

Installation

npm i objql-object-query-language

Compound fields

Items in a collection can have additional fields added. To do so, use a callback as a second parameter of the select() method.

.select('*', item => ({
    desc: `${item.name} being ${item.age} having a ${item.extra}`
}))

Dependencies of compound fields

When some field doesn't have some property, a compound field may have a value that contains undefined, what might not be intended.

As a third parameter of the select() method, you can pass an array of strings - property names that all must be present in item to add compound properties.

.select('*', item => ({
    desc: `${item.name} being ${item.age} having a ${item.extra}`
}), ['name', 'age', 'extra'])

Shortcuts for Functions

Function Shortcut
{name: ObjQL.equal('John')} {name: 'John'}
{name: ObjQL.regExp(/^J/)} {name: /^J/}
group: ObjQL.in(['A', 'B', 'C']) {group: new Set(['A', 'B', 'C'])}
{age: ObjQL.range(20, 32)} {age: [20, 32]}

Functions

General

Function Purpose Example
equal(value, strict?=true) match value that equals another one {age: ObjQL.equal('20', false)}
is(value) match value that is equal to another one (uses Object.is()) {result: ObjQL.is(NaN)}
in(valuesArray) match value that equals one from an array {group: ObjQL.in(['A', 'B', 'C', 'D'])}
range(min, max) match value that is from the range <min;max> {age: ObjQL.range(15, 25)}
regExp(re) match value that matches to a regular expression {name: ObjQL.regExp(/^.A/i)}
like(pattern) match value that matches to a pattern (% means 0+ chars, _ means 1 char) {name: ObjQL.like('%A_a_')}
ref(anotherField) match value by a value of other field {name: ObjQL.ref('fatherName')}
match(fn) match value by a custom condition {name: ObjQL.match((val, rec) => val === rec.surname)}
size(numberOrRange) match value by its length or size {term: ObjQL.size([20, null])}
likeArray(valuesArr) match value that is an array containing all the values from the array passed to the matcher (meanwhile can contain other values) {flags: ObjQL.likeArray(['canWrite', 'canEdit'])}
likeExactArray(valuesArr, checkIndexes?=false) match value that is an array containing all the values from the array passed to the matcher (meanwhile can't contain other values) {badges: ObjQL.likeExactArray(['Freshman'])}

The match() matcher

A callback passed to the match() matcher can accept up to 4 parameters:

  • value of a field in a current record
  • entire current record
  • index of the current record in the entire collection
  • entire collection
// get items followed by another item whose
// `result` property is greater than or equal to
// the `result` property of the current item

ObjQL.from(collection)
.select('*')
.where({
    name: ObjQL.match((name, item, idx, coll) => {
        return (
            coll[idx+1] &&
            coll[idx+1].result >= item.result
        );
    })
})

Strings

Function Purpose Example
firstChar(char) match value by the first character {city: ObjQL.firstChar('A')}
lastChar(char) match value by the last character {city: ObjQL.lastChar('Z')}
nthChar(char, position) match value by the n-th character {city: ObjQL.nthChar('D', 3)}
startsWith(substr, caseSensitive?=true) match value by the beginning {city: ObjQL.startsWith('Los')}
endsWith(substr, caseSensitive?=true) match value by the end {city: ObjQL.endsWith('os')}
contains(substr, caseSensitive?=true) match value by a substring {city: ObjQL.contains('yo')}

Date

There are functions checking date that can be represented by:

  • a particular value (e.g., month(4) to match April)
  • an instance of the Date()
  • a timestamp (a number of milliseconds that have passed from 01.01.1970 00:00:00)
  • a string in one of the following formats:
    • YYYY-MM-DD HH:mm:ss.uuu
    • DD.MM.YYYY HH:mm:ss.uuu
    • MM/DD/YYYY HH:mm:ss.uuu
  • the ObjQL.CURRENT constant

When it comes to the latest three, the following parts are optional: entire time part (HH:mm:ss.uuu), seconds with milliseconds (ss.uuu) and milliseconds (uuu).

Function Purpose Example
day(dayIndexOrRange) match value by a day in date {birth_date: ObjQL.day(20)}
month(monthIndexOrRange) match value by a month in date {birth_date: ObjQL.month(12)}
year(fullYearOrRange) match value by a full year (e.g., 1998 rather than 98) {registered: ObjQL.year(2010)}
hour(hourOrRange) match value by an hour {orders: ObjQL.hour(15)}
minute(minuteOrRange) match value by a minute {orders: ObjQL.minute(30)}
second(secondOrRange) match value by a second {lap: ObjQL.second(10)}
millisecond(msOrRange) match value by a millisecond {click: ObjQL.millisecond(12)}
date(dateFormat, dateValue) match value by a date {birth_date: ObjQL.date('DD.MM', '14.02')}
weekDay(weekDayIndexOrRange) match value by a week day (1=Monday, 7=Sunday) {weekend_visits: ObjQL.weekDay(6)}

The dateFormat parameter in the date() method can consist of the following parts: YYYY - full year, MM - month, DD - day, HH - hour, mm - minute, ss - second, uuu - millisecond.

Examples of matching date

  • match entries where the start_date field is date whose month is April
where({
    start_date: ObjQL.month(4)
})
  • match entries where the start_date field is date whose day is 14th and month is February
where({
    start_date: ObjQL.date('DD.MM', '14.02')
})

Note that the second parameter may be the standard date. In such a case, it does not have to match a format given as the first parameter. Elements from the first parameter will be used to compare dates:

where({
    // pass entire date
    // but only compare day and month
    start_date: ObjQL.date('DD.MM', '2020-02-14 15:45:30')
})
  • match entries where the event_date field is date whose week day is Friday, Saturday or Sunday
where({
    event_date: ObjQL.weekDay([5, 7])
})

Array of Numbers

Function Purpose Example
min(numberOrRange) match value by minimum value(s) in an array {height: ObjQL.min([180, null])}
max(numberOrRange) match value by maximum value(s) in an array {weight: ObjQL.max(100)}
avg(numberOrRange) match value by average value(s) of an array {test: ObjQL.avg([4, 5])}
sum(numberOrRange) match value by sum of an array items {width: ObjQL.sum(24)}
count(item, numberOrRange) match value by a number of item occurencies {comment: ObjQL.count('fuc', [null, 3])}
unique(numberOrRange) match value by a number of unique items {awards: ObjQL.unique([10, 50])}

Example ranges:

  • count('a', [1, 4]) - a number of occurencies of a >= 1 and <= 4
  • count('a', [2, null]) - a number of occurencies of a >= 2
  • count('a', [null, 5]) - a number of occurencies of a <= 5

How do min()/max() work?

const collection = ObjQL.from([
    {name: 'John', marks: [3, 4, 6]},
    {name: 'Mark', marks: [2, 3, 5]}
]);



const result = collection.select('*').where({
    marks: ObjQL.min(2)
});
// only Mark has been matched
// John has not as his minimum value is 3

const result2 = collection.select('*').where({
    marks: ObjQL.min([2, 4])
});
// both Mark and John have been matched
// given minimum value is from the range 2-4



const result3 = collection.select('*').where({
    marks: ObjQL.min([null, 2])
});
// only Mark has been matched
// minimum value must be less or equal to 2 [null, 2]

const result4 = collection.select('*').where({
    marks: ObjQL.min([2, null])
});
// both Mark and John have been matched
// minimum value must be greater or equal to 2 [2, null]

Objects

Function Purpose Example
hasKey(keyName) match object that has a given key {config: ObjQL.hasKey('language')}
hasKeys(keyNamesArr, mode) match object that has the given keys: all (if mode equals ALL, it's default value) or some (if mode equals SOME) {theme: ObjQL.hasKeys(['color', 'background'], 'SOME')}
hasValue(value) match object that has a given value {theme: ObjQL.hasValue('pink')}
hasValues(valuesArr, mode) match object that has the given values, all or some depending on mode (ALL being default value or SOME) {config: ObjQL.hasValues(['PL', 'FR'], 'SOME')}
hasProp(keyName, value) match object that has a given key equal to given value {theme: ObjQL.hasProp('color', 'red')}
hasProps(pairArr, mode) match object that has the given keys equal to a respective value (depending on mode: ALL (default) or SOME) {config: ObjQL.hasProps([['language', 'PL'], ['location', 'Poland']])}

Types

Function Purpose Example
isType(type) match value by the type (uses Object#toString(), matching is case insensitive) {pattern: ObjQL.isType('regexp')}
isInstanceOf(klazz) match value that is instance of the given class {publishedAt: ObjQL.isInstanceOf(Date)}
isNull() match value that equals null {projects: ObjQL.isNull()}
isUndefined() match value that is undefined {dob: ObjQL.isUndefined()}
isTruthy() match value that is truthy {results: ObjQL.isTruthy()}
isFalsy() match value that is falsy {skills: ObjQL.isFalsy()}
isInteger() match value that is an integer {progress: ObjQL.isInteger()}
isFloat() match value that is a float {average: ObjQL.isFloat()}

Package Sidebar

Install

npm i objql-object-query-language

Weekly Downloads

1

Version

3.2.0

License

ISC

Unpacked Size

55.5 kB

Total Files

70

Last publish

Collaborators

  • damianc