Searching and testing - DarthJDG/Mangler.js GitHub Wiki
Another powerful feature of Mangler.js is checking if an object or value satisfies a test expression. A test expression is a JavaScript object literal with special properties, very similar to and inspired by MongoDB's .find() method.
Using test expressions, there are a number of different methods which help you filter and extract parts of your collection, as well as finding the first or last item that passes the test. Here are some quick examples:
stock = [
{
id: 1001,
name: 'Apple',
price: 0.50,
qty: 150,
tags: ['fruit', 'red'],
expiry: new Date('2014-06-16')
},
{
id: 1002,
name: 'Banana',
price: 1.20,
qty: 30,
tags: ['fruit', 'yellow', 'seedless'],
expiry: new Date('2014-07-10')
},
{
id: 1003,
name: 'Cherry',
price: 2.50,
qty: 220,
tags: ['fruit', 'red'],
expiry: new Date('2014-06-19')
},
{
id: 1004,
name: 'Grapes',
price: 0.80,
qty: 130,
tags: ['fruit', 'green', 'seedless'],
expiry: new Date('2014-07-12')
}
];
// Find cherries by ID and return object
cherry = Mangler(stock).first({ id: 1003 });
// Find all red fruit and put them in an array
red_fruit = Mangler.find(stock, { tags: ['red', 'fruit'] });
// Create mangler object then narrow down list to cheap seedless fruit
m = Mangler(stock).filter({ price: { $lt: 1.00 }, tags: ['seedless'] });Before looking at the test expressions in detail, here is a list of all the functions and methods of the Mangler.js library that can be used for querying and testing. The following parameter types will be used in the specification below:
| Type | Description |
|---|---|
<value> |
Any JavaScript value or object, e.g. string, number, object or array |
<test> |
Test expression |
<iterable> |
Any object that can be iterated by Mangler.each(), i.e. object, array and mangler object by default |
<integer> |
A whole number |
<function> |
A JavaScript function |
Many functions and methods below use Mangler.test(<value>, <test>) internally, which returns true if a <value> satisfies the <test> expression.
Utility functions for testing items contained in any iterable object, such as arrays:
-
Mangler.find(<iterable>, <test>)returns an array of all items in<iterable>that passes the<test>. -
Mangler.findOne(<iterable>, <test>)returns the first item of<iterable>that passes the<test>. -
Mangler.first(<iterable>, <test>)same asfindOneabove. -
Mangler.last(<iterable>, <test>)returns the last item of<iterable>that passes the<test>.
On a mangler object m = Mangler(data), you can use the following methods:
-
m.find(<test>)returns a new mangler object with all items that passes the<test>. -
m.findOne(<test>)returns a new mangler object with only the first item that passes the<test>. -
m.first(<test>)returns the first item that passes the<test>. -
m.last(<test>)returns the last item that passes the<test>. -
m.filter(<test>)removes all items from the mangler object that doesn't pass the<test>and returns a reference to the mangler object itself for method chaining.
A <test> expression can be one of the following:
-
Any simple value can be a test expression in itself and it's evaluated using the strict equality operator
===. For exampleMangler.test(5, 5)returns true, whileMangler.test(5, '5')returns false. - A regular expression, which evaluates to true if it matches the tested string.
Mangler.test('hello', /^h/)returns true. - An object literal with special properties. All properties are evaluated with an implied
andlogical relationship. - An array is interpreted as an implied $all operator.
- A function is interpreted as an implied $where operator.
Here's a complete list of the valid properties of a test object:
-
$gt, $gte, $lt, $lte, $eq and $ne are simple comparisons, corresponding to
>,>=,<,<=,===and!==respectively. Use it as{ $gt: <value> }- You can also use any comparison operator directly as a property name, e.g.
'<'. Note that this is the only way to use the non-strict operators'=='and'!='. Use it as{ '==': <value> }
- You can also use any comparison operator directly as a property name, e.g.
-
$or is true if any test expression in the passed array evaluates to true.
{ $or: [<test>, <test>, ...] } -
$all is true if the tested array contains all values passed.
{ $all: [<value>, <value>, ...] } -
$size is true if the tested array has matching length.
{ $size: <integer> } -
$elemMatch is true if any item in the tested array satisfies the test expression.
{ $elemMatch: <test> } -
$in is true if the tested array contains at least one passed value. If tested against a single value, it's true if value is in the passed array.
{ $in: [<value>, <value>, ...] } -
$not is the logical opposite of the passed test expression.
{ $not: <test> } -
$nin is shorthand for
{ $not: { $in: [<value>, <value>, ...] } } -
$nor is shorthand for
{ $not: { $or: [<test>, <test>, ...] } } -
$exists evaluates to the value passed if the tested value is not undefined.
{ $exists: true/false } -
$type checks the type with
Mangler.compareType().{ $type: <value> } -
$mod is true if
value % divisor === remainder. Use as{ $mod: [divisor, remainder] } -
$where evaluates to the return value of the passed function, called with the tested value as parameter.
{ $where: <function> } -
$aggregate passes the current value to
Mangler.aggregate()and checks the result against a test expression.{ $aggregate: [aggregator, <test>] }or{ $aggregate: [aggregator, options, <test>] } -
All other property names will be interpreted as either a named property on the tested object, or a path into the tested object. It will be evaluated using
.getPath(), then tested. Use it as{ property: <test> }or{ 'path.to.value': <test> }
Mangler.get(object, key) gets a single named property or array item from object.
Mangler.getPath(object, path) splits the path parameter to tokens and recursively calls Mangler.get() on object.
data = {
array: [{ value: 'example' }],
'special.property': true
};
// The following all return 'example'
Mangler.getPath(data, 'array[0].value');
Mangler.getPath(data.array, '[0].value');
Mangler.getPath(data.array[0], 'value');
// The following returns undefined, as it splits the path
Mangler.getPath(data, 'special.property');
// The following returns true, as it directly reads the named property
Mangler.get(data, 'special.property');