Merge branch 'master' of github.com:lfthomaz/nedb into lfthomaz-master

pull/2/head
Louis Chatriot 11 years ago
commit 421311e234
  1. 33
      lib/model.js
  2. 33
      test/model.test.js

@ -12,6 +12,7 @@ var dateToJSON = function () { return { $$date: this.getTime() }; }
, lastStepModifierFunctions = {}
, comparisonFunctions = {}
, logicalOperators = {}
, queryOperatorArray = {}
;
@ -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,6 +573,12 @@ comparisonFunctions.$exists = function (value, exists) {
}
};
queryOperatorArray.$size = function (obj, value) {
if (!util.isArray(obj)) { throw "$size operator not being applied to an array"; }
if (value % 1 !== 0) { throw "$size operator called without an integer"; }
return (obj.length == value);
};
/**
* Match any of the subqueries
@ -614,7 +627,7 @@ logicalOperators.$not = function (obj, query) {
/**
* 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
*/
@ -652,10 +665,22 @@ function match (obj, 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
// Check if the object value is an array
if (util.isArray(objValue)) {
// Check if it's a query operator array
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 (keys.length == 1 && dollarFirstChars.length > 0 && queryOperatorArray[keys[0]]) {
if (!queryOperatorArray[keys[0]](objValue, queryValue[keys[0]])) { return false; }
return true;
}
}
// Else, treat it as an array of { obj, query } where there needs to be at least one match
for (i = 0; i < objValue.length; i += 1) {
if (matchQueryPart({ k: objValue[i] }, 'k', queryValue)) { return true; } // k here could be any string
}

@ -1079,7 +1079,30 @@ describe('Model', function () {
});
describe('Array fields', function () {
describe('Query operator array $size', function () {
it('$size', function () {
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens": { $size: 0 } }).should.equal(false);
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens": { $size: 2 } }).should.equal(false);
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens": { $size: 3 } }).should.equal(true);
});
it('$size operator works with empty arrays', function () {
model.match({ childrens: [ ] }, { "childrens": { $size: 0 } }).should.equal(true);
model.match({ childrens: [ ] }, { "childrens": { $size: 2 } }).should.equal(false);
model.match({ childrens: [ ] }, { "childrens": { $size: 3 } }).should.equal(false);
});
it('Should throw an error if a query operator is used without being applied to an array and comparing to an integer', function () {
(function () { model.match({ a: 5 }, { a: { $size: 1 } }); }).should.throw();
(function () { model.match({ a: [1, 5] }, { a: { $size: 1.4 } }); }).should.throw();
(function () { model.match({ a: [1, 5] }, { a: { $size: 'fdf' } }); }).should.throw();
});
});
describe('Array fields', function () {
it('Field equality', function () {
model.match({ tags: ['node', 'js', 'db'] }, { tags: 'python' }).should.equal(false);
@ -1111,6 +1134,14 @@ describe('Model', function () {
model.match({ children: { ages: [3, 7, 12] } }, { "children.ages": { $lt: 13 } }).should.equal(true);
});
it('Works also with arrays of objects that are in subdocuments', function () {
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens.age": { $lt: 2 } }).should.equal(false);
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens.age": { $lt: 3 } }).should.equal(false);
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens.age": { $lt: 4 } }).should.equal(true);
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens.age": { $lt: 8 } }).should.equal(true);
model.match({ childrens: [ { name: "Huey", age: 3 }, { name: "Dewey", age: 7 }, { name: "Louie", age: 12 } ] }, { "childrens.age": { $lt: 13 } }).should.equal(true);
});
});
}); // ==== End of 'Finding documents' ==== //

Loading…
Cancel
Save