diff --git a/src/dynamo/expression/update-expression-builder.spec.ts b/src/dynamo/expression/update-expression-builder.spec.ts index f23d87a4a..3aa1a476b 100644 --- a/src/dynamo/expression/update-expression-builder.spec.ts +++ b/src/dynamo/expression/update-expression-builder.spec.ts @@ -26,6 +26,16 @@ describe('buildUpdateExpression', () => { }) }) + it('should build expression for number at document path ', () => { + const exp = buildUpdateExpression('numberValues[0]', op, [23], [], metaDataU) + expect(exp).toEqual({ + attributeNames: { '#numberValues': 'numberValues' }, + attributeValues: { ':numberValues_at_0': { N: '23' } }, + statement: '#numberValues[0] = #numberValues[0] + :numberValues_at_0', + type: 'SET', + }) + }) + it('should throw when not number', () => { expect(() => buildUpdateExpression('age', op, ['notANumber'], [], metaDataS)).toThrow() }) @@ -43,6 +53,16 @@ describe('buildUpdateExpression', () => { }) }) + it('should build expression for number at document path ', () => { + const exp = buildUpdateExpression('numberValues[0]', op, [23], [], metaDataU) + expect(exp).toEqual({ + attributeNames: { '#numberValues': 'numberValues' }, + attributeValues: { ':numberValues_at_0': { N: '23' } }, + statement: '#numberValues[0] = #numberValues[0] - :numberValues_at_0', + type: 'SET', + }) + }) + it('should throw when not number', () => { expect(() => buildUpdateExpression('age', op, ['notANumber'], [], metaDataS)).toThrow() }) diff --git a/src/dynamo/expression/update-expression-builder.ts b/src/dynamo/expression/update-expression-builder.ts index bd35dab43..3cd5e92db 100644 --- a/src/dynamo/expression/update-expression-builder.ts +++ b/src/dynamo/expression/update-expression-builder.ts @@ -99,8 +99,10 @@ function buildDefaultExpression( // special case: [same as in buildDefaultConditionExpression] // we have the metadata for an Array/Set of an Object, - // but only get a single item when using `attribute('myCollectionProp[0]').set({})` - if (operator.action === 'set' && /\[\d+\]$/.test(attributePath)) { + // but only get a single item when using list indexes in attributePath + // e.g. `attribute('myCollectionProp[0]').set(...)` + // (not exclusive to `.set(...)` but all updateActions) + if (/\[\d+\]$/.test(attributePath)) { attribute = toDbOne(values[0], getPropertyPath(propertyMetadata, attributePath), alterCollectionPropertyMetadataForSingleItem(propertyMetadata)) } else { attribute = toDbOne(values[0], propertyMetadata) diff --git a/src/dynamo/request/update/update.request.spec.ts b/src/dynamo/request/update/update.request.spec.ts index fa98fea2d..cb3e50baa 100644 --- a/src/dynamo/request/update/update.request.spec.ts +++ b/src/dynamo/request/update/update.request.spec.ts @@ -53,7 +53,7 @@ describe('update request', () => { expect(req.params.ReturnValues).toEqual('UPDATED_OLD') }) - it('should add operations', () => { + it('should add operation 1', () => { const now = new Date() const request = new UpdateRequest(null, UpdateModel, 'myId') request.operations(update('lastUpdated').set(now)) @@ -64,6 +64,16 @@ describe('update request', () => { ':lastUpdated': { S: now.toISOString() }, }) }) + it('should add operation 2', () => { + const request = new UpdateRequest(null, UpdateModel, 'myId') + request.operations(update('numberValues[1]').incrementBy(42)) + + expect(request.params.UpdateExpression).toBe('SET #numberValues[1] = #numberValues[1] + :numberValues_at_1') + expect(request.params.ExpressionAttributeNames).toEqual({ '#numberValues': 'numberValues' }) + expect(request.params.ExpressionAttributeValues).toEqual({ + ':numberValues_at_1': { N: '42' }, + }) + }) it('should allow to add multiple operations', () => { const request = new UpdateRequest(null, UpdateModel, 'myId').operations(