diff --git a/lib/Model.js b/lib/Model.js index d29aa536f..0528fb91a 100644 --- a/lib/Model.js +++ b/lib/Model.js @@ -799,6 +799,7 @@ Model.update = async function(NewModel, key, update, options, next) { this.SET = {}; this.ADD = {}; this.REMOVE = {}; + this.LISTAPPEND = {}; this.addIfNotExistsSet = function(name, item) { this.ifNotExistsSet[name] = item; @@ -810,6 +811,12 @@ Model.update = async function(NewModel, key, update, options, next) { } }; + this.addListAppend = function(name, item) { + if(schema.hashKey.name !== name && (schema.rangeKey || {}).name !== name) { + this.LISTAPPEND[name] = item; + } + }; + this.addAdd = function(name, item) { if(schema.hashKey.name !== name && (schema.rangeKey || {}).name !== name) { this.ADD[name] = item; @@ -859,6 +866,19 @@ Model.update = async function(NewModel, key, update, options, next) { attrCount += 1; } + for (name in this.LISTAPPEND) { + item = this.LISTAPPEND[name]; + + attrName = '#_n' + attrCount; + valName = ':_p' + attrCount; + + updateReq.ExpressionAttributeNames[attrName] = name; + updateReq.ExpressionAttributeValues[valName] = item; + + setExpressions.push(attrName + ' = ' + `list_append(${attrName}, ${valName})`); + + attrCount += 1; + } if (setExpressions.length > 0) { updateExpression += `SET ${setExpressions.join(',')} `; } @@ -964,7 +984,11 @@ Model.update = async function(NewModel, key, update, options, next) { let addVal = update.$ADD[addItem]; try { if (addAttr) { - operations.addAdd(addItem, await addAttr.toDynamo(addVal)); + if (addAttr.type.name === "list") { + operations.addListAppend(addItem, await addAttr.toDynamo(addVal)); + } else { + operations.addAdd(addItem, await addAttr.toDynamo(addVal)); + } } else if (schema.options.saveUnknown) { operations.addAdd(addItem, await Attribute.create(schema, addItem, addVal).toDynamo(addVal)); } diff --git a/test/Model.js b/test/Model.js index b9644c921..6cd57b649 100644 --- a/test/Model.js +++ b/test/Model.js @@ -2271,6 +2271,23 @@ describe('Model', function (){ }); }); + it('Add attribute to list', function (done) { + Cats.Cat13.create({id: 1000, items: [{name: "item 2", amount: 25}]}, function () { + Cats.Cat13.update({id: 1000}, {$ADD: {items: [{name: "item 1", amount: 50}]}}, function (err, data) { + should.not.exist(err); + should.exist(data); + data.id.should.eql(1000); + data.items.should.eql([{name: "item 2", amount: 25}, {name: "item 1", amount: 50}]); + Cats.Cat13.get(1000, function (err, cat){ + should.not.exist(err); + should.exist(cat); + cat.id.should.eql(1000); + cat.items.should.eql([{name: "item 2", amount: 25}, {name: "item 1", amount: 50}]); + done(); + }); + }); + }); + }); it('Delete attribute', function (done) { Cats.Cat.update({id: 999}, {$DELETE: {owner: null}}, function (err, data) { should.not.exist(err); diff --git a/test/fixtures/Cats.js b/test/fixtures/Cats.js index faa8f8310..b33665e10 100644 --- a/test/fixtures/Cats.js +++ b/test/fixtures/Cats.js @@ -392,6 +392,29 @@ module.exports = function(dynamoose){ name: String }); + var Cat13 = dynamoose.model('Cat13', + { + id: { + type: Number, + validate: function (v) { return v > 0; } + }, + items: { + type: "list", + list: [ + { + name: { + type: String, + required: true + }, + amount: { + type: Number, + required: true + } + } + ] + } + }); + var CatWithMethodsSchema = new dynamoose.Schema({ id: Number, name: String @@ -422,6 +445,7 @@ module.exports = function(dynamoose){ Cat10: Cat10, Cat11: Cat11, Cat12: Cat12, + Cat13: Cat13, CatWithOwner: CatWithOwner, Owner: Owner, ExpiringCat: ExpiringCat,