dynamodb中的预期约束以防止重复 [英] Expected constraint in dynamodb to prevent duplicates

查看:276
本文介绍了dynamodb中的预期约束以防止重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是DynamoDB的新手,我无法在node.js和DynamoDB中使用以下方案:



我想在用户中插入用户表,但是如果用户的电子邮件地址已经存在,我不希望此操作成功。



以下代码能够成功插入新用户:

  var项目= {
id:{S:uuid.v4()},
电子邮件:{S:'my @ email.com'}
};

dynamodb.putItem({
TableName:'user',
Item:item,
预期:{
电子邮件:{存在:false}
}
},函数(错误,数据){
if(err){
return callback(err);
}
callback();
});

我认为Expected值会引发ConditionalCheckFailedException错误,从而防止用户表中的电子邮件地址重复。不是这种情况;上面的代码将一致地插入重复的电子邮件。我尝试将 id添加为附加的Expected字段,但这并没有改变行为。



当我修改代码时,确实得到了ConditionalCheckFailedException,因此ID为固定而不是生成的UUID;

  var item = {
id:{S:'Test'},
电子邮件:{S:'my@email.com'}
};

我应该解释一下, id是哈希键, email是范围键。



这种行为使我相信约束仅适用于使用哈希键指定的记录。如果是这样的话,AWS文档的确会非常混乱(我以粗体突出显示了使我感到困惑的地方):


如果Exists存在, Amazon DynamoDB假定表中不存在属性值。如果实际上该值不存在,则该假设有效,并且操作成功。如果找到该值,则尽管假设该值不存在,但该操作将失败,并显示ConditionalCheckFailedException。


假设文档正确我一定做错了什么?任何帮助将不胜感激!



编辑2013-11-09



根据下面的评论,我决定更改策略。我有点不愿意在其他大多数不变的域对象中使用需要引用的值。我现在有一个电子邮件地址表,可以用作用户ID的查找/索引表。这使我可以让用户非常轻松地更改其电子邮件地址(我什至可以支持多个电子邮件地址)。



感谢帮助!

解决方案

DynamoDB中的项目带有范围键的表是哈希键和范围键的组合,在mysql中是唯一的(id,email)。因此,在第一种方法中,当您插入表中已经存在电子邮件的用户时,您将创建一个全新的项目,因为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,并且放置项成功。



如果您确实要保证用户电子邮件的唯一性,则应将其作为表的哈希键。当您要查询用户时,这也将使您更轻松:如您所知,要在DynamoDB中执行查询,您必须指定要查询的哈希键的确切值(如果您不知道该值)

因此,如果您使用uuid作为哈希键,则必须执行表扫描(效率要低得多)。将必须使用表扫描来检索您的用户(我假设您不知道与要从数据库检索的用户关联的uuid)。如果您使用用户邮件作为哈希键,则可以使用查询来检索它们。



希望它会有所帮助!


I am new to DynamoDB and I am having trouble getting the following scenario to work in node.js and DynamoDB:

I want to insert a user in a user table but I don't want this to succeed if the user's email address already exists.

The following code is able to successfully insert a new user:

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

I assumed the Expected value would prevent duplicate email addresses in the user's table by raising an ConditionalCheckFailedException error. This is not the case; the code above will insert duplicate emails consistently. I tried adding the 'id' as an additional Expected field but this didn't change the behavior.

I do get a ConditionalCheckFailedException when I modify the code so the ID is fixed rather than a generated UUID;

var item = {
    id: { S: 'Test' },
    email: { S: 'my@email.com' }
};

I should explain, the 'id' is the hash key and 'email' is the range key.

This behavior led me to believe the constraints only work on the record specified with the hash key. If that were the case the AWS documentation would be very confusing indeed (I highlighted in bold what confuses me):

If Exists is false, Amazon DynamoDB assumes that the attribute value does not exist in the table. If in fact the value does not exist, then the assumption is valid and the operation succeeds. If the value is found, despite the assumption that it does not exist, the operation fails with a ConditionalCheckFailedException.

Assuming the documentation is correct I must be doing something wrong? Any help would be much appreciated!

EDIT 2013-11-09

Based on the comment below I decided to change tactics. I'm a bit reluctant to use a value that I need to reference in most other domain objects that isn't immutable. I now have an email address table that acts as a lookup / index table for user ID's. This allows me to have the user change his or her email address quite easily (I could even support multiple email addresses).

Thanks for the help!

解决方案

The items in a DynamoDB table with range key are the combination of hash key and range key, sort of a unique(id, email) in mysql. So in your first approach, when you insert a user who's email already exists in the table, you are creating a whole new item because the uuid is completely different:

1st item -> Hash key: 7f224b97-c144-4df2-bc3e-cfba69d5bc6e, Range key: my@email.com

2nd item -> Hash key: 34cc6d26-dce4-4eb4-afec-3a382d9579fc, Range key: my@email.com

So the Expected condition is working indeed, but no other item in the table with the Hash key 7f224b97-c144-4df2-bc3e-cfba69d5bc6e has a Range key = my@email.com, and the put item succeeds.

If you really want to guarantee the uniqueness of the user's email, you should put it as the Hash key of the table. It will also make things easier to you when you want to query a user: as you probably know, to perform a query in DynamoDB you have to specify the exact value of the hash key you want to query, if you do not know the value of the hash key you are looking for, you will have to perform a table scan (much more inefficient).

So if you use an uuid as a Hash key, you will have to retrieve your users using a table scan (I assume that you don't know the uuid associated to a user you want to retrieve from DB). If you use the user mail as the Hash key, you will be able to retrieve them using queries.

Hope it helps!

这篇关于dynamodb中的预期约束以防止重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆