diff --git a/lib/model.js b/lib/model.js index e6899b4..53c7979 100644 --- a/lib/model.js +++ b/lib/model.js @@ -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 @@ -620,18 +624,7 @@ 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 + * Tell if a given document matches a query * @param {Object} obj Document to check * @param {Object} query */ @@ -667,56 +660,62 @@ function match (obj, query) { * Match an object against a specific { key: value } part of a query */ function matchQueryPart (obj, queryKey, queryValue) { - var objValue = getDotValue(obj, queryKey) - , i, keys, firstChars, dollarFirstChars; + var objValue = getDotValue(obj, queryKey) + , i, keys, firstChars, dollarFirstChars; + + // 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)) { + // 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: { : queryOperator } + if (dollarFirstChars.length > 0 && queryOperators[keys[0]]) { + if (!queryOperators[keys[0]](objValue, queryValue[keys[0]])) { return false; } + return true; + } + } + // 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 === '$'; }); - // 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]; } - - if (!queryOperators[keys[0]](objValue, queryValue[keys[0]])) { return false; } - return true; - } else { - 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; - } + if (dollarFirstChars.length !== 0 && dollarFirstChars.length !== firstChars.length) { + throw "You cannot mix operators and normal fields"; } - // 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)) { + // queryValue is an object of this form: { $comparisonOperator1: value1, ... } + if (dollarFirstChars.length > 0) { + for (i = 0; i < keys.length; i += 1) { + if (!comparisonFunctions[keys[i]]) { throw "Unknown comparison function " + keys[i]; } - if (dollarFirstChars.length !== 0 && dollarFirstChars.length !== firstChars.length) { - throw "You cannot mix operators and normal fields"; - } - - // queryValue is an object of this form: { $comparisonOperator1: value1, ... } - if (dollarFirstChars.length > 0) { - for (i = 0; i < keys.length; i += 1) { - if (!comparisonFunctions[keys[i]]) { throw "Unknown comparison function " + keys[i]; } - - if (!comparisonFunctions[keys[i]](objValue, queryValue[keys[i]])) { return false; } - } - return true; - } + if (!comparisonFunctions[keys[i]](objValue, queryValue[keys[i]])) { return false; } + } + return true; } + } - // Using regular expressions with basic querying - if (util.isRegExp(queryValue)) { return comparisonFunctions.$regex(objValue, queryValue); } + // Using regular expressions with basic querying + if (util.isRegExp(queryValue)) { return comparisonFunctions.$regex(objValue, queryValue); } - // queryValue is either a native value or a normal object - // Basic matching is possible - if (!areThingsEqual(objValue, queryValue)) { return false; } + // queryValue is either a native value or a normal object + // Basic matching is possible + if (!areThingsEqual(objValue, queryValue)) { return false; } - return true; + return true; }