clarkie / dynogels

DynamoDB data mapper for node.js. Originally forked from https://github.com/ryanfitz/vogels

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Docs need updating for Exists condition

austin43 opened this issue · comments

Currently, the dynogels docs say you can use: Exists: true as a param, but specifying this without a Value causes dynamo to throw: ExpressionAttributeValues must not be empty.

Per the AWS docs:
The default setting for Exists is true. If you supply a Value all by itself, DynamoDB assumes the attribute exists: You don't have to set Exists to true, because it is implied.

DynamoDB returns a ValidationException if:
Exists is true but there is no Value to check. (You expect a value to exist, but don't specify what that value is.)

I think we should update the docs to specify this like { email: { Value: 'my@email.com'} }.

dynogels@9.0.0

EDIT

Upon looking deeper at this functionality, it seems the similarities of usage of "Exists" are only coincidental. Looks like manual construction vs. using dynamo ExpectedAttributeValue.

Because an empty object of ExpressionAttributeValues is generated, the aws sdk is complaining. Is this potentially only a factor on newer aws sdk versions?

await MyModel.destroyAsync('Id-123', 'Id-123', { expected: { Id: { Exists: true } } })

generates

  Key: { Id: 'Id-123', EntityId: 'Id-123' },
  ExpressionAttributeNames: { '#EntityId': 'EntityId', '#Id': 'Id' },
  ExpressionAttributeValues: {},
  ConditionExpression: '(attribute_exists(#Id)) AND (attribute_exists(#EntityId))' }

A valid workaround for now is to pass Expected in to the params:


await MyModel.destroyAsync('Id-123', 'Id-123', {
	Expected: {
		Id: {
			Value:'Id-123'
		},
		EntityId: {
			Value: 'Id-123'
		}
	}
})

await MyModel.destroyAsync('Id-123', 'Id-123', { expected: { Id: { Exists: true } } })

generates

  Key: { Id: 'Id-123', EntityId: 'Id-123' },
  ExpressionAttributeNames: { '#EntityId': 'EntityId', '#Id': 'Id' },
  ExpressionAttributeValues: {},
  ConditionExpression: '(attribute_exists(#Id)) AND (attribute_exists(#EntityId))' }

This looks like a valid query to me.

I'm guessing the problem is that ExpressionAttributeValues must either contain at least one attribute or not be passed at all. That is, omitting it should work but passing {} is probably being rejected.

If that's the case, this is a breaking change that DynamoDB and/or aws-sdk made.

Can you write a service-level test that fails?