boto3.client('dynamodb') and `Table.meta.client` are not the same
Describe the issue
This is functionally just trying to reopen the conversation here from a few years ago, since it was closed without conclusion. Please just update the docs!
Short version: documentation of the meta.client and the boto3 stubs would lead a developer to expect that the behavior of the DynamoDB.Client from both boto3.client('dynamodb') and boto3.resource('dynamodb').Table('some-table').meta.client would be the same, but they're not. The latter gracefully handles all the fussing with Dynamodb Types like {'S': 'my-string'}, so you can feed all the client methods more simple types like, 'my-string' but the low-level client obviously does not.
The original ticket suggests that this behavior is a bug, but it can obviously never change without a new major version of boto3, since I'm sure many many applications now depend on that behavior. It's actually super handy to have this seamless translation happen for all of the basic DynamoDB.Client methods, though, so why not acknowledge the feature! I'd just like to see the boto3 documentation updated to explicitly describe this behavior so I can use it without it feeling like a dangerous undocumented feature.
Links
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html#creating-clients https://boto3.amazonaws.com/v1/documentation/api/latest/guide/dynamodb.html
Hello @jusdino, thank you for reaching out. I have tried having query clientand query resource and found that indeed we cannot use the same parameter from client to resource.
Looking at the client doc, it mentions:
You would first need to specify ExpressionAttributeValues as follows:
{ ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} }
Then on the resource, it also mentioned:
You would first need to specify ExpressionAttributeValues as follows:
{ ":avail":{"S":"Available"}, ":back":{"S":"Backordered"}, ":disc":{"S":"Discontinued"} }
When in fact the resource is incorrect. And repro'ing the issue:
Using client:
import boto3
boto3.set_stream_logger('')
client = boto3.client('dynamodb')
params = {
"TableName": "name_of_table",
"KeyConditionExpression": "user_id = :user_id",
"ExpressionAttributeValues": {
":user_id": {"S": "username"}
}
}
response = client.query(**params)
Response from Service:
https://dynamodb.us-east-1.amazonaws.com:443 "POST / HTTP/1.1" 200 39
Then using the same params for resources:
resource = boto3.resource("dynamodb")
params = {
"TableName": "name_of_table",
"KeyConditionExpression": "user_id = :user_id",
"ExpressionAttributeValues": {
":user_id": {"S": "username"}
}
}
response = resource.meta.client.query(**params)
print(response)
Response from Service:
https://dynamodb.us-east-1.amazonaws.com:443 "POST / HTTP/1.1" 400 165
botocore.parsers [DEBUG] Response body:
b'{"__type":"com.amazon.coral.validate#ValidationException","message":"One or more parameter values were invalid: Condition parameter type does not match schema type"}'
Then for fix and as per documentation, I used: ":user_id": "username" and it worked,
The documentation is managed by the DynamoDB service team. That being said, I have reached out to the service team in this regard. I will update as soon as I get any updates from the team. If there are more discrepancy on documentation in regards to client vs. resources and other doc issues based on the API methods you have used apart from my test, please let us know. Thank you.
Internal Ref: P327240276