如何使用boto3有条件地将项目插入到dynamodb表中

ayc*_*dee 21 python amazon-dynamodb boto3

如果我有一个带有userId的散列键和productId的范围键的表,那么只有在使用boto3的dynamodb绑定不存在的情况下,如何才能将该项放入该表中?

对put_item的正常调用如下所示

table.put_item(Item={'userId': 1, 'productId': 2})
Run Code Online (Sandbox Code Playgroud)

我使用ConditionExpression的调用如下所示:

table.put_item(
    Item={'userId': 1, 'productId': 2}, 
    ConditionExpression='userId <> :uid AND productId <> :pid', 
    ExpressionAttributeValues={':uid': 1, ':pid': 3}
)
Run Code Online (Sandbox Code Playgroud)

但是每次都会引发ConditionalCheckFailedException.项目是否存在具有相同productId的项目.

jim*_*lly 55

遗憾的是,这方面的文件并不是很清楚.我需要完成类似的事情,这对我有用,使用boto3:

try:
    table.put_item(
        Item={
            'foo':1,
            'bar':2,
        },
        ConditionExpression='attribute_not_exists(foo) AND attribute_not_exists(bar)'
    )
except botocore.exceptions.ClientError as e:
    # Ignore the ConditionalCheckFailedException, bubble up
    # other exceptions.
    if e.response['Error']['Code'] != 'ConditionalCheckFailedException':
        raise
Run Code Online (Sandbox Code Playgroud)

与其他答案类似,关键在于attribute_not_exists函数,但最初我不清楚如何使其工作.经过一些实验,我能够顺利完成上述工作.

  • 如果从boto3.dynamodb.conditions import Attr中添加此导入`,则`ConditionExpression`可以是`ConditionExpression = Attr(“ foo”)。ne(1)和Attr(“ bar”)。ne(2)中的一个。 `或`ConditionExpression = Attr(“ foo”)。not_exists()和Attr(“ bar”)。not_exists()`我发现not_exists()的名称令人困惑。它看起来像是要检查记录中是否完全缺少该属性,但实际上它检查从“ Item”值推断出的相等性。“密钥,属性”的文档https://boto3.amazonaws.com/v1/documentation/api/latest/reference/customizations/dynamodb.html#ref-dynamodb-conditions (4认同)
  • “我发现 not_exists() 的名称令人困惑。” ——那是因为你不明白。它确实会检查属性是否存在,但可用于检查匹配的分区键。如何?想想当您使用 put_item 添加具有与现有记录匹配的分区键值的记录时的情况。DynamoDB 即将覆盖它(默认行为),但是如果它已经具有分区键(这是因为所有记录都必须具有分区键属性),则您的 Condition 表示不会。这是对平等来自的现有记录的覆盖 (2认同)

Ven*_*V.S 6

您只需要分区键或哈希键就不需要sortkey(或range键)。

try:
    table.put_item(
        Item={
            'foo':1,
            'bar':2,
        },
        ConditionExpression='attribute_not_exists(foo)'
    )
except botocore.exceptions.ClientError as e:
    # Ignore the ConditionalCheckFailedException, bubble up
    # other exceptions.
    if e.response['Error']['Code'] != 'ConditionalCheckFailedException':
        raise
Run Code Online (Sandbox Code Playgroud)

  • 这是不正确的。该表有一个复合键,它需要散列键和范围(排序)键来唯一标识一条记录。如果存在共享相同 hash_key 的其他记录,则 ConditionExpression 将失败,例如 `{ 'foo': 1, 'bar': 1}, { 'foo': 1, 'bar': 3}, { 'foo': 1, 'bar': 4}` 这不是 OP 想要的,它只会在 `{ 'foo': 1, 'bar': 3}` 存在时失败。它可能适用于其他用例,或者您的哈希键可能足以唯一标识记录,但如果是这种情况,那么您的范围键将无所作为,对一袋 1 进行排序是没有意义的。 (2认同)
  • 是的,没关系。甚至我一开始就很困惑。.嘿,只是出于好奇,为什么错误的答案会受到推崇,而正确的答案却没有得到这样的关注。为什么? (2认同)