我正在尝试使用DynamoDB操作
BatchWriteItem
,其中我想将多条记录插入到一个表中。
该表有 1 个分区键和 1 个排序键。
我正在使用 AWS lambda 和 Go 语言。
我将元素插入到切片中。
我正在遵循此程序。
创建
PutRequest
结构并为列表中的第一条记录添加 AttributeValues。
我正在由此创建
WriteRequest
PutRequest
我正在将此
WriteRequest
添加到 array of WriteRequests
我正在创建
BatchWriteItemInput
,它由 RequestItems
组成,它基本上是一个 Tablename 的映射和 WriteRequests
的数组。
之后我调用
BatchWriteItem
,这会导致错误:
Provided list of item keys contains duplicates.
任何指示,为什么会发生这种情况?
您提供了两个或多个具有相同主键的项目(在您的情况下意味着相同的分区和排序键)。
根据 BatchWriteItem 文档,您不能在同一 BatchWriteItem 请求中对同一项目执行多个操作。
注意事项:这个答案适用于Python
正如 @Benoit 所说,boto3 文档指出:
如果您想绕过单批写入请求的重复限制,如 botocore.exceptions.ClientError: 调用 BatchWriteItem 操作时发生错误 (ValidationException): 提供的项键列表包含重复项。
您可以根据
文档和源代码在批处理编写器上指定
overwrite_by_pkeys=['partition_key', 'sort_key']
“如果与指定主键上的新请求项匹配,则删除缓冲区中的重复请求项”。也就是说,如果缓冲区中已存在主排序组合,它将删除该请求并用新请求替换它。
假设您想要将 pandas 数据帧写入 DynamoDB 表,以下函数可能会有所帮助,
import json
import datetime as dt
import boto3
import pandas as pd
from typing import Optional
def write_dynamoDB(df:'pandas.core.frame.DataFrame', tbl:str, partition_key:Optional[str]=None, sort_key:Optional[str]=None):
'''
Function to write a pandas DataFrame to a DynamoDB Table through
batchWrite operation. In case there are any float values it handles
them by converting the data to a json format.
Arguments:
* df: pandas DataFrame to write to DynamoDB table.
* tbl: DynamoDB table name.
* partition_key (Optional): DynamoDB table partition key.
* sort_key (Optional): DynamoDB table sort key.
'''
# Initialize AWS Resource
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(tbl)
# Check if overwrite keys were provided
overwrite_keys = [partition_key, sort_key] if partition_key else None
# Check if they are floats (convert to decimals instead)
if any([True for v in df.dtypes.values if v=='float64']):
from decimal import Decimal
# Save decimals with JSON
df_json = json.loads(
json.dumps(df.to_dict(orient='records'),
default=date_converter,
allow_nan=True),
parse_float=Decimal
)
# Batch write
with table.batch_writer(overwrite_by_pkeys=overwrite_keys) as batch:
for element in df_json:
batch.put_item(
Item=element
)
else: # If there are no floats on data
# Batch writing
with table.batch_writer(overwrite_by_pkeys=overwrite_keys) as batch:
columns = df.columns
for row in df.itertuples():
batch.put_item(
Item={
col:row[idx+1] for idx,col in enumerate(columns)
}
)
def date_converter(obj):
if isinstance(obj, dt.datetime):
return obj.__str__()
elif isinstance(obj, dt.date):
return obj.isoformat()
致电
write_dynamoDB(dataframe, 'my_table', 'the_partition_key', 'the_sort_key')
。
使用
batch_writer
代替 batch_write_item
:
import boto3
dynamodb = boto3.resource("dynamodb", region_name='eu-west-1')
my_table = dynamodb.Table('mirrorfm_yt_tracks')
with my_table.batch_writer(overwrite_by_pkeys=["user_id", "game_id"]) as batch:
for item in items:
batch.put_item(
Item={
'user_id': item['user_id'],
'game_id': item['game_id'],
'score': item['score']
}
)
如果您没有排序键,
overwrite_by_pkeys
可以是None
这基本上与@MiguelTrejo 相同的答案(谢谢!+1),但经过简化