diff --git a/lib/model.js b/lib/model.js index 935f6df..4a6f341 100644 --- a/lib/model.js +++ b/lib/model.js @@ -9,6 +9,7 @@ var dateToJSON = function () { return { $$date: this.getTime() }; } , util = require('util') , _ = require('underscore') , modifierFunctions = {} + , matcherFunctions = {} ; @@ -125,6 +126,10 @@ function deepCopy (obj) { } +// ============================================================== +// Updating documents +// ============================================================== + /** * Set field to value in a model * Create it if it doesn't exist @@ -221,6 +226,30 @@ function modify (obj, updateQuery) { }; +// ============================================================== +// Finding documents +// ============================================================== + +/** + * Test for field equality + * @param {Object} obj The model to check + * @param {String} field Can contain dots, in that case that means we will set a subfield recursively + * @param {Model} value + */ +matcherFunctions.$eq = function (obj, field, value) { + var fieldParts = typeof field === 'string' ? field.split('.') : field; + + if (!obj) { return false; } // field cannot be empty here so that means there is no match + + if (fieldParts.length === 1) { + return obj[fieldParts[0]] === value; + } else { + return matcherFunctions.$eq(obj[fieldParts[0]], fieldParts.slice(1), value); + } +}; + + + /** * Tell if a given document matches a query */ @@ -229,7 +258,7 @@ function match (obj, query) { , i, k; Object.keys(query).forEach(function (k) { - if (obj[k] !== query[k]) { match = false; } + if (!matcherFunctions.$eq(obj, k, query[k])) { match = false; } }); return match; diff --git a/test/db.test.js b/test/db.test.js index 6f32d06..a0b21f5 100644 --- a/test/db.test.js +++ b/test/db.test.js @@ -233,7 +233,7 @@ describe('Database', function () { ], done); }); - it.skip('Can use dot-notation to query subfields', function (done) { + it('Can use dot-notation to query subfields', function (done) { d.insert({ greeting: { english: 'hello' } }, function () { d.findOne({ "greeting.english": 'hello' }, function (err, doc) { doc.greeting.english.should.equal('hello'); diff --git a/test/model.test.js b/test/model.test.js index 758787d..b1178f9 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -327,4 +327,31 @@ describe('Model', function () { }); // ==== End of 'Modifying documents' ==== // + + describe('Finding documents', function () { + + describe('$eq', function () { + + it('Can find documents with simple fields', function () { + model.match({ test: 'yeah' }, { test: 'yea' }).should.equal(false); + model.match({ test: 'yeah' }, { test: 'yeahh' }).should.equal(false); + model.match({ test: 'yeah' }, { test: 'yeah' }).should.equal(true); + }); + + it('Can find documents with the dot-notation', function () { + model.match({ test: { ooo: 'yeah' } }, { "test.ooo": 'yea' }).should.equal(false); + model.match({ test: { ooo: 'yeah' } }, { "test.oo": 'yeah' }).should.equal(false); + model.match({ test: { ooo: 'yeah' } }, { "tst.ooo": 'yeah' }).should.equal(false); + model.match({ test: { ooo: 'yeah' } }, { "test.ooo": 'yeah' }).should.equal(true); + }); + + it('Can find undefined in first level or dot notation', function () { + model.match({ test: undefined }, { test: undefined }).should.equal(true); + model.match({ test: { pp: undefined } }, { "test.pp": undefined }).should.equal(true); + }); + + }); + + }); // ==== End of 'Finding documents' ==== // + });