3

我是 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();
});

我假设 Expected 值会通过引发 ConditionalCheckFailedException 错误来防止用户表中出现重复的电子邮件地址。不是这种情况; 上面的代码将一致地插入重复的电子邮件。我尝试将“id”添加为额外的预期字段,但这并没有改变行为。

当我修改代码时,我确实得到了 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 的查找/索引表。这让我可以很容易地让用户更改他或她的电子邮件地址(我什至可以支持多个电子邮件地址)。

谢谢您的帮助!

4

1 回答 1

3

具有范围键的 DynamoDB 表中的项目是哈希键和范围键的组合,在 mysql 中是唯一的(id,电子邮件)。因此,在您的第一种方法中,当您插入一个电子邮件已经存在于表中的用户时,您正在创建一个全新的项目,因为 uuid 完全不同:

第一项 -> 哈希键:7f224b97-c144-4df2-bc3e-cfba69d5bc6e,范围键:my@email.com

第二项 -> 哈希键:34cc6d26-dce4-4eb4-afec-3a382d9579fc,范围键:my@email.com

因此,预期条件确实有效,但表中哈希键为 7f224b97-c144-4df2-bc3e-cfba69d5bc6e 的其他项目没有 Range 键 = my@email.com,并且放置项目成功。

如果真的要保证用户邮件的唯一性,应该把它作为表的Hash key。当您想要查询用户时,它也会让您更轻松:您可能知道,要在 DynamoDB 中执行查询,您必须指定要查询的哈希键的确切值,如果您不知道该值对于您要查找的哈希键,您将不得不执行表扫描(效率低得多)。

因此,如果您使用 uuid 作为哈希键,则必须使用表扫描检索用户(我假设您不知道与要从 DB 检索的用户关联的 uuid)。如果您使用用户邮件作为哈希键,您将能够使用查询来检索它们。

希望能帮助到你!

于 2013-11-08T11:18:33.160 回答