sift

mongodb query style array filtering

For extended documentation, checkout http://docs.mongodb.org/manual/reference/operator/query/

 
var sift = require('sift');
 
//intersecting arrays 
var sifted = sift({ $in: ['hello','world'] }, ['hello','sifted','array!']); //['hello'] 
 
//regexp filter 
var sifted = sift(/^j/, ['craig','john','jake']); //['john','jake'] 
 
 
//A *sifter* is returned if the second parameter is omitted 
var siftPeople = sift({
 
    //you can also filter against functions 
    namefunction(value) {
        return value.length == 5;
    }
});
 
//filtered: [{ name: 'craig' }] 
siftPeople([{
    name: 'craig',
},
{
    name: 'john'
},
{
    name: 'jake'
}]);
 
 
//you can test *single values* against your custom sifter 
siftPeople.test({ name: 'sarah' }); //true 
siftPeople.test({ name: 'tim' }); //false\ 
<html>
    <head>
        <script src="https://raw.github.com/crcn/sift.js/master/sift.min.js" type="text/javascript"></script> 
        <script type="text/javascript">
            //regexp filter 
            var sifted = sift(/^j/, ['craig','john','jake']); //['john','jake']
        </script> 
    </head>
    <body>
    </body>
</html>
  • filter - the filter to use against the target array
  • array - sifts against target array. Without this, a function is returned
  • selectorFn - selector for the values within the array.

With an array:

sift({$exists:true}, ['craig',null]); //['craig'] 

Without an array, a sifter is returned:

var siftExists = sift({$exists:true});
 
siftExists(['craig',null]); //['craig'] 

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.test(null); //false 
siftExists.test('craig'); //true 

See MongoDB's advanced queries for more info.

array value must be $in the given query:

Intersecting two arrays:

//filtered: ['Brazil'] 
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' });

Opposite of $in:

//filtered: ['Haiti','Peru','Chile'] 
sift({ $nin: ['Costa Rica','Brazil'] }, ['Brazil','Haiti','Peru','Chile']); 

Checks if whether a value exists:

//filtered: ['Craig','Tim'] 
sift({ $exists: true }, ['Craig',null,'Tim']); 

You can also filter out values that don't exist

//filtered: [{ name: 'Craig', city: 'Minneapolis' }] 
sift({ city: { $exists: false } }, [ { name: 'Craig', city: 'Minneapolis' }, { name: 'Tim' }]); 

Checks if a number is >= value:

//filtered: [2, 3] 
sift({ $gte: 2 }, [0, 1, 2, 3]); 

Checks if a number is > value:

//filtered: [3] 
sift({ $gt: 2 }, [0, 1, 2, 3]); 

Checks if a number is <= value.

//filtered: [0, 1, 2] 
sift({ $lte: 2 }, [0, 1, 2, 3]); 

Checks if number is < value.

//filtered: [0, 1] 
sift({ $lt: 2 }, [0, 1, 2, 3]); 

Checks if query == value. Note that $eq can be omitted. For $eq, and $ne

//filtered: [{ state: 'MN' }] 
sift({ state: {$eq: 'MN' }}, [{ state: 'MN' }, { state: 'CA' }, { state: 'WI' }); 

Or:

//filtered: [{ state: 'MN' }] 
sift({ state: 'MN' }, [{ state: 'MN' }, { state: 'CA' }, { state: 'WI' }); 

Checks if query != value.

//filtered: [{ state: 'CA' }, { state: 'WI'}]  
sift({ state: {$ne: 'MN' }}, [{ state: 'MN' }, { state: 'CA' }, { state: 'WI' }); 

Modulus:

//filtered: [300, 600] 
sift({ $mod: [3, 0] }, [100, 200, 300, 400, 500, 600]); 

values must match everything in array:

//filtered: [ { tags: ['books','programming','travel' ]} ] 
sift({ tags: {$all: ['books','programming'] }}, [
{ tags: ['books','programming','travel' ] }, 
{ tags: ['travel','cooking'] } ]); 

ability to use an array of expressions. All expressions must test true.

//filtered: [ { name: 'Craig', state: 'MN' }] 
 
sift({ $and: [ { name: 'Craig' }, { state: 'MN' } ] }, [ 
{ name: 'Craig', state: 'MN' }, 
{ name: 'Tim', state: 'MN' }, 
{ name: 'Joe', state: 'CA' } ]); 

OR array of expressions.

//filtered: [ { name: 'Craig', state: 'MN' }, { name: 'Tim', state: 'MN' }] 
sift({ $or: [ { name: 'Craig' }, { state: 'MN' } ] }, [ 
{ name: 'Craig', state: 'MN' }, 
{ name: 'Tim', state: 'MN' }, 
{ name: 'Joe', state: 'CA' } ]); 

opposite of or:

//filtered: [ { name: 'Tim', state: 'MN' }, { name: 'Joe', state: 'CA' }] 
sift({ $nor: [ { name: 'Craig' }, { state: 'MN' } ] }, [ 
{ name: 'Craig', state: 'MN' }, 
{ name: 'Tim', state: 'MN' }, 
{ name: 'Joe', state: 'CA' } ]); 

Matches an array - must match given size:

//filtered: ['food','cooking'] 
sift({ tags: { $size: 2 } }, [ { tags: ['food','cooking'] }, { tags: ['traveling'] }]); 

Matches a values based on the type

sift({ $type: Date }, [new Date(), 4342, 'hello world']); //returns single date 
sift({ $type: String }, [new Date(), 4342, 'hello world']); //returns ['hello world'] 

Matches values based on the given regular expression

sift({ $regex: /^f/i, $nin: ["frank"] }, ["frank", "fred", "sam", "frost"]); // ["fred", "frost"] 

Matches based on some javascript comparison

sift({ $where: "this.name === 'frank'" }, [{name:'frank'},{name:'joe'}]); // ["frank"] 
sift({ 
    $wherefunction() { 
        return this.name === "frank"
    }
}, [{name:'frank'},{name:'joe'}]); // ["frank"] 

Not expression:

sift({$not:{$in:['craig','tim']}}, ['craig','tim','jake']); //['jake'] 
sift({$not:{$size:5}}, ['craig','tim','jake']); //['tim','jake'] 
var people = [{
    name: 'craig',
    address: {
        city: 'Minneapolis'
    }
},
{
    name: 'tim',
    address: {
        city: 'St. Paul'
    }
}];
 
var sifted = sift({ address: { city: 'Minneapolis' }}, people); // count = 1 
 
//or 
var sifted = sift({'address.city': 'minneapolis'}, people);//count = 1 

You can add your own expressions. For instance - say you want to do some bitmask filtering, you could add this example:

 
sift.use({
    operators: {
        bandfunction(ab) {
            return (& b) ? 0 : -1; // 0 = exists, -1 = doesn't exist 
        }
    }
})
 
// ops 
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 ]);