DynamoDB PutItem上似乎没有考虑条件表达式



这是我第一次使用DynamoDB,并为系统中的用户帐户创建了一个表。

表格定义如下:

{
"Table": {
"AttributeDefinitions": [
{
"AttributeName": "AccountId",
"AttributeType": "B"
},
{
"AttributeName": "Email",
"AttributeType": "S"
}
],
"KeySchema": [
{
"AttributeName": "AccountId",
"KeyType": "HASH"
}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "EmailAddress",
"KeySchema": [
{
"AttributeName": "Email",
"KeyType": "HASH"
}
],
"Projection": {
"ProjectionType": "ALL"
},
"IndexStatus": "ACTIVE"
}
]
}
}

为了简洁起见,省略了一些字段

我使用的是Rusoto DynamoDB客户端,这就是PutItem调用的样子:

dynamodb_client.put_item(PutItemInput{
item: account_doc.as_hashmap(),
table_name: accounts_datastore_name,
condition_expression: Some("attribute_not_exists(Email) and attribute_not_exists(AccountId)".to_string()),
..PutItemInput::default()
});

据我所知,这应该具有以下行为:如果有文档包含我在新文档中提供的值为EmailAccountId,则事务失败。

我已经能够多次提交同一份文档,而服务没有任何错误。文件都在表格里。

你知道为什么这个条件表达式允许文档通过吗?

您误解了条件的作用。它不查看表中的其他记录,只查看您正在put处理的记录。想象一下以下两条记录:

{
"AccountId": "<some_unique_id_1>",
"Email": "user@example.com"
}

{
"AccountId": "<some_unique_id_2>",
"Email": "user@example.com"
}

其中的每一个都将被保存,因为AccountId值不同,这意味着它在表中是不同的记录。

你的条件会阻止你第二次用相同的AccountId写唱片。因为AccountId是记录的关键,并且您要确保正在写入的记录没有设置AccountId,所以只有在第一次写入时才能写入该记录。在这种情况下,条件的Email部分实际上没有做任何事情。

对于你想要的东西,你可以考虑两种选择。

  1. 将密钥切换为电子邮件地址。这将确保电子邮件地址是唯一的
  2. 使用事务来写入您的记录。这并不像听起来那么简单。Alex DeBrie有一篇关于使用交易的非常好的文章

最新更新