diff --git a/lib/datastore.js b/lib/datastore.js index 1c5bd76..e488c12 100644 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -282,5 +282,4 @@ Datastore.prototype.remove = function (query, options, cb) { }; - module.exports = Datastore; diff --git a/lib/model.js b/lib/model.js index af7c306..98f4229 100644 --- a/lib/model.js +++ b/lib/model.js @@ -133,13 +133,13 @@ function deepCopy (obj) { * @param {Model} value */ modifierFunctions.$set = function (obj, field, value) { - var fieldParts = field.split('.'); + var fieldParts = typeof field === 'string' ? field.split('.') : field; if (fieldParts.length === 1) { - obj[field] = value; + obj[fieldParts[0]] = value; } else { obj[fieldParts[0]] = obj[fieldParts[0]] || {}; - modifierFunctions.$set(obj[fieldParts[0]], fieldParts.slice(1).join('.'), value); + modifierFunctions.$set(obj[fieldParts[0]], fieldParts.slice(1), value); } }; @@ -152,23 +152,23 @@ modifierFunctions.$set = function (obj, field, value) { * @param {Model} value */ modifierFunctions.$inc = function (obj, field, value) { - var fieldParts = field.split('.'); + var fieldParts = typeof field === 'string' ? field.split('.') : field; if (typeof value !== 'number') { throw value + " must be a number"; } if (fieldParts.length === 1) { - if (typeof obj[field] !== 'number') { - if (!_.has(obj, field)) { - obj[field] = value; + if (typeof obj[fieldParts[0]] !== 'number') { + if (!_.has(obj, fieldParts[0])) { + obj[fieldParts[0]] = value; } else { throw "Don't use the $inc modifier on non-number fields"; } } else { - obj[field] += value; + obj[fieldParts[0]] += value; } } else { obj[fieldParts[0]] = obj[fieldParts[0]] || {}; - modifierFunctions.$inc(obj[fieldParts[0]], fieldParts.slice(1).join('.'), value); + modifierFunctions.$inc(obj[fieldParts[0]], fieldParts.slice(1), value); } }; diff --git a/test/db.test.js b/test/db.test.js index afec11c..f104b7a 100644 --- a/test/db.test.js +++ b/test/db.test.js @@ -484,6 +484,28 @@ describe('Database', function () { }); }); + it('When using modifiers, the only way to update subdocs is with the dot-notation', function (done) { + d.insert({ bloup: { blip: "blap", other: true } }, function () { + // Correct methos + d.update({}, { $set: { "bloup.blip": "hello" } }, {}, function () { + d.findOne({}, function (err, doc) { + doc.bloup.blip.should.equal("hello"); + doc.bloup.other.should.equal(true); + + // Wrong + d.update({}, { $set: { bloup: { blip: "ola" } } }, {}, function () { + d.findOne({}, function (err, doc) { + doc.bloup.blip.should.equal("ola"); + assert.isUndefined(doc.bloup.other); // This information was lost + + done(); + }); + }); + }); + }); + }); + }); + }); // ==== End of 'Update' ==== // @@ -534,9 +556,33 @@ describe('Database', function () { ], done); }); - }); // ==== End of 'Remove' ==== // - + // This tests concurrency issues + // Right now, it doesn't pass, because I need to + //it.only('Remove can be called multiple times in parallel and everything that needs to be removed will be', function (done) { + //d.insert({ planet: 'Earth' }, function () { + //d.insert({ planet: 'Mars' }, function () { + //d.insert({ planet: 'Saturn' }, function () { + //d.find({}, function (err, docs) { + //docs.length.should.equal(3); + + //// Remove two docs simultaneously + //var toRemove = ['Mars', 'Saturn']; + //async.each(toRemove, function(planet, cb) { + //d.remove({ planet: planet }, function (err) { return cb(err); }); + //}, function (err) { + //d.find({}, function (err, docs) { + //docs.length.should.equal(1); + + //done(); + //}); + //}); + //}); + //}); + //}); + //}); + //}); + }); // ==== End of 'Remove' ==== // });