DynamoDB BatchWrite不同Hash Key同Range Key为何报重复键错误?
问题原因与解决办法
问题根源
你遇到的报错是因为复用了同一个mainItem map对象。Go语言中的map是引用类型,循环里你只修改了address字段,然后将这个map传入PutRequest.Item,但所有PutRequest保存的都是这个map的引用。当循环结束时,所有Item的address都会被覆盖成最后一次循环的storeKey对应值,导致所有请求的主键变成完全相同的(最后一个address, tx_id),DynamoDB因此检测到重复主键并抛出ValidationException。
解决办法
每次循环都创建独立的Item对象,避免引用复用:
方案1:循环内新建Item(推荐)
如果你的Item除了address还有其他固定字段(比如tx_id),可以在循环内初始化完整的Item:
for _, storeKey := range t.StoreKeys() { // 每次循环新建独立的Item map mainItem := make(map[string]types.AttributeValue) // 先赋值固定字段(比如tx_id) mainItem["tx_id"], err = dynamodbattribute.Marshal(yourTxIdValue) if err != nil { return err } // 赋值当前循环的address mainItem["address"], err = dynamodbattribute.Marshal(storeKey) if err != nil { return err } mainTxPut := dynamodb.PutRequest{ Item: mainItem, } writeRequests = append(writeRequests, &dynamodb.WriteRequest{ PutRequest: &mainTxPut, }) }
方案2:复制已有Item(适用于原Item有大量固定字段的场景)
如果原mainItem已经包含大部分固定字段,可以在循环内复制一份新的map再修改address:
for _, storeKey := range t.StoreKeys() { // 复制原mainItem到新的map,避免引用复用 newItem := make(map[string]types.AttributeValue) for k, v := range mainItem { newItem[k] = v } // 修改当前循环的address newItem["address"], err = dynamodbattribute.Marshal(storeKey) if err != nil { return err } mainTxPut := dynamodb.PutRequest{ Item: newItem, } writeRequests = append(writeRequests, &dynamodb.WriteRequest{ PutRequest: &mainTxPut, }) }
这样每个PutRequest的Item都是独立的对象,主键会被正确设置为(当前address, tx_id),不会出现重复的情况。
内容的提问来源于stack exchange,提问作者Ben2077
相关产品推荐
相关产品推荐

