validate objects & filter arrays with mongodb queries
For extended documentation, checkout http://docs.mongodb.org/manual/reference/operator/query/
Features:
- Supported operators: $in, $nin, $exists, $gte, $gt, $lte, $lt, $eq, $ne, $mod, $all, $and, $or, $nor, $not, $size, $type, $regex, $where, $elemMatch
- Regexp searches
- Function filtering
- sub object searching
- dot notation searching
- Supports node.js, and web
- Small (2 kb minified) library
- Custom Expressions
- filtering of immutable datastructures
Node.js Examples
var sift = require('sift');
var sifted = sift({ $in: ['hello','world'] }, ['hello','sifted','array!']);
var sifted = sift(/^j/, ['craig','john','jake']);
var testQuery = sift({
name: function(value) {
return value.length == 5;
}
});
[{
name: 'craig',
},
{
name: 'john'
},
{
name: 'jake'
}].filter(testQuery);
testQuery({ name: 'sarah' });
testQuery({ name: 'tim' });
Browser Examples
<html>
<head>
<script src="https://raw.github.com/crcn/sift.js/master/sift.min.js" type="text/javascript"></script>
<script type="text/javascript">
var sifted = sift(/^j/, ['craig','john','jake']);
</script>
</head>
<body>
</body>
</html>
API
.sift(filter[, array][, selectorFn])
filter
- the filter to use against the target arrayarray
- sifts against target array. Without this, a function is returnedselectorFn
- selector for the values within the array.
With an array:
sift({$exists:true}, ['craig',null]);
Without an array, a sifter is returned:
var siftExists = sift({$exists:true});
siftExists(['craig',null]);
With a selector:
var sifter = sift({$exists:true}, function(user) {
return !!user.name;
});
sifter([
{
name: "Craig"
},
{
name: null
}
])
With your sifter, you can also test values:
siftExists(null);
siftExists('craig');
Supported Operators:
See MongoDB's advanced queries for more info.
$in
array value must be $in the given query:
Intersecting two arrays:
sift({ $in: ['Costa Rica','Brazil'] }, ['Brazil','Haiti','Peru','Chile']);
Here's another example. This acts more like the $or operator:
sift({ location: { $in: ['Costa Rica','Brazil'] } }, { name: 'Craig', location: 'Brazil' });
$nin
Opposite of $in:
sift({ $nin: ['Costa Rica','Brazil'] }, ['Brazil','Haiti','Peru','Chile']);
$exists
Checks if whether a value exists:
sift({ $exists: true }, ['Craig',null,'Tim']);
You can also filter out values that don't exist
sift({ city: { $exists: false } }, [ { name: 'Craig', city: 'Minneapolis' }, { name: 'Tim' }]);
$gte
Checks if a number is >= value:
sift({ $gte: 2 }, [0, 1, 2, 3]);
$gt
Checks if a number is > value:
sift({ $gt: 2 }, [0, 1, 2, 3]);
$lte
Checks if a number is <= value.
sift({ $lte: 2 }, [0, 1, 2, 3]);
$lt
Checks if number is < value.
sift({ $lt: 2 }, [0, 1, 2, 3]);
$eq
Checks if query == value. Note that $eq can be omitted. For $eq, and $ne
sift({ state: {$eq: 'MN' }}, [{ state: 'MN' }, { state: 'CA' }, { state: 'WI' });
Or:
sift({ state: 'MN' }, [{ state: 'MN' }, { state: 'CA' }, { state: 'WI' });
$ne
Checks if query != value.
sift({ state: {$ne: 'MN' }}, [{ state: 'MN' }, { state: 'CA' }, { state: 'WI' });
$mod
Modulus:
sift({ $mod: [3, 0] }, [100, 200, 300, 400, 500, 600]);
$all
values must match everything in array:
sift({ tags: {$all: ['books','programming'] }}, [
{ tags: ['books','programming','travel' ] },
{ tags: ['travel','cooking'] } ]);
$and
ability to use an array of expressions. All expressions must test true.
sift({ $and: [ { name: 'Craig' }, { state: 'MN' } ] }, [
{ name: 'Craig', state: 'MN' },
{ name: 'Tim', state: 'MN' },
{ name: 'Joe', state: 'CA' } ]);
$or
OR array of expressions.
sift({ $or: [ { name: 'Craig' }, { state: 'MN' } ] }, [
{ name: 'Craig', state: 'MN' },
{ name: 'Tim', state: 'MN' },
{ name: 'Joe', state: 'CA' } ]);
$nor
opposite of or:
sift({ $nor: [ { name: 'Craig' }, { state: 'MN' } ] }, [
{ name: 'Craig', state: 'MN' },
{ name: 'Tim', state: 'MN' },
{ name: 'Joe', state: 'CA' } ]);
$size
Matches an array - must match given size:
sift({ tags: { $size: 2 } }, [ { tags: ['food','cooking'] }, { tags: ['traveling'] }]);
$type
Matches a values based on the type
sift({ $type: Date }, [new Date(), 4342, 'hello world']);
sift({ $type: String }, [new Date(), 4342, 'hello world']);
$regex
Matches values based on the given regular expression
sift({ $regex: /^f/i, $nin: ["frank"] }, ["frank", "fred", "sam", "frost"]);
sift({ $regex: "^f", $options: "i", $nin: ["frank"] }, ["frank", "fred", "sam", "frost"]);
$where
Matches based on some javascript comparison
sift({ $where: "this.name === 'frank'" }, [{name:'frank'},{name:'joe'}]);
sift({
$where: function() {
return this.name === "frank"
}
}, [{name:'frank'},{name:'joe'}]);
$elemMatch
Matches elements of array
var bills = [{
month: 'july',
casts: [{
id: 1,
value: 200
},{
id: 2,
value: 1000
}]
},
{
month: 'august',
casts: [{
id: 3,
value: 1000,
}, {
id: 4,
value: 4000
}]
}];
var result = sift({
casts: {$elemMatch:{
value: {$gt: 1000}
}}
}, bills);
$not
Not expression:
sift({$not:{$in:['craig','tim']}}, ['craig','tim','jake']);
sift({$not:{$size:5}}, ['craig','tim','jake']);
sub object Searching
var people = [{
name: 'craig',
address: {
city: 'Minneapolis'
}
},
{
name: 'tim',
address: {
city: 'St. Paul'
}
}];
var sifted = sift({ address: { city: 'Minneapolis' }}, people);
var sifted = sift({'address.city': 'minneapolis'}, people);
Custom Expressions
You can add your own expressions. For instance - say you want to do some bitmask filtering, you could add this example:
sift.use({
$band: function(a, b) {
return (a & b) ? 0 : -1;
}
});
var IS_ANIMAL = 2,
IS_PERSON = IS_ANIMAL << 1,
IS_DOG = IS_PERSON << 1,
EATS_CEREAL = IS_DOG << 1,
EATS_BONES = EATS_CEREAL << 1;
sift({ $band: IS_PERSON }, [ S_PERSON|EATS_CEREAL, IS_DOG|EATS_BONES, IS_PERSON ]);
Get index of first matching element
Get the index (0-based) of first matching element in target array. Returns -1
if no match is found.
var people = [{
name: 'craig',
address: {
city: 'Minneapolis'
}
},
{
name: 'tim',
address: {
city: 'St. Paul'
}
}];
var index = sift.indexOf({ address: { city: 'Minneapolis' }}, people);