Proposed syntax.
Internally, this prepares the predicate for an array.filter() operation.
.where( propertyName ) : Start query. Returns query object.
.and( propertyName ) : Continues query with logical AND. Returns query object.
.or ( propertyName ) : Continues query with logical OR. Returns query object.
.startsWith(), .endsWith() : Adds string start/end match comparison to the query. Returns query object.
.includes() : Adds substring match to the query. Returns query object.
.is()|.isGreaterThan()|.isLessThan() : Adds value comparison to the query. Returns query object.
Internally, this executes and returns the result of an array.filter() operation. If a specific set of properties is requested, an array.map() is also performed.
.get ([property1, property2, …]) : Executes query. If properties are specified, returns only those properties.
Internally, these result in an array.sort() operation.
.sortBy() : Sorts by given property in ascending order.
.sortAscendingBy() : Alias for sortBy()
.sortDescendingBy() : Sorts by given property in descending order.
Internally, these result in an array.reduce() operation.
.groupBy() : Groups the result by the passed property. Returns array.
.sum() : Reduces to the sum of the given property. Returns a numerical value.
.average() : Reduces to the average of the given property. Returns a numerical value.
.expectOne() : Returns the only item in the array. If array has more than one item, throws.
.expectMany() : Returns array. If array has no items or one item, throws.
.expectNone() : Returns null. If array is not empty, throws.
.expect(n) : Returns the array with N items. If array.length !== n, throws.
require('@small-tech/whatdb')
const people = [
{ name: 'Aral', pet: {type: 'dog', name: 'Oskar'}, likesToPlay: 'RimWorld' },
{ name: 'Laura', pet: {type: 'dog', name: 'Oskar'}, likesToPlay: 'Dishonored 2'}
]
let person
person = people
.where('name')
.is('Laura')
.and('pet.name')
.is('Oskar')
.get()
// Returns [ { name: 'Laura', pet: {type: 'dog', name: 'Oskar'}, likesToPlay: 'Dishonored 2'} ]
try {
person = people.where('pet.type').is('dog').and('likesToPlay').includes('World').get('name').expectOne()
} catch (error) {
// e.g., if there is more than one.
console.log(`Query error: ${error}`)
}
// Returns: {name: 'Aral'}
// With get('name.value') instead, would return the string value: 'Aral'
Yea, me neither.. exactly. There should be some way to exclude from a query, that is still intuitive wrt query syntax already adopted. I typed this just off the top of my head. Let's see..
This can certainly be improved.. looks a bit contrived. Note the
isNot(null)to check for existence of a nested object, where in 3rd example it is unclear what a missingwhere('company.minWage')indicates. You might need a.exists()in that case, maybe. I thought of thenot()as just a general way to negate whatever comes after it.The
andNot().is()could also be aand().isNot(), butandNot()leaves more options for what comes after it and might improve readability in some cases. The lastnot()certainly looks contrived, and should be anandNot('lastname').