From 1917bffb9ec86520c7c854383a2dd016f49d45d4 Mon Sep 17 00:00:00 2001 From: Louis Chatriot Date: Thu, 11 Jul 2013 12:43:01 +0200 Subject: [PATCH] Created operator --- lib/model.js | 24 ++++++++++++++---------- test/model.test.js | 27 ++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/model.js b/lib/model.js index a29a0dc..82a05d3 100644 --- a/lib/model.js +++ b/lib/model.js @@ -415,15 +415,6 @@ function getDotValue (obj, field) { function areThingsEqual (a, b) { var aKeys , bKeys , i; - // String against regexp - if (util.isRegExp(b)) { - if (typeof a !== 'string') { - return false - } else { - return b.test(a); - } - } - // Strings, booleans, numbers, null if (a === null || typeof a === 'string' || typeof a === 'boolean' || typeof a === 'number' || b === null || typeof b === 'string' || typeof b === 'boolean' || typeof b === 'number') { return a === b; } @@ -512,6 +503,16 @@ comparisonFunctions.$nin = function (a, b) { return !comparisonFunctions.$in(a, b); }; +comparisonFunctions.$regex = function (a, b) { + if (!util.isRegExp(b)) { throw "$regex operator called with non regular expression"; } + + if (typeof a !== 'string') { + return false + } else { + return b.test(a); + } +}; + comparisonFunctions.$exists = function (value, exists) { if (exists || exists === '') { // This will be true for all values of exists except false, null, undefined and 0 exists = true; // That's strange behaviour (we should only use true/false) but that's the way Mongo does it... @@ -638,8 +639,11 @@ function matchQueryPart (obj, queryKey, 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 - // Simple matching is possible + // Basic matching is possible if (!areThingsEqual(objValue, queryValue)) { return false; } return true; diff --git a/test/model.test.js b/test/model.test.js index ab12c1c..c260b8f 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -741,16 +741,41 @@ describe('Model', function () { model.match({ test: d }, { test: r }).should.equal(false); }); - it('Can match strings', function () { + it('Can match strings using basic querying', function () { model.match({ test: 'true' }, { test: /true/ }).should.equal(true); model.match({ test: 'babaaaar' }, { test: /aba+r/ }).should.equal(true); model.match({ test: 'babaaaar' }, { test: /^aba+r/ }).should.equal(false); model.match({ test: 'true' }, { test: /t[ru]e/ }).should.equal(false); }); + it('Can match strings using the $regex operator', function () { + model.match({ test: 'true' }, { test: { $regex: /true/ } }).should.equal(true); + model.match({ test: 'babaaaar' }, { test: { $regex: /aba+r/ } }).should.equal(true); + model.match({ test: 'babaaaar' }, { test: { $regex: /^aba+r/ } }).should.equal(false); + model.match({ test: 'true' }, { test: { $regex: /t[ru]e/ } }).should.equal(false); + }); + + it('Will throw if $regex operator is used with a non regex value', function () { + (function () { + model.match({ test: 'true' }, { test: { $regex: 42 } }) + }).should.throw(); + + (function () { + model.match({ test: 'true' }, { test: { $regex: 'true' } }) + }).should.throw(); + }); + + it('Can use the $regex operator in cunjunction with other operators', function () { + model.match({ test: 'helLo' }, { test: { $regex: /ll/i, $nin: ['helL', 'helLop'] } }).should.equal(true); + model.match({ test: 'helLo' }, { test: { $regex: /ll/i, $nin: ['helLo', 'helLop'] } }).should.equal(false); + }); + it('Can use dot-notation', function () { model.match({ test: { nested: 'true' } }, { 'test.nested': /true/ }).should.equal(true); model.match({ test: { nested: 'babaaaar' } }, { 'test.nested': /^aba+r/ }).should.equal(false); + + model.match({ test: { nested: 'true' } }, { 'test.nested': { $regex: /true/ } }).should.equal(true); + model.match({ test: { nested: 'babaaaar' } }, { 'test.nested': { $regex: /^aba+r/ } }).should.equal(false); }); });