我是DynamoDB的新手,我无法在node.js和DynamoDB中使用以下方案:
我想在用户表中插入用户,但如果用户的电子邮件地址已经存在,我不希望这成功。
以下代码能够成功插入新用户:
var item = {
id: { S: uuid.v4()},
email: { S: 'my@email.com' }
};
dynamodb.putItem({
TableName: 'user',
Item: item,
Expected: {
email: { Exists: false }
}
}, function (err, data) {
if (err) {
return callback(err);
}
callback();
});
我认为预期值会通过引发ConditionalCheckFailedException错误来阻止用户表中的重复电子邮件地址。不是这种情况;上面的代码将一致地插入重复的电子邮件。我尝试将'id'添加为额外的Expected字段,但这并未改变行为。
我在修改代码时遇到ConditionalCheckFailedException,因此修复了ID而不是生成的UUID;
var item = {
id: { S: 'Test' },
email: { S: 'my@email.com' }
};
我应该解释一下,'id'是哈希键,'email'是范围键。
这种行为让我相信约束只适用于使用散列键指定的记录。如果是这种情况,那么AWS文档确实会非常令人困惑(我用粗体突出显示了让我困惑的事情):
如果Exists为false,则Amazon DynamoDB假定表中不存在属性值。如果实际上该值不存在,那么该假设是有效的并且操作成功。如果找到该值,尽管假设它不存在,操作将失败并出现ConditionalCheckFailedException。
假设文档正确我一定做错了吗?任何帮助将不胜感激!
编辑2013-11-09
根据下面的评论,我决定改变战术。我有点不愿意使用我需要在大多数其他不可变的域对象中引用的值。我现在有一个电子邮件地址表,充当用户ID的查找/索引表。这使我可以让用户很容易地更改他或她的电子邮件地址(我甚至可以支持多个电子邮件地址)。
感谢您的帮助!
答案 0 :(得分:2)
带有范围键的DynamoDB表中的项是散列键和范围键的组合,是mysql中唯一(id,email)的排序。因此,在您的第一种方法中,当您插入表中已存在电子邮件的用户时,您正在创建一个全新的项目,因为uuid完全不同:
第1项 - >哈希键:7f224b97-c144-4df2-bc3e-cfba69d5bc6e,范围键:my@email.com
第2项 - >哈希键:34cc6d26-dce4-4eb4-afec-3a382d9579fc,范围键:my@email.com
因此预期条件确实有效,但表中没有其他项目的哈希键7f224b97-c144-4df2-bc3e-cfba69d5bc6e有一个范围键= my@email.com,并且put项目成功。
如果您真的想保证用户电子邮件的唯一性,则应将其作为表格的哈希键。当您想要查询用户时,它也会使您更容易:您可能知道,要在DynamoDB中执行查询,您必须指定要查询的哈希键的确切值,如果您不知道该值您正在寻找的哈希键,您将不得不执行表扫描(效率更低)。
因此,如果您使用uuid作为哈希键,则必须使用表扫描检索您的用户(我假设您不知道与要从DB检索的用户关联的uuid)。如果您使用用户邮件作为哈希密钥,您将能够使用查询检索它们。
希望它有所帮助!