Skip to content

Instantly share code, notes, and snippets.

@raycmorgan
Last active October 28, 2016 22:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raycmorgan/035dbfbe4581716196f8 to your computer and use it in GitHub Desktop.
Save raycmorgan/035dbfbe4581716196f8 to your computer and use it in GitHub Desktop.
function queryMatch(obj, query) {
return _.every(query, function (pred, key) {
if (_.contains(['$and', '$or', '$nor'], key)) {
assert(Array.isArray(pred), 'Value of ' + key + ' must be an array');
var recur = _.partial(queryMatch, obj);
switch (key) {
case '$and': return _.every(pred, recur);
case '$or': return _.some(pred, recur);
case '$nor': return !_.some(pred, recur);
}
}
var val = obj[key];
if (typeof(pred) === 'object') {
return _.every(pred, function _check(p, op) {
if (op === '$not') {
return !_.every(p, _check);
}
var typeMatch = typeof(p) === typeof(val);
switch (op) {
case '$gt': return typeMatch && val > p;
case '$lt': return typeMatch && val < p;
case '$gte': return typeMatch && val >= p;
case '$lte': return typeMatch && val <= p;
case '$in': return _.contains(p, val);
case '$ne': return p !== val;
case '$nin': return !_.contains(p, val);
default: throw new Error('Unknown operator: ' + op);
}
});
} else if (val === pred) {
return true;
} else {
return false;
}
});
}
function assert(bool, message) {
if (!bool) {
throw new Error(message);
}
}
var p = {name: 'Tom', age 24};
queryMatch(p, {name: 'Tom'}); // => true
queryMatch(p, {name: 'Bill'}); // => false
queryMatch(p, {name: {$in: ['Tom', 'Bill']}); // => true
queryMatch(p, {age: {$gt: 20}); // => true
queryMatch(p, {age: {$not: {$gt: 20}}); // => false
queryMatch(p, {$or: [{age: {$gt: 20}, {name: 'Bill'}]); // => true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment