|
|
|
@ -573,6 +573,10 @@ comparisonFunctions.$exists = function (value, exists) { |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
queryOperators.$size = function (obj, value) { |
|
|
|
|
return (util.isArray(obj) && obj.length == value); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Match any of the subqueries |
|
|
|
|
* @param {Model} obj |
|
|
|
@ -619,17 +623,6 @@ logicalOperators.$not = function (obj, query) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* |
|
|
|
|
* @param obj |
|
|
|
|
* @param value |
|
|
|
|
* @returns {*|boolean} |
|
|
|
|
*/ |
|
|
|
|
queryOperators.$size = function (obj, value) { |
|
|
|
|
return (util.isArray(obj) && obj.length == value); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Tell if a given document matches a query |
|
|
|
|
* @param {Object} obj Document to check |
|
|
|
@ -670,29 +663,35 @@ function matchQueryPart (obj, queryKey, queryValue) { |
|
|
|
|
var objValue = getDotValue(obj, queryKey) |
|
|
|
|
, i, keys, firstChars, dollarFirstChars; |
|
|
|
|
|
|
|
|
|
keys = Object.keys(queryValue); |
|
|
|
|
firstChars = _.map(keys, function (item) { return item[0]; }); |
|
|
|
|
dollarFirstChars = _.filter(firstChars, function (c) { return c === '$'; }); |
|
|
|
|
|
|
|
|
|
// Check if the object value is an array treat it as an array of { obj, query }
|
|
|
|
|
// Where there needs to be at least one match
|
|
|
|
|
if (util.isArray(objValue)) { |
|
|
|
|
if (dollarFirstChars.length > 0) { |
|
|
|
|
if (!queryOperators[keys[0]]) { throw "Unknown query operator " + keys[i]; } |
|
|
|
|
// Check if it's a query operator
|
|
|
|
|
// TODO REFACTOR!!! keys[0]!!!
|
|
|
|
|
if (queryValue !== null && typeof queryValue === 'object' && !util.isRegExp(queryValue)) { |
|
|
|
|
keys = Object.keys(queryValue); |
|
|
|
|
firstChars = _.map(keys, function (item) { return item[0]; }); |
|
|
|
|
dollarFirstChars = _.filter(firstChars, function (c) { return c === '$'; }); |
|
|
|
|
|
|
|
|
|
// queryValue is an object of this form: { <array>: queryOperator }
|
|
|
|
|
if (dollarFirstChars.length > 0 && queryOperators[keys[0]]) { |
|
|
|
|
if (!queryOperators[keys[0]](objValue, queryValue[keys[0]])) { return false; } |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Else, process every array value
|
|
|
|
|
for (i = 0; i < objValue.length; i += 1) { |
|
|
|
|
if (matchQueryPart({ k: objValue[i] }, 'k', queryValue)) { return true; } // k here could be any string
|
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// queryValue is an actual object. Determine whether it contains comparison operators
|
|
|
|
|
// or only normal fields. Mixed objects are not allowed
|
|
|
|
|
if (queryValue !== null && typeof queryValue === 'object' && !util.isRegExp(queryValue)) { |
|
|
|
|
keys = Object.keys(queryValue); |
|
|
|
|
firstChars = _.map(keys, function (item) { return item[0]; }); |
|
|
|
|
dollarFirstChars = _.filter(firstChars, function (c) { return c === '$'; }); |
|
|
|
|
|
|
|
|
|
if (dollarFirstChars.length !== 0 && dollarFirstChars.length !== firstChars.length) { |
|
|
|
|
throw "You cannot mix operators and normal fields"; |
|
|
|
|