[英]Boto3 - Can I get items with batch_get_item whose sort key begins with a variable?
[英]How to batch_get_item many items at once given a list of primary partition key values
所以,我有一個 dynamodb 表,其中包含一個主分區鍵列foo_id
並且沒有主排序鍵。 我有一個foo_id
值列表,並希望獲得與此 id 列表關聯的觀察結果。
我認為最好的方法(?)是使用batch_get_item()
,但它對我不起作用。
# python code
import boto3
client = boto3.client('dynamodb')
# ppk_values = list of `foo_id` values (strings) (< 100 in this example)
x = client.batch_get_item(
RequestItems={
'my_table_name':
{'Keys': [{'foo_id': {'SS': [id for id in ppk_values]}}]}
})
我使用SS
是因為我正在傳遞一個字符串列表( foo_id
值列表),但我得到:
ClientError: An error occurred (ValidationException) when calling the
BatchGetItem operation: The provided key element does not match the
schema
所以我認為這意味着它認為foo_id
包含列表值而不是字符串值,這是錯誤的。
--> 這樣解釋對嗎? 批量查詢一堆主分區鍵值的最佳方法是什么?
應按如下所述給出密鑰。 它不能被稱為“SS”。
基本上,您可以將 DynamoDB 字符串數據類型與字符串(即不與 SS)進行比較。 每個項目都單獨處理。 它與 query 中的 SQL 不同。
'Keys': [
{
'foo_id': key1
},
{
'foo_id': key2
}
],
示例代碼:-
您可能需要更改表名和鍵值。
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
from boto3.dynamodb.conditions import Key, Attr
from botocore.exceptions import ClientError
# Helper class to convert a DynamoDB item to JSON.
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)
dynamodb = boto3.resource("dynamodb", region_name='us-west-2', endpoint_url="http://localhost:8000")
email1 = "abc@gmail.com"
email2 = "bcd@gmail.com"
try:
response = dynamodb.batch_get_item(
RequestItems={
'users': {
'Keys': [
{
'email': email1
},
{
'email': email2
},
],
'ConsistentRead': True
}
},
ReturnConsumedCapacity='TOTAL'
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
item = response['Responses']
print("BatchGetItem succeeded:")
print(json.dumps(item, indent=4, cls=DecimalEncoder))
Boto3 現在有一個batch_get_item
版本,它允許您以更自然的 Pythonic 方式傳遞鍵,而無需指定類型。
您可以在https://github.com/awsdocs/aws-doc-sdk-examples 中找到完整且有效的代碼示例。 該示例處理有關重試的一些其他細微差別,但這里是回答此問題的代碼部分的摘要:
import logging
import boto3
dynamodb = boto3.resource('dynamodb')
logger = logging.getLogger(__name__)
movie_table = dynamodb.Table('Movies')
actor_table = dyanmodb.Table('Actors')
batch_keys = {
movie_table.name: {
'Keys': [{'year': movie[0], 'title': movie[1]} for movie in movie_list]
},
actor_table.name: {
'Keys': [{'name': actor} for actor in actor_list]
}
}
response = dynamodb.batch_get_item(RequestItems=batch_keys)
for response_table, response_items in response.items():
logger.info("Got %s items from %s.", len(response_items), response_table)
批准的答案不再有效。
對我來說,工作呼叫格式是這樣的:
import boto3
client = boto3.client('dynamodb')
# ppk_values = list of `foo_id` values (strings) (< 100 in this example)
x = client.batch_get_item(
RequestItems={
'my_table_name': {
'Keys': [{'foo_id': {'S': id}} for id in ppk_values]
}
}
)
被要求類型的信息。 對我來說,字符串鍵是“S”。 沒有它,我得到一個錯誤,說庫找到了一個str
但期望一個dict
。 也就是說,他們想要{'foo_id': {'S': id}}
而不是我首先嘗試的更簡單的{'foo_id': id}
。
這是 dynamodb 版本 2.15.0 的 java 解決方案。 假設 foo_id 是字符串類型並且鍵小於 100。您可以將列表分成所需大小的批次
private void queryTable(List<String> keys){
List<Map<String, AttributeValue>> keysBatch = keys.stream()
.map(key -> singletonMap("foo_id", AttributeValue.builder().s(key).build()))
.collect(toList());
KeysAndAttributes keysAndAttributes = KeysAndAttributes.builder()
.keys(keysBatch)
.build();
Map<String, KeysAndAttributes> requestItems = new HashMap<>();
requestItems.put("tableName", keysAndAttributes);
BatchGetItemRequest batchGet = BatchGetItemRequest.builder()
.requestItems(requestItems)
.build();
Map<String, List<Map<String, AttributeValue>>> responses = dbClient.batchGetItem(batchGet).responses();
responses.entrySet().stream().forEach(entry -> {
System.out.println("Table : " + entry.getKey());
entry.getValue().forEach(v -> {
System.out.println("value: "+v);
});
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.