3

I have tried all methods mentioned in many different docs of aws dynamoDB. like this and this.

Also referred to this post.

But it just doesn't seem to work.

I have this entry in dynamoDB:

dict1={
    'token':1234567890,
    'name':'bigCompany',
    'nestedDict':{
        'a':3810,
        'b':3815,
        'c':3805,
        'd':3811
        },
    'High1':3815,
    'Low1':3805
}

And i'm using this code to update an attribute:

updater = table.update_item(
    Key={
        'token': '1234567890',
        'name':'bigCompany'
    },
    ExpressionAttributeNames={'#LM':'Low1'},
    ExpressionAttributeValues={
        ':nlm': {
            'N':'3802'
            }
    },
    ReturnValues='UPDATED_OLD',
    UpdateExpression='SET #LM = :nlm',
)

This is the stack trace:

Traceback (most recent call last):
  File "updating1.py", line 89, in <module>
    UpdateExpression='SET #LM = :nlm',
  File ".local/lib/python3.7/site-packages/boto3/resources/factory.py", line 520, in do_action
    response = action(self, *args, **kwargs)
  File ".local/lib/python3.7/site-packages/boto3/resources/action.py", line 83, in __call__
    response = getattr(parent.meta.client, operation_name)(*args, **params)
  File ".local/lib/python3.7/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File ".local/lib/python3.7/site-packages/botocore/client.py", line 676, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the UpdateItem operation: The provided key element does not match the schema

What am i missing here.

Harsh Math
  • 443
  • 5
  • 12
  • just a quick guess, but do you need quotes around the `nlm` value? Should it read `'N':3802` (no quotes around the number?) – Seth Geoghegan Dec 03 '20 at 20:30
  • Is `table` a DynamoDB resource or a DynamoDB client? Presume the former. With the resource-level API, you don't provide numeric values as strings and you don't have to indicate `{ 'N': 'value' }` so use `'token': 1234567890` in the key and `':nlm': 3802` in the ExpressionAttributeValues. – jarmod Dec 03 '20 at 20:41
  • @SethGeoghegan i have tried both ways but the error sustains – Harsh Math Dec 04 '20 at 08:48
  • @jarmod i took a hint from your pointer about resource and client. I had initialized the object as a resource but was referring to documentation for a client. After following steps for client, i was finally able to update.. However, it seems i have to stick to {'N':'value'} {'S':'Value'} type syntax for clients.. whereas in resource it seems it's not required.. i will check that as well..... Many thanks for the pointer.. – Harsh Math Dec 04 '20 at 09:29
  • @jarmod i referred to [this](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html) documentation about dynamodb resource, and followed all steps but it gives out the same error as in my question.. – Harsh Math Dec 04 '20 at 09:38
  • UPDATE: i was able to update using the link mentioned in the above comment... thanks all for your help – Harsh Math Dec 04 '20 at 11:58
  • pl check my answer.. it will make it clear – Harsh Math Dec 04 '20 at 12:09
  • The fix I gave you earlier worked correctly. I just tested it. And I explained the difference between the two APIs (client and resource) which you had mixed up. – jarmod Dec 04 '20 at 13:21
  • yes, as i mentioned in my earlier comment, i had initialized the boto3 object as a resource but was referring to documentation of client. I got that hint from your comment. – Harsh Math Dec 04 '20 at 14:22
  • I guess I'm not being clear here somehow, but I'm glad the problem is resolved. – jarmod Dec 04 '20 at 14:31

1 Answers1

3

Based on the pointers provided by good people in comments, i was able to resolve this so updating both methods.

The issue originally was, i had initiated a boto3 object as a resource using boto3.resource(), however was referring to aws documentation of boto3.client().

If you're using a resource, the update method is easier: this is documentation link for boto3 resource

changer = table.update_item(
    Key={
        'token': '1234567890',
        'name':'bigCompany'
    },
    UpdateExpression='SET LM = :val1',
    ExpressionAttributeValues={
        ':val1': 3802
    }
)

However, if you're using a client, then you'll have to change the syntax: this is the documentation link for boto3 client

changer = client.update_item(
    Key={
        'token': {
            'N':'1234567890',
            },
        'company': {
            'S':'bigCompany'
            },
    },
    ExpressionAttributeNames={'#LM':'val1'},
    ExpressionAttributeValues={
        ':val1': {
            'N':'3802',
        },
    },
    ReturnValues='UPDATED_OLD',
    UpdateExpression='SET #LM = :val1',
    TableName='myTable'
)

Hope no one get's confused now.

Harsh Math
  • 443
  • 5
  • 12
  • You should indicate `'token': 1234567890` if token is a number. While it appears to work if you supply it as a string, because boto3 or DynamoDB is converting string to numeric, it's not a string (at least according to your original post). – jarmod Dec 04 '20 at 13:25
  • yes, i guess it's a typo.. it should be `'token':1234567890` for a resource object. – Harsh Math Dec 04 '20 at 14:23
  • What a nightmare, different syntaxes for different methods. Thanks Amazon. Thanks @HarshMath for figuring it out. – Jim Bob May 05 '23 at 12:25