首页 > 解决方案 > 具有多个条件的 Dynamo putItem 在 localstack 中不起作用

问题描述

我第一次在本地的玩具项目中直接使用 Dynamo。我正在尝试创建由条件表达式保护的记录-如果用户名(范围键)或 uniqueId(哈希键)已经存在,则失败:"attribute_not_exists(UserId) and attribute_not_exists(Username)"。但是,当我使用相同的用户名放置记录时,我没有遇到冲突——并且对表的扫描证实了这一点。我正在使用 localstack(本地 AWS 模拟),如果这有所作为。

问题:

以下是创建记录的逻辑:

userID := GenerateUniqueID()
record := UserCredentialsRecord{
    UserID:           userID,
    Username:         username,
    Password:         base64.StdEncoding.EncodeToString(hashedPassword),
    Salt:             base64.StdEncoding.EncodeToString(salt),
    Email:            email,
    AccountCreatedTS: time.Now().Unix(),
}
...

input := &dynamodb.PutItemInput{
    Item:                av,
    TableName:           aws.String(userCredentialsTableName),
    ConditionExpression: aws.String("attribute_not_exists(UserId) and attribute_not_exists(Username)"),
}
...

_, err = session.PutItem(input)
if err != nil {
    fmt.Println("Got error calling PutItem:", err.Error())
}

这是 localstack 中的 Dynamo 表:

localstack         | ++ aws --endpoint-url=http://localstack:4566 dynamodb create-table --table-name UserCredentials --attribute-definitions AttributeName=UserID,AttributeType=S AttributeName=Username,AttributeType=S --key-schema AttributeName=UserID,KeyType=HASH AttributeName=Username,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
localstack         | {
localstack         |     "TableDescription": {
localstack         |         "AttributeDefinitions": [
localstack         |             {
localstack         |                 "AttributeName": "UserID",
localstack         |                 "AttributeType": "S"
localstack         |             },
localstack         |             {
localstack         |                 "AttributeName": "Username",
localstack         |                 "AttributeType": "S"
localstack         |             }
localstack         |         ],
localstack         |         "TableName": "UserCredentials",
localstack         |         "KeySchema": [
localstack         |             {
localstack         |                 "AttributeName": "UserID",
localstack         |                 "KeyType": "HASH"
localstack         |             },
localstack         |             {
localstack         |                 "AttributeName": "Username",
localstack         |                 "KeyType": "RANGE"
localstack         |             }
localstack         |         ],
localstack         |         "TableStatus": "ACTIVE",
localstack         |         "CreationDateTime": 1610668286.312,
localstack         |         "ProvisionedThroughput": {
localstack         |             "LastIncreaseDateTime": 0.0,
localstack         |             "LastDecreaseDateTime": 0.0,
localstack         |             "NumberOfDecreasesToday": 0,
localstack         |             "ReadCapacityUnits": 1,
localstack         |             "WriteCapacityUnits": 1
localstack         |         },
localstack         |         "TableSizeBytes": 0,
localstack         |         "ItemCount": 0,
localstack         |         "TableArn": "arn:aws:dynamodb:us-east-1:000000000000:table/UserCredentials"
localstack         |     }
localstack         | }

标签: goamazon-dynamodblocalstack

解决方案


attribute_not_exists您对条件表达式的作用有误解。

这并不意味着该属性在表中的任何项目上都不存在,而是该属性在您正在使用的项目上不存在。

因此,操作按设计进行。

如果要确保没有两个具有相同用户名或用户 ID 的项目添加到表中,则必须使用这两个属性作为表的主键,或者想出另一种方法来检查重复。


推荐阅读