New operator and extended dot operator document search

pull/2/head
lf250055 11 years ago
parent b4ae736d4d
commit d6eeb00d95
  1. 87
      lib/model.js

@ -12,6 +12,7 @@ var dateToJSON = function () { return { $$date: this.getTime() }; }
, lastStepModifierFunctions = {}
, comparisonFunctions = {}
, logicalOperators = {}
, queryOperators = {}
;
@ -439,6 +440,12 @@ function getDotValue (obj, field) {
if (fieldParts.length === 1) {
return obj[fieldParts[0]];
} else if (util.isArray(obj[fieldParts[0]])) {
var objs = new Array();
for (var i = 0; i < obj[fieldParts[0]].length; i += 1) {
objs = objs.concat(getDotValue(obj[fieldParts[0]][i], fieldParts.slice(1).join('.')));
}
return objs;
} else {
return getDotValue(obj[fieldParts[0]], fieldParts.slice(1));
}
@ -566,7 +573,6 @@ comparisonFunctions.$exists = function (value, exists) {
}
};
/**
* Match any of the subqueries
* @param {Model} obj
@ -613,6 +619,17 @@ 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
@ -650,48 +667,56 @@ 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;
// 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)) {
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;
}
var objValue = getDotValue(obj, queryKey)
, i, keys, firstChars, dollarFirstChars;
// 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";
// 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;
}
}
// 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]; }
// 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)) {
if (!comparisonFunctions[keys[i]](objValue, queryValue[keys[i]])) { return false; }
}
return true;
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;
}
}
}
// 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;
}

Loading…
Cancel
Save