具有多种条件的 Dynamo putItem 在 localstack 中不起作用
Dynamo putItem with multiple conditions not working in localstack
我第一次直接使用 Dynamo,在本地的玩具项目中。我正在尝试创建一个由条件表达式保护的记录 - 如果用户名(范围键)或 uniqueId(哈希键)已经存在,则失败:"attribute_not_exists(UserId) and attribute_not_exists(Username)"
。但是,当我放置具有相同用户名的记录时,我没有遇到冲突 - table 的扫描证实了这一点。我正在使用 localstack(本地 AWS 模拟),如果这有所不同的话。
问题:
- 我应该改用事务还是其他一些抽象?
- 我在 table 设置中是否构建了错误的密钥(参见 q 的底部)?
- 我需要在条件中指定键的类型吗?
创建记录的逻辑如下:
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())
}
这是本地堆栈中的 Dynamo table:
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 | }
在 DynamoDB 中,hash key
+ range key
构成主键。或者,只有 hash key
,如果我们没有为我们的 table 定义 range key
。
所以,你想要的不能在范围键上完成,因为它不是唯一的。
这里要注意的是 - attribute_not_exists
不会为您扫描 table,而是检查您正在使用的 record/item(来自散列键和 ddb 查询中的范围键)。
您对 attribute_not_exists
条件表达式的作用有误解。
这并不意味着该属性在 任何 项上不存在于 table,而是该属性在您的项上不存在正在与.
因此,操作按设计进行。
如果您想确保没有两个项目被添加到 table 具有相同的用户名或用户 ID,您将不得不使用这两个属性作为 [=21] 的主键=],或想出一种检查重复项的替代方法。
我第一次直接使用 Dynamo,在本地的玩具项目中。我正在尝试创建一个由条件表达式保护的记录 - 如果用户名(范围键)或 uniqueId(哈希键)已经存在,则失败:"attribute_not_exists(UserId) and attribute_not_exists(Username)"
。但是,当我放置具有相同用户名的记录时,我没有遇到冲突 - table 的扫描证实了这一点。我正在使用 localstack(本地 AWS 模拟),如果这有所不同的话。
问题:
- 我应该改用事务还是其他一些抽象?
- 我在 table 设置中是否构建了错误的密钥(参见 q 的底部)?
- 我需要在条件中指定键的类型吗?
创建记录的逻辑如下:
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())
}
这是本地堆栈中的 Dynamo table:
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 | }
在 DynamoDB 中,hash key
+ range key
构成主键。或者,只有 hash key
,如果我们没有为我们的 table 定义 range key
。
所以,你想要的不能在范围键上完成,因为它不是唯一的。
这里要注意的是 - attribute_not_exists
不会为您扫描 table,而是检查您正在使用的 record/item(来自散列键和 ddb 查询中的范围键)。
您对 attribute_not_exists
条件表达式的作用有误解。
这并不意味着该属性在 任何 项上不存在于 table,而是该属性在您的项上不存在正在与.
因此,操作按设计进行。
如果您想确保没有两个项目被添加到 table 具有相同的用户名或用户 ID,您将不得不使用这两个属性作为 [=21] 的主键=],或想出一种检查重复项的替代方法。