Comparing version 0.4.2 to 0.5.0
293
mingo.js
@@ -1,2 +0,2 @@ | ||
// Mingo.js 0.4.2 | ||
// Mingo.js 0.5.0 | ||
// Copyright (c) 2015 Francis Asante <kofrasa@gmail.com> | ||
@@ -23,10 +23,8 @@ // MIT | ||
var nodeEnabled = ('undefined' !== typeof exports && 'undefined' !== typeof require); | ||
var nodeEnabled = ('undefined' !== typeof module && 'undefined' !== typeof require); | ||
// Export the Mingo object for Node.js | ||
if (nodeEnabled) { | ||
if (typeof module !== 'undefined' && module.exports) { | ||
exports = module.exports = Mingo; | ||
} else { | ||
exports = Mingo; | ||
if (typeof module !== 'undefined') { | ||
module.exports = Mingo; | ||
} | ||
@@ -44,2 +42,11 @@ _ = require("underscore"); // get a reference to underscore | ||
function isPrimitive(value) { | ||
for (var i = 0; i < primitives.length; i++) { | ||
if (primitives[i](value)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
/** | ||
@@ -51,16 +58,12 @@ * Simplify expression for easy evaluation with query operators map | ||
function normalize(expr) { | ||
// normalized primitives | ||
for (var i = 0; i < primitives.length; i++) { | ||
if (primitives[i](expr)) { | ||
if (_.isRegExp(expr)) { | ||
return {"$regex": expr}; | ||
} else { | ||
return {"$eq": expr}; | ||
} | ||
} | ||
if (isPrimitive(expr)) { | ||
return _.isRegExp(expr) ? {"$regex": expr} : {"$eq": expr}; | ||
} | ||
// normalize object expression | ||
if (_.isObject(expr)) { | ||
var keys = _.keys(expr); | ||
var notQuery = _.intersection(Ops.queryOperators, keys).length === 0; | ||
var notQuery = _.intersection(ops(OP_QUERY), keys).length === 0; | ||
@@ -150,17 +153,7 @@ // no valid query operator found, so we do simple comparison | ||
_processOperator: function (field, operator, value) { | ||
var compiledSelector; | ||
if (_.contains(Ops.simpleOperators, operator)) { | ||
compiledSelector = { | ||
test: function (obj) { | ||
var fieldValue = resolve(obj, field); | ||
// value of operator must already be fully resolved. | ||
return simpleOperators[operator](fieldValue, value); | ||
} | ||
}; | ||
} else if (_.contains(Ops.compoundOperators, operator)) { | ||
compiledSelector = compoundOperators[operator](field, value); | ||
if (_.contains(ops(OP_QUERY), operator)) { | ||
this._compiled.push(queryOperators[operator](field, value)); | ||
} else { | ||
throw new Error("Invalid query operator '" + operator + "' detected"); | ||
} | ||
this._compiled.push(compiledSelector); | ||
}, | ||
@@ -452,3 +445,3 @@ | ||
var key = _.keys(operator); | ||
if (key.length == 1 && _.contains(Ops.pipelineOperators, key[0])) { | ||
if (key.length == 1 && _.contains(ops(OP_PIPELINE), key[0])) { | ||
key = key[0]; | ||
@@ -552,2 +545,90 @@ if (query instanceof Mingo.Query) { | ||
/** | ||
* Add new operators | ||
* @param type the operator type to extend | ||
* @param f a function returning an object of new operators | ||
*/ | ||
Mingo.addOperators = function (type, f) { | ||
var newOperators = f({ | ||
resolve: resolve, | ||
computeValue: computeValue, | ||
ops: ops, | ||
key: function () { | ||
return settings.key; | ||
} | ||
}); | ||
// ensure correct type specified | ||
if (!_.contains([OP_AGGREGATE, OP_GROUP, OP_PIPELINE, OP_PROJECTION, OP_QUERY], type)) { | ||
throw new Error("Could not identify type '" + type + "'"); | ||
} | ||
var operators = ops(type); | ||
// check for existing operators | ||
_.each(_.keys(newOperators), function (op) { | ||
if (!/^\$\w+$/.test(op)) { | ||
throw new Error("Invalid operator name '" + op + "'"); | ||
} | ||
if (_.contains(operators, op)) { | ||
throw new Error("Operator " + op + " is already defined for " + type + " operators"); | ||
} | ||
}); | ||
var wrapped = {}; | ||
switch (type) { | ||
case OP_QUERY: | ||
_.each(_.keys(newOperators), function (op) { | ||
wrapped[op] = (function (f, ctx) { | ||
return function (selector, value) { | ||
return { | ||
test: function (obj) { | ||
// value of field must be fully resolved. | ||
var lhs = resolve(obj, selector); | ||
var result = f.call(ctx, selector, lhs, value); | ||
if (_.isBoolean(result)) { | ||
return result; | ||
} else if (result instanceof Mingo.Query) { | ||
return result.test(obj); | ||
} else { | ||
throw new Error("Invalid return type for '" + op + "'. Must return a Boolean or Mingo.Query"); | ||
} | ||
} | ||
}; | ||
} | ||
}(newOperators[op], newOperators)); | ||
}); | ||
break; | ||
case OP_PROJECTION: | ||
_.each(_.keys(newOperators), function (op) { | ||
wrapped[op] = (function (f, ctx) { | ||
return function (obj, expr, selector) { | ||
var lhs = resolve(obj, selector); | ||
return f.call(ctx, selector, lhs, expr); | ||
} | ||
}(newOperators[op], newOperators)); | ||
}); | ||
break; | ||
default: | ||
_.each(_.keys(newOperators), function (op) { | ||
wrapped[op] = (function (f, ctx) { | ||
return function () { | ||
var args = Array.prototype.slice.call(arguments); | ||
return f.apply(ctx, args); | ||
} | ||
}(newOperators[op], newOperators)); | ||
}); | ||
} | ||
// update if wrapped | ||
if (!_.isEmpty(wrapped)) { | ||
newOperators = wrapped; | ||
} | ||
// toss the operator salad :) | ||
_.extend(OPERATORS[type], newOperators); | ||
}; | ||
/** | ||
* Mixin for Backbone.Collection objects | ||
@@ -589,12 +670,8 @@ */ | ||
var idKey = expr[settings.key]; | ||
var indexes = []; | ||
// group collection by key | ||
var groups = _.groupBy(collection, function (obj) { | ||
var key = computeValue(obj, idKey, idKey); | ||
indexes.push(key); | ||
return key; | ||
var partitions = groupBy(collection, function (obj) { | ||
return computeValue(obj, idKey, idKey); | ||
}); | ||
// group indexes | ||
indexes = _.uniq(indexes); | ||
var result = []; | ||
@@ -604,10 +681,14 @@ // remove the group key | ||
var result = []; | ||
_.each(indexes, function (index) { | ||
_.each(partitions.keys, function (value, i) { | ||
var obj = {}; | ||
obj[settings.key] = index; | ||
// exclude undefined key value | ||
if (!_.isUndefined(value)) { | ||
obj[settings.key] = value; | ||
} | ||
// compute remaining keys in expression | ||
for (var key in expr) { | ||
if (expr.hasOwnProperty(key)) { | ||
obj[key] = accumulate(groups[index], key, expr[key]); | ||
obj[key] = accumulate(partitions.groups[i], key, expr[key]); | ||
} | ||
@@ -650,2 +731,3 @@ } | ||
var objKeys = _.keys(expr); | ||
var idOnlyExcludedExpression = false; | ||
@@ -656,2 +738,5 @@ if (_.contains(objKeys, settings.key)) { | ||
objKeys = _.without(objKeys, settings.key); | ||
if (_.isEmpty(objKeys)) { | ||
idOnlyExcludedExpression = true; | ||
} | ||
} | ||
@@ -664,7 +749,13 @@ } else { | ||
for (var i = 0; i < collection.length; i++) { | ||
var obj = collection[i]; | ||
var cloneObj = {}; | ||
var foundSlice = false; | ||
var foundExclusion = false; | ||
var dropKeys = []; | ||
if (idOnlyExcludedExpression) { | ||
dropKeys.push(settings.key); | ||
} | ||
_.each(objKeys, function (key) { | ||
@@ -674,2 +765,5 @@ | ||
var newValue; | ||
if (key !== settings.key && subExpr === 0) { | ||
foundExclusion = true; | ||
} | ||
@@ -686,3 +780,3 @@ // tiny optimization here to skip over id | ||
operator = operator.length > 1 ? false : operator[0]; | ||
if (operator !== false && _.contains(Ops.projectionOperators, operator)) { | ||
if (operator !== false && _.contains(ops(OP_PROJECTION), operator)) { | ||
// apply the projection operator on the operator expression for the key | ||
@@ -707,7 +801,7 @@ var temp = projectionOperators[operator](obj, subExpr[operator], key); | ||
} | ||
}); | ||
// if projection included $slice operator | ||
// Also if exclusion fields are found or we want to exclude only the id field | ||
// include keys that were not explicitly excluded | ||
if (foundSlice) { | ||
if (foundSlice || foundExclusion || idOnlyExcludedExpression) { | ||
cloneObj = _.defaults(cloneObj, _.omit(obj, dropKeys)); | ||
@@ -803,2 +897,5 @@ } | ||
////////// QUERY OPERATORS ////////// | ||
var queryOperators = {}; | ||
var compoundOperators = { | ||
@@ -919,2 +1016,5 @@ | ||
// add compound query operators | ||
_.extend(queryOperators, compoundOperators); | ||
var simpleOperators = { | ||
@@ -1158,4 +1258,17 @@ | ||
} | ||
}; | ||
// add simple query operators | ||
_.each(_.keys(simpleOperators), function (op) { | ||
queryOperators[op] = (function (f, ctx) { | ||
return function (selector, value) { | ||
return { | ||
test: function (obj) { | ||
// value of field must be fully resolved. | ||
var lhs = resolve(obj, selector); | ||
return f.call(ctx, lhs, value); | ||
} | ||
}; | ||
} | ||
}(simpleOperators[op], simpleOperators)); | ||
}); | ||
@@ -1254,2 +1367,5 @@ var projectionOperators = { | ||
$sum: function (collection, expr) { | ||
if (!_.isArray(collection)) { | ||
return 0; | ||
} | ||
if (_.isNumber(expr)) { | ||
@@ -1937,13 +2053,72 @@ // take a short cut if expr is number literal | ||
var Ops = { | ||
simpleOperators: _.keys(simpleOperators), | ||
compoundOperators: _.keys(compoundOperators), | ||
aggregateOperators: _.keys(aggregateOperators), | ||
groupOperators: _.keys(groupOperators), | ||
pipelineOperators: _.keys(pipelineOperators), | ||
projectionOperators: _.keys(projectionOperators) | ||
var OP_QUERY = Mingo.OP_QUERY = 'query', | ||
OP_GROUP = Mingo.OP_GROUP = 'group', | ||
OP_AGGREGATE = Mingo.OP_AGGREGATE = 'aggregate', | ||
OP_PIPELINE = Mingo.OP_PIPELINE = 'pipeline', | ||
OP_PROJECTION = Mingo.OP_PROJECTION = 'projection'; | ||
// operator definitions | ||
var OPERATORS = { | ||
'aggregate': aggregateOperators, | ||
'group': groupOperators, | ||
'pipeline': pipelineOperators, | ||
'projection': projectionOperators, | ||
'query': queryOperators | ||
}; | ||
Ops.queryOperators = _.union(Ops.simpleOperators, Ops.compoundOperators); | ||
/** | ||
* Return the registered operators on the given operator category | ||
* @param type catgory of operators | ||
* @returns {*} | ||
*/ | ||
function ops(type) { | ||
return _.keys(OPERATORS[type]); | ||
} | ||
/** | ||
* Groups the collection into sets by the returned key | ||
* | ||
* @param collection | ||
* @param fn | ||
*/ | ||
function groupBy(collection, fn) { | ||
var result = { | ||
'keys': [], | ||
'groups': [] | ||
}; | ||
_.each(collection, function (obj) { | ||
var key = fn(obj); | ||
var index = -1; | ||
if (_.isObject(key)) { | ||
for (var i = 0; i < result.keys.length; i++) { | ||
if (_.isEqual(key, result.keys[i])) { | ||
index = i; | ||
break; | ||
} | ||
} | ||
} else { | ||
index = _.indexOf(result.keys, key); | ||
} | ||
if (index > -1) { | ||
result.groups[index].push(obj); | ||
} else { | ||
result.keys.push(key); | ||
result.groups.push([obj]); | ||
} | ||
}); | ||
// assert this | ||
if (result.keys.length !== result.groups.length) { | ||
throw new Error("assert groupBy(): keys.length !== groups.length"); | ||
} | ||
return result; | ||
} | ||
/** | ||
* Returns the result of evaluating a $group operation over a collection | ||
@@ -1957,3 +2132,3 @@ * | ||
function accumulate(collection, field, expr) { | ||
if (_.contains(Ops.groupOperators, field)) { | ||
if (_.contains(ops(OP_GROUP), field)) { | ||
return groupOperators[field](collection, expr); | ||
@@ -1969,3 +2144,3 @@ } | ||
// if so, return result of the computed value | ||
if (_.contains(Ops.groupOperators, key)) { | ||
if (_.contains(ops(OP_GROUP), key)) { | ||
result = result[key]; | ||
@@ -1997,3 +2172,3 @@ // if there are more keys in expression this is bad | ||
// if the field of the object is a valid operator | ||
if (_.contains(Ops.aggregateOperators, field)) { | ||
if (_.contains(ops(OP_AGGREGATE), field)) { | ||
return aggregateOperators[field](obj, expr); | ||
@@ -2022,3 +2197,3 @@ } | ||
// if so, return result of the computed value | ||
if (_.contains(Ops.aggregateOperators, key)) { | ||
if (_.contains(ops(OP_AGGREGATE), key)) { | ||
result = result[key]; | ||
@@ -2035,6 +2210,4 @@ // if there are more keys in expression this is bad | ||
// check and return value if already in a resolved state | ||
for (var i = 0; i < primitives.length; i++) { | ||
if (primitives[i](expr)) { | ||
return expr; | ||
} | ||
if (isPrimitive(expr)) { | ||
return expr; | ||
} | ||
@@ -2041,0 +2214,0 @@ } |
@@ -1,1 +0,2 @@ | ||
!function(r,n){"use strict";function t(r){for(var n=0;n<l.length;n++)if(l[n](r))return a.isRegExp(r)?{$regex:r}:{$eq:r};if(a.isObject(r)){var t=a.keys(r),e=0===a.intersection(D.queryOperators,t).length;if(e)return{$eq:r};if(a.contains(t,"$regex")){var i=r.$regex,u=r.$options||"",o="";a.isString(i)&&(o+=i.ignoreCase||u.indexOf("i")>=0?"i":"",o+=i.multiline||u.indexOf("m")>=0?"m":"",o+=i.global||u.indexOf("g")>=0?"g":"",i=new RegExp(i,o)),r.$regex=i,delete r.$options}}return r}function e(r,n){return a.result(r,n)}function i(r,t){if(!t)return n;for(var u,o=t.split("."),s=r,c=0;c<o.length;c++){if(u=null===o[c].match(/^\d+$/),u&&a.isArray(s)){var f=[];a.each(s,function(r){a.isObject(r)&&f.push(i(r,o[c]))}),s=f}else s=e(s,o[c]);if(s===n)break}return s}function u(r,t,e){if(a.contains(D.groupOperators,t))return m[t](r,e);if(a.isObject(e)){var i={};for(var o in e)if(e.hasOwnProperty(o)&&(i[o]=u(r,o,e[o]),a.contains(D.groupOperators,o))){if(i=i[o],a.keys(e).length>1)throw new Error("Invalid $group expression '"+JSON.stringify(e)+"'");break}return i}return n}function o(r,n,t){if(a.contains(D.aggregateOperators,t))return S[t](r,n);if(a.isString(n)&&n.length>0&&"$"===n[0])return i(r,n.slice(1));var e;if(a.isArray(n))e=a.map(n,function(n){return o(r,n,null)});else if(a.isObject(n)){e={};for(var u in n)if(n.hasOwnProperty(u)&&(e[u]=o(r,n[u],u),a.contains(D.aggregateOperators,u))){if(e=e[u],a.keys(n).length>1)throw new Error("Invalid aggregation expression '"+JSON.stringify(n)+"'");break}}else for(var s=0;s<l.length;s++)if(l[s](n))return n;return e}var s,a,c={};null!=r&&(s=r.Mingo),c.noConflict=function(){return r.Mingo=s,c};var f="undefined"!=typeof exports&&"undefined"!=typeof require;f?(exports="undefined"!=typeof module&&module.exports?module.exports=c:c,a=require("underscore")):(r.Mingo=c,a=r._);var l=[a.isString,a.isBoolean,a.isNumber,a.isDate,a.isNull,a.isRegExp],h={key:"_id"};if(c.setup=function(r){a.extend(h,r||{})},c.Query=function(r,n){return this instanceof c.Query?(this._criteria=r,this._projection=n,this._compiled=[],void this._compile()):new c.Query(r,n)},c.Query.prototype={_compile:function(){if(!a.isEmpty(this._criteria)){if(a.isArray(this._criteria)||a.isFunction(this._criteria)||!a.isObject(this._criteria))throw new Error("Invalid type for criteria");for(var r in this._criteria)if(this._criteria.hasOwnProperty(r)){var n=this._criteria[r];if(a.contains(["$and","$or","$nor","$where"],r))this._processOperator(r,r,n);else{n=t(n);for(var e in n)n.hasOwnProperty(e)&&this._processOperator(r,e,n[e])}}}},_processOperator:function(r,n,t){var e;if(a.contains(D.simpleOperators,n))e={test:function(e){var u=i(e,r);return $[n](u,t)}};else{if(!a.contains(D.compoundOperators,n))throw new Error("Invalid query operator '"+n+"' detected");e=y[n](r,t)}this._compiled.push(e)},test:function(r){for(var n=0;n<this._compiled.length;n++)if(!this._compiled[n].test(r))return!1;return!0},find:function(r,n){return new c.Cursor(r,this,n)},remove:function(r){for(var n=[],t=0;t<r.length;t++)this.test(r[t])||n.push(r[t]);return n}},f){var p=require("stream").Transform,g=require("util");c.Query.prototype.stream=function(r){return new c.Stream(this,r)},c.Stream=function(r,n){return this instanceof c.Stream?(n=n||{},a.extend(n,{objectMode:!0}),p.call(this,n),void(this._query=r)):new c.Stream(r,n)},g.inherits(c.Stream,p),c.Stream.prototype._transform=function(r,n,t){if(a.isObject(r)&&this._query.test(r))if(a.isEmpty(this._query._projection))this.push(r);else{var e=new c.Cursor([r],this._query);e.hasNext()&&this.push(e.next())}t()}}c.Cursor=function(r,n,t){return this instanceof c.Cursor?(this._query=n,this._collection=r,this._projection=t||n._projection,this._operators={},this._result=!1,void(this._position=0)):new c.Cursor(r,n,t)},c.Cursor.prototype={_fetch:function(){var r=this;if(this._result!==!1)return this._result;if(a.isObject(this._projection)&&a.extend(this._operators,{$project:this._projection}),!a.isArray(this._collection))throw new Error("Input collection is not of valid type. Must be an Array.");this._result=a.filter(this._collection,this._query.test,this._query);var n=[];if(a.each(["$sort","$skip","$limit","$project"],function(t){a.has(r._operators,t)&&n.push(a.pick(r._operators,t))}),n.length>0){var t=new c.Aggregator(n);this._result=t.run(this._result,this._query)}return this._result},all:function(){return this._fetch()},first:function(){return this.count()>0?this._fetch()[0]:null},last:function(){return this.count()>0?this._fetch()[this.count()-1]:null},count:function(){return this._fetch().length},skip:function(r){return a.extend(this._operators,{$skip:r}),this},limit:function(r){return a.extend(this._operators,{$limit:r}),this},sort:function(r){return a.extend(this._operators,{$sort:r}),this},next:function(){return this.hasNext()?this._fetch()[this._position++]:null},hasNext:function(){return this.count()>this._position},max:function(r){return m.$max(this._fetch(),r)},min:function(r){return m.$min(this._fetch(),r)},map:function(r){return a.map(this._fetch(),r)},forEach:function(r){a.each(this._fetch(),r)}},c.Aggregator=function(r){return this instanceof c.Aggregator?void(this._operators=r):new c.Aggregator(r)},c.Aggregator.prototype={run:function(r,n){if(!a.isEmpty(this._operators))for(var t=0;t<this._operators.length;t++){var e=this._operators[t],i=a.keys(e);if(1!=i.length||!a.contains(D.pipelineOperators,i[0]))throw new Error("Invalid aggregation operator '"+i+"'");i=i[0],r=n instanceof c.Query?v[i].call(n,r,e[i]):v[i](r,e[i])}return r}},c.find=function(r,n,t){return new c.Query(n).find(r,t)},c.remove=function(r,n){return new c.Query(n).remove(r)},c.aggregate=function(r,n){if(!a.isArray(n))throw new Error("Aggregation pipeline must be an array");return new c.Aggregator(n).run(r)},c.CollectionMixin={query:function(r,n){return c.find(this.toJSON(),r,n)},aggregate:function(r){var n=[this.toJSON(),r];return c.aggregate.apply(null,n)}};var v={$group:function(r,n){var t=n[h.key],e=[],i=a.groupBy(r,function(r){var n=o(r,t,t);return e.push(n),n});e=a.uniq(e),n=a.omit(n,h.key);var s=[];return a.each(e,function(r){var t={};t[h.key]=r;for(var e in n)n.hasOwnProperty(e)&&(t[e]=u(i[r],e,n[e]));s.push(t)}),s},$match:function(r,n){return new c.Query(n).find(r).all()},$project:function(r,t){if(a.isEmpty(t))return r;var e=[],i=a.keys(t);if(a.contains(i,h.key)){var u=t[h.key];(0===u||u===!1)&&(i=a.without(i,h.key))}else i.push(h.key);for(var s=0;s<r.length;s++){var c=r[s],f={},l=!1,p=[];a.each(i,function(r){var e,i=t[r];if(r===h.key&&a.isEmpty(i))e=c[r];else if(a.isString(i))e=o(c,i,r);else if(1===i||i===!0)e=a.result(c,r);else if(a.isObject(i)){var u=a.keys(i);if(u=u.length>1?!1:u[0],u!==!1&&a.contains(D.projectionOperators,u)){var s=d[u](c,i[u],r);a.isUndefined(s)||(e=s),"$slice"==u&&(l=!0)}else e=o(c,i,r)}else p.push(r);e!==n&&(f[r]=a.isObject(e)?a.clone(e):e)}),l&&(f=a.defaults(f,a.omit(c,p))),e.push(f)}return e},$limit:function(r,n){return a.first(r,n)},$skip:function(r,n){return a.rest(r,n)},$unwind:function(r,n){for(var t=[],i=n.substr(1),u=0;u<r.length;u++){var o=r[u],s=e(o,i);if(!a.isArray(s))throw new Error("Target field '"+i+"' is not of type Array.");a.each(s,function(r){var n=a.clone(o);n[i]=r,t.push(n)})}return t},$sort:function(r,n){if(!a.isEmpty(n)&&a.isObject(n)){var t=a.keys(n);t.reverse().forEach(function(t){var e=[],u=a.groupBy(r,function(r){var n=i(r,t);return e.push(n),n});e=a.sortBy(a.uniq(e),function(r){return r}),-1===n[t]&&e.reverse(),r=[],a.each(e,function(n){Array.prototype.push.apply(r,u[n])})})}return r}},y={$and:function(r,n){if(!a.isArray(n))throw new Error("Invalid expression for $and criteria");var t=[];return a.each(n,function(r){t.push(new c.Query(r))}),{test:function(r){for(var n=0;n<t.length;n++)if(!t[n].test(r))return!1;return!0}}},$or:function(r,n){if(!a.isArray(n))throw new Error("Invalid expression for $or criteria");var t=[];return a.each(n,function(r){t.push(new c.Query(r))}),{test:function(r){for(var n=0;n<t.length;n++)if(t[n].test(r))return!0;return!1}}},$nor:function(r,n){if(!a.isArray(n))throw new Error("Invalid expression for $nor criteria");var t=this.$or("$or",n);return{test:function(r){return!t.test(r)}}},$not:function(r,n){var e={};e[r]=t(n);var i=new c.Query(e);return{test:function(r){return!i.test(r)}}},$where:function(r,n){return a.isFunction(n)||(n=new Function("return "+n+";")),{test:function(r){return n.call(r)===!0}}}},$={$eq:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return a.isEqual(r,t)}),r!==n},$ne:function(r,n){return!this.$eq(r,n)},$in:function(r,n){return r=a.isArray(r)?r:[r],a.intersection(r,n).length>0},$nin:function(r,n){return a.isUndefined(r)||!this.$in(r,n)},$lt:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return t>r}),r!==n},$lte:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return t>=r}),r!==n},$gt:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return r>t}),r!==n},$gte:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return r>=t}),r!==n},$mod:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return a.isNumber(r)&&a.isArray(t)&&2===t.length&&r%t[0]===t[1]}),r!==n},$regex:function(r,t){return r=a.isArray(r)?r:[r],r=a.find(r,function(r){return a.isString(r)&&a.isRegExp(t)&&!!r.match(t)}),r!==n},$exists:function(r,n){return n===!1&&a.isUndefined(r)||n===!0&&!a.isUndefined(r)},$all:function(r,n){var t=this,e=!1;if(a.isArray(r)&&a.isArray(n))for(var i=0;i<n.length;i++){if(!a.isObject(n[i])||!a.contains(a.keys(n[i]),"$elemMatch"))return a.intersection(n,r).length===n.length;e=e||t.$elemMatch(r,n[i].$elemMatch)}return e},$size:function(r,n){return a.isArray(r)&&a.isNumber(n)&&r.length===n},$elemMatch:function(r,n){if(a.isArray(r)&&!a.isEmpty(r))for(var t=new c.Query(n),e=0;e<r.length;e++)if(t.test(r[e]))return!0;return!1},$type:function(r,n){switch(n){case 1:return a.isNumeric(r)&&-1!==(r+"").indexOf(".");case 2:case 5:return a.isString(r);case 3:return a.isObject(r);case 4:return a.isArray(r);case 8:return a.isBoolean(r);case 9:return a.isDate(r);case 10:return a.isNull(r);case 11:return a.isRegExp(r);case 16:return a.isNumeric(r)&&2147483647>=r&&-1===(r+"").indexOf(".");case 18:return a.isNumeric(r)&&r>2147483647&&0x8000000000000000>=r&&-1===(r+"").indexOf(".");default:return!1}}},d={$:function(){throw new Error("$ not implemented")},$elemMatch:function(r,t,e){var u=i(r,e),o=new c.Query(t);if(a.isUndefined(u)||!a.isArray(u))return n;for(var s=0;s<u.length;s++)if(o.test(u[s]))return[u[s]];return n},$slice:function(r,n,t){var e=i(r,t);if(!a.isArray(e))return e;if(a.isArray(n)){var u=n[0]<0?e.length+n[0]:n,o=u+n[1];n=[u,o]}else{if(!a.isNumber(n))throw new Error("Invalid type for $slice operator");n=0>n?[n]:[0,n]}return Array.prototype.slice.apply(e,n)}},m={$addToSet:function(r,n){var t=a.map(r,function(r){return o(r,n,null)});return a.uniq(t)},$sum:function(r,n){return a.isNumber(n)?r.length*n:a.reduce(r,function(r,t){return r+o(t,n,null)},0)},$max:function(r,n){var t=a.max(r,function(r){return o(r,n,null)});return o(t,n,null)},$min:function(r,n){var t=a.min(r,function(r){return o(r,n,null)});return o(t,n,null)},$avg:function(r,n){return this.$sum(r,n)/(r.length||1)},$push:function(r,n){return a.map(r,function(r){return o(r,n,null)})},$first:function(r,t){return r.length>0?o(r[0],t):n},$last:function(r,t){return r.length>0?o(r[r.length-1],t):n}},w={$add:function(r,n){var t=o(r,n,null);return a.reduce(t,function(r,n){return r+n},0)},$subtract:function(r,n){var t=o(r,n,null);return t[0]-t[1]},$divide:function(r,n){var t=o(r,n,null);return t[0]/t[1]},$multiply:function(r,n){var t=o(r,n,null);return a.reduce(t,function(r,n){return r*n},1)},$mod:function(r,n){var t=o(r,n,null);return t[0]%t[1]}},_={$concat:function(r,t){var e=o(r,t,null);return a.contains(e,null)||a.contains(e,n)?null:e.join("")},$strcasecmp:function(r,n){var t=o(r,n,null);return t[0]=a.isEmpty(t[0])?"":t[0].toUpperCase(),t[1]=a.isEmpty(t[1])?"":t[1].toUpperCase(),t[0]>t[1]?1:t[0]<t[1]?-1:0},$substr:function(r,n){var t=o(r,n,null);return a.isString(t[0])?t[1]<0?"":t[2]<0?t[0].substr(t[1]):t[0].substr(t[1],t[2]):""},$toLower:function(r,n){var t=o(r,n,null);return a.isEmpty(t)?"":t.toLowerCase()},$toUpper:function(r,n){var t=o(r,n,null);return a.isEmpty(t)?"":t.toUpperCase()}},O={$dayOfYear:function(r,t){var e=o(r,t,null);if(a.isDate(e)){var i=new Date(e.getFullYear(),0,0),u=e-i,s=864e5;return Math.round(u/s)}return n},$dayOfMonth:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getDate():n},$dayOfWeek:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getDay()+1:n},$year:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getFullYear():n},$month:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getMonth()+1:n},$week:function(r,n){var t=o(r,n,null);t=new Date(+t),t.setHours(0,0,0),t.setDate(t.getDate()+4-(t.getDay()||7));var e=new Date(t.getFullYear(),0,1);return Math.floor(((t-e)/864e5+1)/7)},$hour:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getHours():n},$minute:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getMinutes():n},$second:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getSeconds():n},$millisecond:function(r,t){var e=o(r,t,null);return a.isDate(e)?e.getMilliseconds():n},$dateToString:function(r,n){n.format,o(r,n.date);throw new Error("Not Implemented")}},x={$setEquals:function(r,n){var t=o(r,n,null),e=a.uniq(t[0]),i=a.uniq(t[1]);return e.length!==i.length?!1:0==a.difference(e,i).length},$setIntersection:function(r,n){var t=o(r,n,null);return a.intersection(t[0],t[1])},$setDifference:function(r,n){var t=o(r,n,null);return a.difference(t[0],t[1])},$setUnion:function(r,n){var t=o(r,n,null);return a.union(t[0],t[1])},$setIsSubset:function(r,n){var t=o(r,n,null);return a.intersection(t[0],t[1]).length===t[0].length},$anyElementTrue:function(r,n){for(var t=o(r,n,null)[0],e=0;e<t.length;e++)if(t[e])return!0;return!1},$allElementsTrue:function(r,n){for(var t=o(r,n,null)[0],e=0;e<t.length;e++)if(!t[e])return!1;return!0}},A={$cond:function(r,n){var t,e,i;if(a.isArray(n)){if(3!=n.length)throw new Error("Invalid arguments for $cond operator");t=n[0],e=n[1],i=n[2]}else a.isObject(n)&&(t=n["if"],e=n.then,i=n["else"]);var u=o(r,t,null);return u?o(r,e,null):o(r,i,null)},$ifNull:function(r,t){if(!a.isArray(t)||2!=t.length)throw new Error("Invalid arguments for $ifNull operator");var e=o(r,t,null);return null===e[0]||e[0]===n?e[1]:e[0]}},E={$cmp:function(r,n){var t=o(r,n,null);return t[0]>t[1]?1:t[0]<t[1]?-1:0}};a.each(["$eq","$ne","$gt","$gte","$lt","$lte"],function(r){E[r]=function(n,t){var e=o(n,t,null);return $[r](e[0],e[1])}});var k={$size:function(r,t){var e=o(r,t,null);return a.isArray(e)?e.length:n}},b={$literal:function(r,n){return n}},q={$map:function(r,n){var t=o(r,n.input,null);if(!a.isArray(t))throw new Error("Input expression for $map must resolve to an array");var e=n.as,i=n["in"],u="$"+e,s=r[u];return a.map(t,function(n){r[u]=n;var t=o(r,i,null);return a.isUndefined(s)?delete r[u]:r[u]=s,t})},$let:function(r,n){var t=n.vars,e=n["in"],i={},u=a.keys(t);a.each(u,function(n){var e=o(r,t[n],null),u="$"+n;i[u]=r[u],r[u]=e});var s=o(r,e,null);return a.each(u,function(n){var t="$"+n;a.isUndefined(i[t])?delete r[t]:r[t]=i[t]}),s}},j={$and:function(r,n){var t=o(r,n,null);return a.every(t)},$or:function(r,n){var t=o(r,n,null);return a.some(t)},$not:function(r,n){return!o(r,n[0],null)}},S=a.extend({},k,w,j,E,A,O,b,x,_,q),D={simpleOperators:a.keys($),compoundOperators:a.keys(y),aggregateOperators:a.keys(S),groupOperators:a.keys(m),pipelineOperators:a.keys(v),projectionOperators:a.keys(d)};D.queryOperators=a.union(D.simpleOperators,D.compoundOperators)}(this); | ||
!function(r,n){"use strict";function t(r){for(var n=0;n<y.length;n++)if(y[n](r))return!0;return!1}function e(r){if(t(r))return l.isRegExp(r)?{$regex:r}:{$eq:r};if(l.isObject(r)){var n=l.keys(r),e=0===l.intersection(o(Q),n).length;if(e)return{$eq:r};if(l.contains(n,"$regex")){var i=r.$regex,u=r.$options||"",s="";l.isString(i)&&(s+=i.ignoreCase||u.indexOf("i")>=0?"i":"",s+=i.multiline||u.indexOf("m")>=0?"m":"",s+=i.global||u.indexOf("g")>=0?"g":"",i=new RegExp(i,s)),r.$regex=i,delete r.$options}}return r}function i(r,n){return l.result(r,n)}function u(r,t){if(!t)return n;for(var e,o=t.split("."),s=r,a=0;a<o.length;a++){if(e=null===o[a].match(/^\d+$/),e&&l.isArray(s)){var c=[];l.each(s,function(r){l.isObject(r)&&c.push(u(r,o[a]))}),s=c}else s=i(s,o[a]);if(s===n)break}return s}function o(r){return l.keys(T[r])}function s(r,n){var t={keys:[],groups:[]};if(l.each(r,function(r){var e=n(r),i=-1;if(l.isObject(e)){for(var u=0;u<t.keys.length;u++)if(l.isEqual(e,t.keys[u])){i=u;break}}else i=l.indexOf(t.keys,e);i>-1?t.groups[i].push(r):(t.keys.push(e),t.groups.push([r]))}),t.keys.length!==t.groups.length)throw new Error("assert groupBy(): keys.length !== groups.length");return t}function a(r,t,e){if(l.contains(o(C),t))return k[t](r,e);if(l.isObject(e)){var i={};for(var u in e)if(e.hasOwnProperty(u)&&(i[u]=a(r,u,e[u]),l.contains(o(C),u))){if(i=i[u],l.keys(e).length>1)throw new Error("Invalid $group expression '"+JSON.stringify(e)+"'");break}return i}return n}function c(r,n,e){if(l.contains(o(U),e))return M[e](r,n);if(l.isString(n)&&n.length>0&&"$"===n[0])return u(r,n.slice(1));var i;if(l.isArray(n))i=l.map(n,function(n){return c(r,n,null)});else if(l.isObject(n)){i={};for(var s in n)if(n.hasOwnProperty(s)&&(i[s]=c(r,n[s],s),l.contains(o(U),s))){if(i=i[s],l.keys(n).length>1)throw new Error("Invalid aggregation expression '"+JSON.stringify(n)+"'");break}}else if(t(n))return n;return i}var f,l,h={};null!=r&&(f=r.Mingo),h.noConflict=function(){return r.Mingo=f,h};var p="undefined"!=typeof module&&"undefined"!=typeof require;p?("undefined"!=typeof module&&(module.exports=h),l=require("underscore")):(r.Mingo=h,l=r._);var y=[l.isString,l.isBoolean,l.isNumber,l.isDate,l.isNull,l.isRegExp],g={key:"_id"};if(h.setup=function(r){l.extend(g,r||{})},h.Query=function(r,n){return this instanceof h.Query?(this._criteria=r,this._projection=n,this._compiled=[],void this._compile()):new h.Query(r,n)},h.Query.prototype={_compile:function(){if(!l.isEmpty(this._criteria)){if(l.isArray(this._criteria)||l.isFunction(this._criteria)||!l.isObject(this._criteria))throw new Error("Invalid type for criteria");for(var r in this._criteria)if(this._criteria.hasOwnProperty(r)){var n=this._criteria[r];if(l.contains(["$and","$or","$nor","$where"],r))this._processOperator(r,r,n);else{n=e(n);for(var t in n)n.hasOwnProperty(t)&&this._processOperator(r,t,n[t])}}}},_processOperator:function(r,n,t){if(!l.contains(o(Q),n))throw new Error("Invalid query operator '"+n+"' detected");this._compiled.push(m[n](r,t))},test:function(r){for(var n=0;n<this._compiled.length;n++)if(!this._compiled[n].test(r))return!1;return!0},find:function(r,n){return new h.Cursor(r,this,n)},remove:function(r){for(var n=[],t=0;t<r.length;t++)this.test(r[t])||n.push(r[t]);return n}},p){var v=require("stream").Transform,$=require("util");h.Query.prototype.stream=function(r){return new h.Stream(this,r)},h.Stream=function(r,n){return this instanceof h.Stream?(n=n||{},l.extend(n,{objectMode:!0}),v.call(this,n),void(this._query=r)):new h.Stream(r,n)},$.inherits(h.Stream,v),h.Stream.prototype._transform=function(r,n,t){if(l.isObject(r)&&this._query.test(r))if(l.isEmpty(this._query._projection))this.push(r);else{var e=new h.Cursor([r],this._query);e.hasNext()&&this.push(e.next())}t()}}h.Cursor=function(r,n,t){return this instanceof h.Cursor?(this._query=n,this._collection=r,this._projection=t||n._projection,this._operators={},this._result=!1,void(this._position=0)):new h.Cursor(r,n,t)},h.Cursor.prototype={_fetch:function(){var r=this;if(this._result!==!1)return this._result;if(l.isObject(this._projection)&&l.extend(this._operators,{$project:this._projection}),!l.isArray(this._collection))throw new Error("Input collection is not of valid type. Must be an Array.");this._result=l.filter(this._collection,this._query.test,this._query);var n=[];if(l.each(["$sort","$skip","$limit","$project"],function(t){l.has(r._operators,t)&&n.push(l.pick(r._operators,t))}),n.length>0){var t=new h.Aggregator(n);this._result=t.run(this._result,this._query)}return this._result},all:function(){return this._fetch()},first:function(){return this.count()>0?this._fetch()[0]:null},last:function(){return this.count()>0?this._fetch()[this.count()-1]:null},count:function(){return this._fetch().length},skip:function(r){return l.extend(this._operators,{$skip:r}),this},limit:function(r){return l.extend(this._operators,{$limit:r}),this},sort:function(r){return l.extend(this._operators,{$sort:r}),this},next:function(){return this.hasNext()?this._fetch()[this._position++]:null},hasNext:function(){return this.count()>this._position},max:function(r){return k.$max(this._fetch(),r)},min:function(r){return k.$min(this._fetch(),r)},map:function(r){return l.map(this._fetch(),r)},forEach:function(r){l.each(this._fetch(),r)}},h.Aggregator=function(r){return this instanceof h.Aggregator?void(this._operators=r):new h.Aggregator(r)},h.Aggregator.prototype={run:function(r,n){if(!l.isEmpty(this._operators))for(var t=0;t<this._operators.length;t++){var e=this._operators[t],i=l.keys(e);if(1!=i.length||!l.contains(o(P),i[0]))throw new Error("Invalid aggregation operator '"+i+"'");i=i[0],r=n instanceof h.Query?d[i].call(n,r,e[i]):d[i](r,e[i])}return r}},h.find=function(r,n,t){return new h.Query(n).find(r,t)},h.remove=function(r,n){return new h.Query(n).remove(r)},h.aggregate=function(r,n){if(!l.isArray(n))throw new Error("Aggregation pipeline must be an array");return new h.Aggregator(n).run(r)},h.addOperators=function(r,n){var t=n({resolve:u,computeValue:c,ops:o,key:function(){return g.key}});if(!l.contains([U,C,P,R,Q],r))throw new Error("Could not identify type '"+r+"'");var e=o(r);l.each(l.keys(t),function(n){if(!/^\$\w+$/.test(n))throw new Error("Invalid operator name '"+n+"'");if(l.contains(e,n))throw new Error("Operator "+n+" is already defined for "+r+" operators")});var i={};switch(r){case Q:l.each(l.keys(t),function(r){i[r]=function(n,t){return function(e,i){return{test:function(o){var s=u(o,e),a=n.call(t,e,s,i);if(l.isBoolean(a))return a;if(a instanceof h.Query)return a.test(o);throw new Error("Invalid return type for '"+r+"'. Must return a Boolean or Mingo.Query")}}}}(t[r],t)});break;case R:l.each(l.keys(t),function(r){i[r]=function(r,n){return function(t,e,i){var o=u(t,i);return r.call(n,i,o,e)}}(t[r],t)});break;default:l.each(l.keys(t),function(r){i[r]=function(r,n){return function(){var t=Array.prototype.slice.call(arguments);return r.apply(n,t)}}(t[r],t)})}l.isEmpty(i)||(t=i),l.extend(T[r],t)},h.CollectionMixin={query:function(r,n){return h.find(this.toJSON(),r,n)},aggregate:function(r){var n=[this.toJSON(),r];return h.aggregate.apply(null,n)}};var d={$group:function(r,n){var t=n[g.key],e=s(r,function(r){return c(r,t,t)}),i=[];return n=l.omit(n,g.key),l.each(e.keys,function(r,t){var u={};l.isUndefined(r)||(u[g.key]=r);for(var o in n)n.hasOwnProperty(o)&&(u[o]=a(e.groups[t],o,n[o]));i.push(u)}),i},$match:function(r,n){return new h.Query(n).find(r).all()},$project:function(r,t){if(l.isEmpty(t))return r;var e=[],i=l.keys(t),u=!1;if(l.contains(i,g.key)){var s=t[g.key];(0===s||s===!1)&&(i=l.without(i,g.key),l.isEmpty(i)&&(u=!0))}else i.push(g.key);for(var a=0;a<r.length;a++){var f=r[a],h={},p=!1,y=!1,v=[];u&&v.push(g.key),l.each(i,function(r){var e,i=t[r];if(r!==g.key&&0===i&&(y=!0),r===g.key&&l.isEmpty(i))e=f[r];else if(l.isString(i))e=c(f,i,r);else if(1===i||i===!0)e=l.result(f,r);else if(l.isObject(i)){var u=l.keys(i);if(u=u.length>1?!1:u[0],u!==!1&&l.contains(o(R),u)){var s=E[u](f,i[u],r);l.isUndefined(s)||(e=s),"$slice"==u&&(p=!0)}else e=c(f,i,r)}else v.push(r);e!==n&&(h[r]=l.isObject(e)?l.clone(e):e)}),(p||y||u)&&(h=l.defaults(h,l.omit(f,v))),e.push(h)}return e},$limit:function(r,n){return l.first(r,n)},$skip:function(r,n){return l.rest(r,n)},$unwind:function(r,n){for(var t=[],e=n.substr(1),u=0;u<r.length;u++){var o=r[u],s=i(o,e);if(!l.isArray(s))throw new Error("Target field '"+e+"' is not of type Array.");l.each(s,function(r){var n=l.clone(o);n[e]=r,t.push(n)})}return t},$sort:function(r,n){if(!l.isEmpty(n)&&l.isObject(n)){var t=l.keys(n);t.reverse().forEach(function(t){var e=[],i=l.groupBy(r,function(r){var n=u(r,t);return e.push(n),n});e=l.sortBy(l.uniq(e),function(r){return r}),-1===n[t]&&e.reverse(),r=[],l.each(e,function(n){Array.prototype.push.apply(r,i[n])})})}return r}},m={},w={$and:function(r,n){if(!l.isArray(n))throw new Error("Invalid expression for $and criteria");var t=[];return l.each(n,function(r){t.push(new h.Query(r))}),{test:function(r){for(var n=0;n<t.length;n++)if(!t[n].test(r))return!1;return!0}}},$or:function(r,n){if(!l.isArray(n))throw new Error("Invalid expression for $or criteria");var t=[];return l.each(n,function(r){t.push(new h.Query(r))}),{test:function(r){for(var n=0;n<t.length;n++)if(t[n].test(r))return!0;return!1}}},$nor:function(r,n){if(!l.isArray(n))throw new Error("Invalid expression for $nor criteria");var t=this.$or("$or",n);return{test:function(r){return!t.test(r)}}},$not:function(r,n){var t={};t[r]=e(n);var i=new h.Query(t);return{test:function(r){return!i.test(r)}}},$where:function(r,n){return l.isFunction(n)||(n=new Function("return "+n+";")),{test:function(r){return n.call(r)===!0}}}};l.extend(m,w);var _={$eq:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return l.isEqual(r,t)}),r!==n},$ne:function(r,n){return!this.$eq(r,n)},$in:function(r,n){return r=l.isArray(r)?r:[r],l.intersection(r,n).length>0},$nin:function(r,n){return l.isUndefined(r)||!this.$in(r,n)},$lt:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return t>r}),r!==n},$lte:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return t>=r}),r!==n},$gt:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return r>t}),r!==n},$gte:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return r>=t}),r!==n},$mod:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return l.isNumber(r)&&l.isArray(t)&&2===t.length&&r%t[0]===t[1]}),r!==n},$regex:function(r,t){return r=l.isArray(r)?r:[r],r=l.find(r,function(r){return l.isString(r)&&l.isRegExp(t)&&!!r.match(t)}),r!==n},$exists:function(r,n){return n===!1&&l.isUndefined(r)||n===!0&&!l.isUndefined(r)},$all:function(r,n){var t=this,e=!1;if(l.isArray(r)&&l.isArray(n))for(var i=0;i<n.length;i++){if(!l.isObject(n[i])||!l.contains(l.keys(n[i]),"$elemMatch"))return l.intersection(n,r).length===n.length;e=e||t.$elemMatch(r,n[i].$elemMatch)}return e},$size:function(r,n){return l.isArray(r)&&l.isNumber(n)&&r.length===n},$elemMatch:function(r,n){if(l.isArray(r)&&!l.isEmpty(r))for(var t=new h.Query(n),e=0;e<r.length;e++)if(t.test(r[e]))return!0;return!1},$type:function(r,n){switch(n){case 1:return l.isNumeric(r)&&-1!==(r+"").indexOf(".");case 2:case 5:return l.isString(r);case 3:return l.isObject(r);case 4:return l.isArray(r);case 8:return l.isBoolean(r);case 9:return l.isDate(r);case 10:return l.isNull(r);case 11:return l.isRegExp(r);case 16:return l.isNumeric(r)&&2147483647>=r&&-1===(r+"").indexOf(".");case 18:return l.isNumeric(r)&&r>2147483647&&0x8000000000000000>=r&&-1===(r+"").indexOf(".");default:return!1}}};l.each(l.keys(_),function(r){m[r]=function(r,n){return function(t,e){return{test:function(i){var o=u(i,t);return r.call(n,o,e)}}}}(_[r],_)});var E={$:function(){throw new Error("$ not implemented")},$elemMatch:function(r,t,e){var i=u(r,e),o=new h.Query(t);if(l.isUndefined(i)||!l.isArray(i))return n;for(var s=0;s<i.length;s++)if(o.test(i[s]))return[i[s]];return n},$slice:function(r,n,t){var e=u(r,t);if(!l.isArray(e))return e;if(l.isArray(n)){var i=n[0]<0?e.length+n[0]:n,o=i+n[1];n=[i,o]}else{if(!l.isNumber(n))throw new Error("Invalid type for $slice operator");n=0>n?[n]:[0,n]}return Array.prototype.slice.apply(e,n)}},k={$addToSet:function(r,n){var t=l.map(r,function(r){return c(r,n,null)});return l.uniq(t)},$sum:function(r,n){return l.isArray(r)?l.isNumber(n)?r.length*n:l.reduce(r,function(r,t){return r+c(t,n,null)},0):0},$max:function(r,n){var t=l.max(r,function(r){return c(r,n,null)});return c(t,n,null)},$min:function(r,n){var t=l.min(r,function(r){return c(r,n,null)});return c(t,n,null)},$avg:function(r,n){return this.$sum(r,n)/(r.length||1)},$push:function(r,n){return l.map(r,function(r){return c(r,n,null)})},$first:function(r,t){return r.length>0?c(r[0],t):n},$last:function(r,t){return r.length>0?c(r[r.length-1],t):n}},O={$add:function(r,n){var t=c(r,n,null);return l.reduce(t,function(r,n){return r+n},0)},$subtract:function(r,n){var t=c(r,n,null);return t[0]-t[1]},$divide:function(r,n){var t=c(r,n,null);return t[0]/t[1]},$multiply:function(r,n){var t=c(r,n,null);return l.reduce(t,function(r,n){return r*n},1)},$mod:function(r,n){var t=c(r,n,null);return t[0]%t[1]}},x={$concat:function(r,t){var e=c(r,t,null);return l.contains(e,null)||l.contains(e,n)?null:e.join("")},$strcasecmp:function(r,n){var t=c(r,n,null);return t[0]=l.isEmpty(t[0])?"":t[0].toUpperCase(),t[1]=l.isEmpty(t[1])?"":t[1].toUpperCase(),t[0]>t[1]?1:t[0]<t[1]?-1:0},$substr:function(r,n){var t=c(r,n,null);return l.isString(t[0])?t[1]<0?"":t[2]<0?t[0].substr(t[1]):t[0].substr(t[1],t[2]):""},$toLower:function(r,n){var t=c(r,n,null);return l.isEmpty(t)?"":t.toLowerCase()},$toUpper:function(r,n){var t=c(r,n,null);return l.isEmpty(t)?"":t.toUpperCase()}},A={$dayOfYear:function(r,t){var e=c(r,t,null);if(l.isDate(e)){var i=new Date(e.getFullYear(),0,0),u=e-i,o=864e5;return Math.round(u/o)}return n},$dayOfMonth:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getDate():n},$dayOfWeek:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getDay()+1:n},$year:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getFullYear():n},$month:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getMonth()+1:n},$week:function(r,n){var t=c(r,n,null);t=new Date(+t),t.setHours(0,0,0),t.setDate(t.getDate()+4-(t.getDay()||7));var e=new Date(t.getFullYear(),0,1);return Math.floor(((t-e)/864e5+1)/7)},$hour:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getHours():n},$minute:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getMinutes():n},$second:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getSeconds():n},$millisecond:function(r,t){var e=c(r,t,null);return l.isDate(e)?e.getMilliseconds():n},$dateToString:function(r,n){n.format,c(r,n.date);throw new Error("Not Implemented")}},b={$setEquals:function(r,n){var t=c(r,n,null),e=l.uniq(t[0]),i=l.uniq(t[1]);return e.length!==i.length?!1:0==l.difference(e,i).length},$setIntersection:function(r,n){var t=c(r,n,null);return l.intersection(t[0],t[1])},$setDifference:function(r,n){var t=c(r,n,null);return l.difference(t[0],t[1])},$setUnion:function(r,n){var t=c(r,n,null);return l.union(t[0],t[1])},$setIsSubset:function(r,n){var t=c(r,n,null);return l.intersection(t[0],t[1]).length===t[0].length},$anyElementTrue:function(r,n){for(var t=c(r,n,null)[0],e=0;e<t.length;e++)if(t[e])return!0;return!1},$allElementsTrue:function(r,n){for(var t=c(r,n,null)[0],e=0;e<t.length;e++)if(!t[e])return!1;return!0}},q={$cond:function(r,n){var t,e,i;if(l.isArray(n)){if(3!=n.length)throw new Error("Invalid arguments for $cond operator");t=n[0],e=n[1],i=n[2]}else l.isObject(n)&&(t=n["if"],e=n.then,i=n["else"]);var u=c(r,t,null);return u?c(r,e,null):c(r,i,null)},$ifNull:function(r,t){if(!l.isArray(t)||2!=t.length)throw new Error("Invalid arguments for $ifNull operator");var e=c(r,t,null);return null===e[0]||e[0]===n?e[1]:e[0]}},j={$cmp:function(r,n){var t=c(r,n,null);return t[0]>t[1]?1:t[0]<t[1]?-1:0}};l.each(["$eq","$ne","$gt","$gte","$lt","$lte"],function(r){j[r]=function(n,t){var e=c(n,t,null);return _[r](e[0],e[1])}});var N={$size:function(r,t){var e=c(r,t,null);return l.isArray(e)?e.length:n}},I={$literal:function(r,n){return n}},S={$map:function(r,n){var t=c(r,n.input,null);if(!l.isArray(t))throw new Error("Input expression for $map must resolve to an array");var e=n.as,i=n["in"],u="$"+e,o=r[u];return l.map(t,function(n){r[u]=n;var t=c(r,i,null);return l.isUndefined(o)?delete r[u]:r[u]=o,t})},$let:function(r,n){var t=n.vars,e=n["in"],i={},u=l.keys(t);l.each(u,function(n){var e=c(r,t[n],null),u="$"+n;i[u]=r[u],r[u]=e});var o=c(r,e,null);return l.each(u,function(n){var t="$"+n;l.isUndefined(i[t])?delete r[t]:r[t]=i[t]}),o}},D={$and:function(r,n){var t=c(r,n,null);return l.every(t)},$or:function(r,n){var t=c(r,n,null);return l.some(t)},$not:function(r,n){return!c(r,n[0],null)}},M=l.extend({},N,O,D,j,q,A,I,b,x,S),Q=h.OP_QUERY="query",C=h.OP_GROUP="group",U=h.OP_AGGREGATE="aggregate",P=h.OP_PIPELINE="pipeline",R=h.OP_PROJECTION="projection",T={aggregate:M,group:k,pipeline:d,projection:E,query:m}}(this); | ||
//# sourceMappingURL=mingo.min.map |
{ | ||
"name": "mingo", | ||
"version": "0.4.2", | ||
"version": "0.5.0", | ||
"description": "JavaScript implementation of MongoDB query language", | ||
@@ -11,3 +11,3 @@ "main": "mingo.js", | ||
"test": "tape test/*.js", | ||
"build": "uglifyjs mingo.js -c -m -o mingo.min.js" | ||
"build": "uglifyjs mingo.js -c -m -o mingo.min.js --source-map mingo.min.map" | ||
}, | ||
@@ -14,0 +14,0 @@ "repository": { |
@@ -44,6 +44,9 @@ # Mingo | ||
- Variable Operators (`$map`, `$let`) | ||
- Support for custom operators | ||
- BackboneJS Integration | ||
- JSON stream filtering and projection. *NodeJS only* | ||
For documentation on using query operators see [mongodb](http://docs.mongodb.org/manual/reference/operator/query/) | ||
## Usage | ||
@@ -130,11 +133,2 @@ ```js | ||
// ex. [ | ||
// { "_id" : 11, "name" : "Marcus Blohm", "scores" : [ | ||
// { "type" : "exam", "score" : 78.42617835651868 }, | ||
// { "type" : "quiz", "score" : 82.58372817930675 }, | ||
// { "type" : "homework", "score" : 87.49924733328717 }, | ||
// { "type" : "homework", "score" : 15.81264595052612 } ] | ||
// }, | ||
// ... | ||
// ] | ||
file = fs.createReadStream('./students.json'); | ||
@@ -168,54 +162,11 @@ | ||
For documentation on using query operators see [mongodb](http://docs.mongodb.org/manual/reference/operator/query/) | ||
## Reference | ||
- [API](https://github.com/kofrasa/mingo/wiki/API) | ||
- [Custom Operators](https://github.com/kofrasa/mingo/wiki/Custom-Operators) | ||
## API | ||
### Mingo.Query(criteria, [projection]) | ||
Creates a `Mingo.Query` object with the given query criteria | ||
- `test(obj)` Returns true if the object passes the query criteria, otherwise false. | ||
- `find(collection, [projection])` Performs a query on a collection and returns a `Mingo.Cursor` object. | ||
- `remove(collection)` Remove matching documents from the collection and return the remainder | ||
- `stream()` Return a `Mingo.Stream` to filter and transform JSON objects from a readable stream. *_NodeJS only_* | ||
### Mingo.Aggregator(expressions) | ||
Creates a `Mingo.Aggregator` object with a collection of aggregation pipeline expressions | ||
- `run()` Apply the pipeline operations over the collection by order of the sequence added | ||
### Mingo.Cursor(collection, query, [projection]) | ||
Creates a `Mingo.Cursor` object which holds the result of applying the query over the collection | ||
- `all()` Returns all the matched documents in a cursor as a collection. | ||
- `first()` Returns the first documents in a cursor. | ||
- `last()` Returns the last document in a cursor | ||
- `count()` Returns a count of the documents in a cursor. | ||
- `limit(n)` Constrains the size of a cursor's result set. | ||
- `skip(n)` Returns a cursor that begins returning results only after passing or skipping a number of documents. | ||
- `sort(modifier)` Returns results ordered according to a sort specification. | ||
- `next()` Returns the next document in a cursor. | ||
- `hasNext()` Returns true if the cursor has documents and can be iterated. | ||
- `max(expression)` Specifies an exclusive upper index bound for a cursor | ||
- `min(expression)` Specifies an inclusive lower index bound for a cursor. | ||
- `map(callback)` Applies a function to each document in a cursor and collects the return values in an array. | ||
- `forEach(callback)` Applies a JavaScript function for every document in a cursor. | ||
### Mingo.Stream(query, [options]) - _NodeJS only_ | ||
A Transform stream that can be piped from/to any readable/writable JSON stream. | ||
### Mingo.CollectionMixin | ||
A mixin object for `Backbone.Collection` which adds `query()` and `aggregate()` methods | ||
- `query(criteria)` Performs a query on the collection and returns a `Mingo.Cursor` object. | ||
- `aggregate(expressions)` Performs aggregation operation using the aggregation pipeline. | ||
### Mingo.find(collection, criteria, [projection]) | ||
Performs a query on a collection and returns a `Mingo.Cursor` object. | ||
### Mingo.remove(collection, criteria) | ||
Returns the non-matched objects as a collection from executing a `Mingo.Query` with the given criteria | ||
### Mingo.aggregate(collection, expressions) | ||
Performs aggregation operation using the aggregation pipeline. | ||
## TODO | ||
- Geospatial Query Operators ($geoWithin, $geoIntersects, $near, $nearSphere) | ||
- Geometry Specifiers ($geometry, $maxDistance, $center, $centerSphere, $box, $polygon) | ||
- Geospatial Query Operators (`$geoWithin`, `$geoIntersects`, `$near`, `$nearSphere`) | ||
- Geometry Specifiers (`$geometry`, `$maxDistance`, `$center`, `$centerSphere`, `$box`, `$polygon`) | ||
## License | ||
MIT |
83288
2030
169