如何在给定主分区键值列表的情况下一次 batch_get_item 多个项目
How to batch_get_item many items at once given a list of primary partition key values
所以,所以我有一个 dynamodb table,它有一个主分区键列,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)。每个项目单独处理。它与查询中的SQL不相似。
'Keys': [
{
'foo_id': key1
},
{
'foo_id': key2
}
],
示例代码:-
您可能需要更改 table 名称和键值。
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))
批准的答案不再有效。
对我来说,工作调用格式是这样的:
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}
。
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)
这是使用 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);
});
});
}
所以,所以我有一个 dynamodb table,它有一个主分区键列,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)。每个项目单独处理。它与查询中的SQL不相似。
'Keys': [
{
'foo_id': key1
},
{
'foo_id': key2
}
],
示例代码:-
您可能需要更改 table 名称和键值。
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))
批准的答案不再有效。
对我来说,工作调用格式是这样的:
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}
。
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)
这是使用 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);
});
});
}