15

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
  • 9,571
  • 15
  • 75
  • 124
Narendra M
  • 163
  • 1
  • 1
  • 6

7 Answers7

31

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

The correct syntax for a resource is:

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

but personally I recommend to use boto client:

client = boto3.client('dynamodb')

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

http://boto3.readthedocs.io/en/latest/reference/services/dynamodb.html

MarcosBernal
  • 472
  • 4
  • 11
Eyal Ch
  • 8,734
  • 5
  • 40
  • 52
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
  • 563
  • 8
  • 13
  • 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

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,029
  • 3
  • 20
  • 29
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,138
  • 4
  • 52
  • 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
  • 971
  • 15
  • 30
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
  • 96
  • 5
-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