17

I am new to dynamodb trying to get data from dynamodb.

This is my table with "topic" as a primary hash key

my python code

import boto3 
from boto3 import dynamodb 

from boto3.session import Session

from boto3.dynamodb.conditions import Key, Attr


dynamodb_session = Session(aws_access_key_id='XXXXXXXXXXXXXXX',
          aws_secret_access_key='XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
          region_name='us-east-1')

dynamodb = dynamodb_session.resource('dynamodb')

table=dynamodb.Table('Garbage_collector_table')

my_topic = "$aws/things/garbage_collector_thing/shadow/update/accepted"

response = table.get_item(TableName='Garbage_collector_table', Key={'topic':my_topic})

for res in response: 
    print "result ",res

I am getting the following error

Traceback (most recent call last):
 File "get-data-dynamodb-boto3.py", line 19, in <module>
    response = table.get_item(TableName='Garbage_collector_table', Key={'topic': my_topic})   File
 "/usr/local/lib/python2.7/dist-packages/boto3/resources/factory.py",
 line 518, in do_action
     response = action(self, *args, **kwargs)   File "/usr/local/lib/python2.7/dist-packages/boto3/resources/action.py",
 line 83, in __call__
     response = getattr(parent.meta.client, operation_name)(**params)   File "/usr/local/lib/python2.7/dist-packages/botocore/client.py", line
 258, in _api_call
     return self._make_api_call(operation_name, kwargs)   File /usr/local/lib/python2.7/dist-packages/botocore/client.py", line 548,
 in _make_api_call
     raise ClientError(parsed_response, operation_name)

botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the GetItem operation: The provided key element does not match the schema

am I missing anything in my code?

Dawny33
  • 10,543
  • 21
  • 82
  • 134
Narendra M
  • 183
  • 1
  • 1
  • 6

7 Answers7

40

You are mixing resource and client objects which have different methods. More info is here.

The correct syntax for a boto3 resource is:

response = table.get_item(Key={'topic': my_topic})

And the correct syntax for a boto3 client is:

client = boto3.client('dynamodb')
response = client.get_item(TableName='Garbage_collector_table', Key={'topic':{'S':str(my_topic)}})

Reference: Boto3 - DynamoDB

Abdullah Khawer
  • 4,461
  • 4
  • 29
  • 66
Eyal Ch
  • 9,552
  • 5
  • 44
  • 54
  • 5
    This way did not work for me. What worked was the `Key` in the firm `Key={'topic': my_topic}` – Marcin Oct 09 '18 at 23:43
  • 2
    I echo @Marcin, the accepted answer didn't work for me, whereas the format `Key={'topic': my_topic}` did work. – Michael Coxon Aug 17 '19 at 00:24
  • Boto3 provides 2 ways to interact with a DyanmoDB table. The `Key={'topic': my_topic}` style is correct only if you are using the DynamoDB table resource. If you are using the client, as in this example, the other format is correct. – Trenton Nov 09 '22 at 19:05
6

You can also query the database:

from boto3.dynamodb.conditions import Key

table = dynamodb.Table(table_name)
response = table.query(
    KeyConditionExpression=Key('topic').eq(my_topic)
)
items = response['Items']
if items:
    return items[0]
else:
    return []

Source: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Python.04.html

Tomiwa
  • 840
  • 12
  • 14
  • 1
    Thanks @Tomiwa. Just in case this helps anyone, the above code will throw an error if 'Items' is not in the response. Better to check `if "Items" in response: items = response["Items"]` – dillon.harless Nov 19 '19 at 19:52
  • 3
    Good point @dillon, alternatively you can also do `items = response.get("Items", None)` or `items = response.get("Items", [])` – Tomiwa Nov 20 '19 at 03:12
1

There are actual examples here: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html

In your case, you need to do this:

response = table.get_item(TableName='Garbage_collector_table', Key={'topic': my_topic})
mprivat
  • 21,582
  • 4
  • 54
  • 64
1

I'm the author of Lucid-Dynamodb, a minimalist wrapper to AWS DynamoDB. This problem can be easily solved using my library.

Reference: https://github.com/dineshsonachalam/Lucid-Dynamodb#4-read-an-item

from LucidDynamodb.Operations import DynamoDb
import os
import logging
logging.basicConfig(level=logging.INFO)

AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")

if __name__ == "__main__":
    db = DynamoDb(region_name="us-east-1", 
                aws_access_key_id=AWS_ACCESS_KEY_ID, 
                aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
    item = db.read_item(
        TableName="test", 
        Key={
            'topic': "1"
        })
    if(item != None):
        logging.info("Item: {}".format(item))
    else:
        logging.warning("Item doesn't exist")
Dinesh Sonachalam
  • 1,223
  • 19
  • 33
0

Assuming you only have partition key (aka hash key) in the table.

import boto3
dynamodb = boto3.resource('dynamodb',region_name='ap-southeast-2')
table = dynamodb.Table('my-table')
key = {}
key['key'] = 'my-key'
print(key)
response = table.get_item(Key=key)
print(response['Item'])
kartik
  • 2,097
  • 3
  • 21
  • 31
0

If you have sort key as well then:

dynamodb = boto3.client('dynamodb', region_name=AWS_REGION, aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCCESS_KEY)
        
response = dynamodb.get_item(
     TableName=str(os.environ['DYNAMODB_TABLE']), 
     Key={'task_id' : {
           'S' : str(task_id)
           },
          'mac' : {
           'S' : 'AA-00-04-00-XX-YX'
           }
         }
 )
Dhiraj
  • 106
  • 6
-2
# Have the IAM role containing policy *AmazonDynamoDBFullAccess* assigned to your lambda function

import boto3

def lambda_handler(event, context):

    try:
        dynamodb_client = boto3.client('dynamodb')
        response = dynamodb_client.get_item(
                    TableName="Garbage_collector_table",
                    Key={
                         'topic':
                                {'S':str(my_topic)}
                        }
                    )
    except Exception as error:
        print(error)
        raise
    else:
        print(f'Response = {response}')
        return response
  • 1
    While this code snippet may solve the question, [including an explanation](//meta.stackoverflow.com/q/392712/4733879) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Filnor Jul 17 '20 at 06:52