如何使用ConditionExpression检查dynamodb中是否已存在非键属性?

时间:2016-02-23 07:51:01

标签: python amazon-web-services amazon-dynamodb boto3

我想仅在userId,email和username不存在时才插入users表(希望这些是唯一的)。
userId是主键(哈希键,数据类型 - 数字)。
用户名和电子邮件是非关键属性(两个字符串)。

以下是我的尝试:

response = userTable.put_item(
Item={
    'userId': userIdNext,
    'accType': 0,
    'username': usernameInput,
    'pwd': hashedPwd,
    'email': emailInput
},
ConditionExpression = "(attribute_not_exists(userIdNext)) AND (NOT (contains (email, :v_email))) AND (NOT (contains(username, :v_username)))",
ExpressionAttributeValues={
    ":v_email": emailInput,
    ":v_username": usernameInput
}
)

我尝试从这里跟踪逻辑运算符和条件表达式的aws文档:AWS Conditional Expressions

但即使用户名或电子邮件已经存在于数据库中,它也会每次都插入到表中。
(我给新的userIdNext,因为它是主键,不能重复)< / p>

我正在使用Python实现 boto3

2 个答案:

答案 0 :(得分:4)

dynamodb只能对哈希范围表键强制唯一性(而不是全局二级索引键)

在您的情况下有2个选项:

1)强制它在应用程序级别 - 查询记录,并查找是否重复

2)添加另一个带有散列/范围值的dynamodb表(可强制执行uniqeness),您可以在将项目放入主表之前查询此表

3)使用应用程序锁(memcache ..)

4)不要使用dynamodb(也许它不能满足你的要求)

在这里引用你的答案:

DynamoDB avoid duplicate non-key attributes

DynamoDB consistent reads for Global Secondary Index

答案 1 :(得分:1)

好的,我在申请中发现了这个错误。

我尝试向DynamoDB执行条件置位项,但是我传递了一个与DynamoDB上存在的主键不同的主键,此时将创建一个新对象并忽略条件表达式。

# id primary key
id = 123
# email is only index
email = "email@email.com"

item = {
  "id": id,
  "email": email
  "info": {
    "gender": "male",
    "country": "Portugal"
  }
}

response = self._table.put_item(Item=item, ConditionExpression="email <> :v_email", ExpressionAttributeValues={":v_email": email})

如果您希望条件表达式在DynamoDB put_item上正常工作,您应该发送与DB上存在的主键相同的主键。

  

kishorer747,你能把你的代码样本做到这一点吗? &#34;我有   全局二级索引,用于检查是否存在用户名或电子邮件   已经,但它不是原子的。因此,如果2个用户同时查询和   获取该email1可用,它们都插入到users表中。和   如果没有检查以验证电子邮件/用户名是否不存在   我们已经有重复的电子邮件/用户名条目&#34;