dynamodb中的预期约束以防止重复

时间:2013-11-06 07:53:24

标签: node.js amazon-web-services amazon-dynamodb

我是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的查找/索引表。这使我可以让用户很容易地更改他或她的电子邮件地址(我甚至可以支持多个电子邮件地址)。

感谢您的帮助!

1 个答案:

答案 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)。如果您使用用户邮件作为哈希密钥,您将能够使用查询检索它们。

希望它有所帮助!