loopback-connector-mongodb
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -0,1 +1,31 @@ | ||
2015-01-23, Version 1.6.0 | ||
========================= | ||
* Small optimisation on the loop in parseUpdateData (Alexandru Savin) | ||
* Optimized the user data parser method (Alexandru Savin) | ||
* Fixed bug where only the first operator was kept and refactored the parsing logic to be reused (Alexandru Savin) | ||
* Allows array operators (Felipe Figueroa) | ||
* Renamed datasource config var for exended parameters (Alexandru Savin) | ||
* set extended operators to true for the tests where they are needed (Alexandru Savin) | ||
* added configuration switch extended_operators and more update operators (Alexandru Savin) | ||
* Added tests (Alexandru Savin) | ||
* Check for valid operators and disregard any other properties (Alexandru Savin) | ||
* allow DB specific mappings for indexes (Felipe Figueroa) | ||
* Changed the solution to use indexOf (Alexandru Savin) | ||
* Give access to all update operators (Alexandru Savin) | ||
* Enable additional update actions (other than $set) (Alexandru Savin) | ||
2015-01-14, Version 1.5.0 | ||
@@ -2,0 +32,0 @@ ========================= |
@@ -312,2 +312,44 @@ /*! | ||
/** | ||
* Parses the data input for update operations and returns the | ||
* sanitised version of the object. | ||
* | ||
* @param data | ||
* @returns {*} | ||
*/ | ||
MongoDB.prototype.parseUpdateData = function(model, data) { | ||
var parsedData = {}; | ||
if (this.settings.allowExtendedOperators === true) { | ||
// Check for other operators and sanitize the data obj | ||
var acceptedOperators = [ | ||
// Field operators | ||
'$currentDate', '$inc', '$max', '$min', '$mul', '$rename', '$setOnInsert', '$set', '$unset', | ||
// Array operators | ||
'$addToSet', '$pop', '$pullAll', '$pull', '$pushAll', '$push', | ||
// Bitwise operator | ||
'$bit' | ||
]; | ||
var usedOperators = 0; | ||
// each accepted operator will take its place on parsedData if defined | ||
for (var i = 0; i < acceptedOperators.length; i++) { | ||
if(data[acceptedOperators[i]]) { | ||
parsedData[acceptedOperators[i]] = data[acceptedOperators[i]]; | ||
usedOperators++; | ||
} | ||
} | ||
// if parsedData is still empty, then we fallback to $set operator | ||
if(usedOperators === 0) { | ||
parsedData.$set = data; | ||
} | ||
} else { | ||
parsedData.$set = data; | ||
} | ||
return parsedData; | ||
}; | ||
/** | ||
* Update if the model instance exists with the same id or create a new instance | ||
@@ -327,8 +369,13 @@ * | ||
var idName = self.idName(model); | ||
var oid = ObjectID(id); | ||
delete data[idName]; | ||
this.collection(model).findAndModify({_id: oid}, [ | ||
// Check for other operators and sanitize the data obj | ||
data = self.parseUpdateData(model, data); | ||
this.collection(model).findAndModify({ | ||
_id: oid | ||
}, [ | ||
['_id', 'asc'] | ||
], {$set: data}, {upsert: true, new: true}, function (err, result) { | ||
], data, {upsert: true, new: true}, function (err, result) { | ||
if (self.debug) { | ||
@@ -608,2 +655,6 @@ debug('updateOrCreate.callback', model, id, err, result); | ||
var self = this; | ||
// Check for other operators and sanitize the data obj | ||
data = self.parseUpdateData(model, data); | ||
if (self.debug) { | ||
@@ -614,6 +665,6 @@ debug('updateAttributes', model, id, data); | ||
var idName = this.idName(model); | ||
delete data[idName]; | ||
this.collection(model).findAndModify({_id: oid}, [ | ||
['_id', 'asc'] | ||
], {$set: data}, {}, function (err, result) { | ||
], data, {}, function (err, result) { | ||
if (self.debug) { | ||
@@ -647,7 +698,14 @@ debug('updateAttributes.callback', model, id, err, result); | ||
var idName = this.idName(model); | ||
where = self.buildWhere(model, where); | ||
delete data[idName]; | ||
where = self.buildWhere(model, where); | ||
this.collection(model).update(where, {$set: data}, {multi: true, upsert: false}, | ||
// Check for other operators and sanitize the data obj | ||
data = self.parseUpdateData(model, data); | ||
this.collection(model).update(where, data, {multi: true, upsert: false}, | ||
function (err, result) { | ||
if (err){ | ||
var t = err; | ||
} | ||
if (self.debug) { | ||
@@ -729,10 +787,24 @@ debug('updateAll.callback', model, where, data, err, result); | ||
if (typeof properties[p].index === 'object') { | ||
// The index value should be the options | ||
options = properties[p].index; | ||
if(options.background === undefined) { | ||
// If there is a mongodb key for the index, use it | ||
if (typeof properties[p].index.mongodb === 'object') { | ||
options = properties[p].index.mongodb; | ||
index[p] = options.kind || 1; | ||
// Backwards compatibility for former type of indexes | ||
if (properties[p].index.unique === true) { | ||
options.unique = true; | ||
} | ||
} else { | ||
// If there isn't an properties[p].index.mongodb object, we read the properties from properties[p].index | ||
options = properties[p].index; | ||
} | ||
if (options.background === undefined) { | ||
options.background = true; | ||
} | ||
// If properties[p].index isn't an object we hardcode the background option and check for properties[p].unique | ||
} else { | ||
options = {background: true}; | ||
if(p.unique) { | ||
if(properties[p].unique) { | ||
options.unique = true; | ||
@@ -792,5 +864,5 @@ } | ||
} | ||
self.db.dropCollection(model, function(err, collection) { | ||
self.db.dropCollection(model, function (err, collection) { | ||
if(err) { | ||
if(!(err.name === 'MongoError' && err.ok === 0 | ||
if(!(err.name === 'MongoError' && err.ok === 0 | ||
&& err.errmsg === 'ns not found')) { | ||
@@ -835,2 +907,1 @@ // For errors other than 'ns not found' (collection doesn't exist) | ||
{ | ||
"name": "loopback-connector-mongodb", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "LoopBack MongoDB Connector", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
// This test written in mocha+should.js | ||
var should = require('./init.js'); | ||
var User, Post, PostWithStringId, db; | ||
var Superhero, User, Post, PostWithStringId, db; | ||
@@ -25,2 +25,12 @@ describe('mongodb', function () { | ||
Superhero = db.define('Superhero', { | ||
name: { type: String, index: true }, | ||
power: { type: String, index: true, unique: true }, | ||
address: { type: String, required: false, index: { mongodb: { unique: false, sparse: true } } }, | ||
description: { type: String, required: false }, | ||
geometry: { type: Object, required: false, index: { mongodb: { kind: "2dsphere" } } }, | ||
age: Number, | ||
icon: Buffer | ||
}); | ||
Post = db.define('Post', { | ||
@@ -36,2 +46,13 @@ title: { type: String, length: 255, index: true }, | ||
Product = db.define('Product', { | ||
name: { type: String, length: 255, index: true }, | ||
description:{ type: String}, | ||
price: { type: Number }, | ||
pricehistory: { type: Object } | ||
}, { | ||
mongodb: { | ||
collection: 'ProductCollection' // Customize the collection name | ||
} | ||
}); | ||
PostWithStringId = db.define('PostWithStringId', { | ||
@@ -117,2 +138,19 @@ id: {type: String, id: true}, | ||
it('should create complex indexes', function (done) { | ||
db.automigrate('Superhero', function () { | ||
db.connector.db.collection('Superhero').indexInformation(function (err, result) { | ||
var indexes = | ||
{ _id_: [ [ '_id', 1 ] ], | ||
geometry_2dsphere: [ [ 'geometry', '2dsphere' ] ], | ||
power_1: [ [ 'power', 1 ] ], | ||
name_1: [ [ 'name', 1 ] ], | ||
address_1: [ [ 'address', 1 ] ] }; | ||
indexes.should.eql(result); | ||
done(err, result); | ||
}); | ||
}); | ||
}); | ||
it('should have created models with correct _id types', function (done) { | ||
@@ -390,2 +428,226 @@ PostWithObjectId.definition.properties._id.type.should.be.equal(db.ObjectID); | ||
describe('updateAll', function () { | ||
it('should update the instance matching criteria', function (done) { | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.create({name: 'Simon', age: 32, email:'simon@strongloop'}, function (err2, createdusers2) { | ||
should.not.exist(err2); | ||
User.create({name: 'Ray', age: 31, email:'ray@strongloop'}, function (err3, createdusers3) { | ||
should.not.exist(err3); | ||
User.updateAll({age:31},{company:'strongloop.com'},function(err,updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(2); | ||
User.find({where:{age:31}},function(err2,foundusers) { | ||
should.not.exist(err2); | ||
foundusers[0].company.should.be.equal('strongloop.com'); | ||
foundusers[1].company.should.be.equal('strongloop.com'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should clean the data object', function (done) { | ||
User.dataSource.settings.allowExtendedOperators = true; | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.create({name: 'Simon', age: 32, email:'simon@strongloop'}, function (err2, createdusers2) { | ||
should.not.exist(err2); | ||
User.create({name: 'Ray', age: 31, email:'ray@strongloop'}, function (err3, createdusers3) { | ||
should.not.exist(err3); | ||
User.updateAll({}, {age: 40, '$set': {age: 39}},function(err,updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(3); | ||
User.find({where:{age:40}},function(err2, foundusers) { | ||
should.not.exist(err2); | ||
foundusers.length.should.be.equal(0); | ||
User.find({where:{age:39}}, function(err3, foundusers) { | ||
should.not.exist(err3); | ||
foundusers.length.should.be.equal(3); | ||
User.updateAll({}, {'$set': {age: 40}, age: 39}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(3); | ||
User.find({where:{age:40}},function(err2, foundusers) { | ||
should.not.exist(err2); | ||
foundusers.length.should.be.equal(3); | ||
User.find({where:{age:39}}, function(err3, foundusers) { | ||
should.not.exist(err3); | ||
foundusers.length.should.be.equal(0); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should use $set by default if no operator is supplied', function (done) { | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.create({name: 'Simon', age: 32, email:'simon@strongloop'}, function (err2, createdusers2) { | ||
should.not.exist(err2); | ||
User.create({name: 'Ray', age: 31, email:'ray@strongloop'}, function (err3, createdusers3) { | ||
should.not.exist(err3); | ||
User.updateAll({name: 'Simon'}, {name: 'Alex'}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.find({where: {name: 'Alex'}}, function (err, founduser) { | ||
should.not.exist(err); | ||
founduser.length.should.be.equal(1); | ||
founduser[0].name.should.be.equal('Alex'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should be possible to use the $inc operator', function (done) { | ||
User.dataSource.settings.allowExtendedOperators = true; | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.create({name: 'Simon', age: 32, email:'simon@strongloop'}, function (err2, createdusers2) { | ||
should.not.exist(err2); | ||
User.create({name: 'Ray', age: 31, email:'ray@strongloop'}, function (err3, createdusers3) { | ||
should.not.exist(err3); | ||
User.updateAll({name: 'Ray'}, {'$inc': {age: 2}}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.find({where: {name: 'Ray'}}, function (err, foundusers) { | ||
should.not.exist(err); | ||
foundusers.length.should.be.equal(1); | ||
foundusers[0].age.should.be.equal(33); | ||
done(); | ||
}); | ||
}) | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should be possible to use the $min and $max operators', function (done) { | ||
User.dataSource.settings.allowExtendedOperators = true; | ||
User.create({name: 'Simon', age: 32, email:'simon@strongloop'}, function (err2, createdusers2) { | ||
should.not.exist(err2); | ||
User.updateAll({name: 'Simon'}, {'$max': {age: 33}}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.updateAll({name: 'Simon'}, {'$min': {age: 31}}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.find({where: {name: 'Simon'}}, function(err, foundusers) { | ||
should.not.exist(err); | ||
foundusers.length.should.be.equal(1); | ||
foundusers[0].age.should.be.equal(31); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should be possible to use the $mul operator', function (done) { | ||
User.dataSource.settings.allowExtendedOperators = true; | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.updateAll({name: 'Al'}, {'$mul': {age: 2}}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.find({where: {name: 'Al'}}, function(err, foundusers) { | ||
should.not.exist(err); | ||
foundusers.length.should.be.equal(1); | ||
foundusers[0].age.should.be.equal(62); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should be possible to use the $rename operator', function (done) { | ||
User.dataSource.settings.allowExtendedOperators = true; | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.updateAll({name: 'Al'}, {'$rename': {name: 'firstname'}}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.find({where: {firstname: 'Al'}}, function(err, foundusers) { | ||
should.not.exist(err); | ||
foundusers.length.should.be.equal(1); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should be possible to use the $unset operator', function (done) { | ||
User.dataSource.settings.allowExtendedOperators = true; | ||
User.create({name: 'Al', age: 31, email:'al@strongloop'}, function (err1, createdusers1) { | ||
should.not.exist(err1); | ||
User.updateAll({name: 'Al'}, {'$unset': {email: ''}}, function(err, updatedusers) { | ||
should.not.exist(err); | ||
updatedusers.should.be.equal(1); | ||
User.find({where: {name: 'Al'}}, function(err, foundusers) { | ||
should.not.exist(err); | ||
foundusers.length.should.be.equal(1); | ||
should.not.exist(foundusers[0].email); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate should update the instance', function (done) { | ||
@@ -413,2 +675,311 @@ Post.create({title: 'a', content: 'AAA'}, function (err, post) { | ||
it('updateAttributes: $addToSet should append item to an Array if it doesn\'t already exist', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90}]}, function (err, product) { | ||
var newattributes= {$set : {description:'goes well with butter'}, $addToSet : { pricehistory: { '2014-12-12':110 } } }; | ||
product.updateAttributes(newattributes, function (err1, inst) { | ||
should.not.exist(err1); | ||
Product.findById(product.id, function (err2, updatedproduct) { | ||
should.not.exist(err2); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-12-12'].should.be.equal(110); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: $addToSet should append item to an Array if it doesn\'t already exist', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90}]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$addToSet = { pricehistory: { '2014-12-12':110 } }; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-12-12'].should.be.equal(110); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: $addToSet should not append item to an Array if it does already exist', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90},{ '2014-10-10':80 }]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$addToSet = { pricehistory: { '2014-10-10':80 } }; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('updateAttributes: $addToSet should not append item to an Array if it does already exist', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90},{ '2014-10-10':80 }]}, function (err, product) { | ||
var newattributes= {$set : {description:'goes well with butter'}, $addToSet : { pricehistory: { '2014-12-12':110 } } }; | ||
product.updateAttributes(newattributes, function (err1, inst) { | ||
should.not.exist(err1); | ||
Product.findById(product.id, function (err2, updatedproduct) { | ||
should.not.exist(err2); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateAttributes: $pop should remove first or last item from an Array', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90},{'2014-10-10':80},{'2014-09-09':70}]}, function (err, product) { | ||
var newattributes= {$set : {description:'goes well with butter'}, $addToSet : { pricehistory: 1 } }; | ||
product.updateAttributes(newattributes, function (err1, inst) { | ||
should.not.exist(err1); | ||
Product.findById(product.id, function (err2, updatedproduct) { | ||
should.not.exist(err2); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: $pop should remove first or last item from an Array', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90},{'2014-10-10':80},{'2014-09-09':70}]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$pop = { pricehistory: 1 }; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
updatedproduct.$pop = { pricehistory: -1 }; | ||
Product.updateOrCreate(product, function (err, p) { | ||
should.not.exist(err); | ||
should.not.exist(p._id); | ||
updatedproduct.pricehistory[0]['2014-10-10'].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateAttributes: $pull should remove items from an Array if they match a criteria', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[70,80,90,100]}, function (err, product) { | ||
var newattributes= {$set : {description:'goes well with butter'}, $pull: { pricehistory: {$gte:90 } } }; | ||
product.updateAttributes(newattributes, function (err1, updatedproduct) { | ||
should.not.exist(err1); | ||
Product.findById(product.id, function (err2, updatedproduct) { | ||
should.not.exist(err1); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0].should.be.equal(70); | ||
updatedproduct.pricehistory[1].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: $pull should remove items from an Array if they match a criteria', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[70,80,90,100]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$pull = { pricehistory: {$gte:90 }}; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0].should.be.equal(70); | ||
updatedproduct.pricehistory[1].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('updateAttributes: $pullAll should remove items from an Array if they match a value from a list', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[70,80,90,100]}, function (err, product) { | ||
var newattributes= {$set : {description:'goes well with butter'}, $pullAll : { pricehistory: [80,100]} }; | ||
product.updateAttributes(newattributes, function (err1, inst) { | ||
should.not.exist(err1); | ||
Product.findById(product.id, function (err2, updatedproduct) { | ||
should.not.exist(err2); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0].should.be.equal(70); | ||
updatedproduct.pricehistory[1].should.be.equal(90); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: $pullAll should remove items from an Array if they match a value from a list', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[70,80,90,100]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$pullAll = { pricehistory: [80,100]}; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0].should.be.equal(70); | ||
updatedproduct.pricehistory[1].should.be.equal(90); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('updateAttributes: $push should append item to an Array even if it does already exist', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90},{ '2014-10-10':80 }]}, function (err, product) { | ||
var newattributes= {$set : {description:'goes well with butter'}, $push : { pricehistory: { '2014-10-10':80 } } }; | ||
product.updateAttributes(newattributes, function (err1, inst) { | ||
should.not.exist(err1); | ||
Product.findById(product.id, function (err2, updatedproduct) { | ||
should.not.exist(err2); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
updatedproduct.pricehistory[2]['2014-10-10'].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: $push should append item to an Array even if it does already exist', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, pricehistory:[{'2014-11-11':90},{ '2014-10-10':80 }]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$push = { pricehistory: { '2014-10-10':80 } }; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
updatedproduct.pricehistory[2]['2014-10-10'].should.be.equal(80); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate: should handle combination of operators and top level properties without errors', function (done) { | ||
Product.dataSource.settings.allowExtendedOperators = true; | ||
Product.create({name: 'bread', price: 100, ingredients:['flour'],pricehistory:[{'2014-11-11':90},{ '2014-10-10':80 }]}, function (err, product) { | ||
product.$set = {description:'goes well with butter'}; | ||
product.$push = { ingredients: 'water' }; | ||
product.$addToSet = { pricehistory: { '2014-09-09':70 } }; | ||
product.description = 'alternative description'; | ||
Product.updateOrCreate(product, function (err, updatedproduct) { | ||
should.not.exist(err); | ||
should.not.exist(updatedproduct._id); | ||
updatedproduct.id.should.be.eql(product.id); | ||
updatedproduct.name.should.be.equal(product.name); | ||
updatedproduct.description.should.be.equal('goes well with butter'); | ||
updatedproduct.ingredients[0].should.be.equal('flour'); | ||
updatedproduct.ingredients[1].should.be.equal('water'); | ||
updatedproduct.pricehistory[0]['2014-11-11'].should.be.equal(90); | ||
updatedproduct.pricehistory[1]['2014-10-10'].should.be.equal(80); | ||
updatedproduct.pricehistory[2]['2014-09-09'].should.be.equal(70); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('updateOrCreate should update the instance without removing existing properties', function (done) { | ||
@@ -415,0 +986,0 @@ Post.create({title: 'a', content: 'AAA', comments: ['Comment1']}, function (err, post) { |
119464
2190