diff --git a/lib/model.js b/lib/model.js index a8427ae..9f561c2 100644 --- a/lib/model.js +++ b/lib/model.js @@ -287,7 +287,7 @@ function getDotValue (obj, field) { /** - * Match any of the subconditions + * Match any of the subqueries */ matcherFunctions.$or = function (obj, query) { var i; @@ -302,6 +302,22 @@ matcherFunctions.$or = function (obj, query) { }; +/** + * Match all of the subqueries + */ +matcherFunctions.$and = function (obj, query) { + var i; + + if (!util.isArray(query)) { throw "$and operator used without an array"; } + + for (i = 0; i < query.length; i += 1) { + if (!match(obj, query[i])) { return false; } + } + + return true; +}; + + /** * Tell if a given document matches a query * @param {Object} obj Document to check diff --git a/test/model.test.js b/test/model.test.js index 3624395..55b427b 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -488,6 +488,22 @@ describe('Model', function () { model.match({ hello: 'world', age: 15 }, { $and: [ { hello: 'pluton' }, { age: { $lt: 20 } } ] }).should.equal(false); }); + it('Logical operators are all top-level, only other logical operators can be above', function () { + model.match({ a: { b: 7 } }, { a: { $or: [ { b: 5 }, { b: 7 } ] } }).should.equal(false); + model.match({ a: { b: 7 } }, { $or: [ { "a.b": 5 }, { "a.b": 7 } ] }).should.equal(true); + }); + + it('Logical operators can be combined as long as they are on top of the decision tree', function () { + model.match({ a: 5, b: 7, c: 12 }, { $or: [ { $and: [ { a: 5 }, { b: 8 } ] }, { $and: [{ a: 5 }, { c : { $lt: 40 } }] } ] }).should.equal(true); + model.match({ a: 5, b: 7, c: 12 }, { $or: [ { $and: [ { a: 5 }, { b: 8 } ] }, { $and: [{ a: 5 }, { c : { $lt: 10 } }] } ] }).should.equal(false); + }); + + it('Should throw an error if a logical operator is used without an array or if an unknown logical operator is used', function () { + (function () { model.match({ a: 5 }, { $or: { a: 5, a: 6 } }); }).should.throw(); + (function () { model.match({ a: 5 }, { $and: { a: 5, a: 6 } }); }).should.throw(); + (function () { model.match({ a: 5 }, { $unknown: [ { a: 5 } ] }); }).should.throw(); + }); + }); }); // ==== End of 'Finding documents' ==== //