如果值不存在,dynamodb 是否支持 SET 操作上的原子计数器?

发布于 2025-01-14 23:44:52 字数 1152 浏览 1 评论 0 原文

我有一个用例,需要在 DynamoDB 中存储查看博客文章的人数。

假设我有一个像下面这样的表

blogId Total Views。
1 100

现在,当用户查看 ID 为 2 的新博客时,我必须将其存储在表中。我可以执行以下操作来实现此目的:

isBlogExists = dynamodbMapper.get(BlogViews,{blogId: 2})
if (isBlogExists){
   dynamodbMapper.set("totalViews", new MathematicalExpression("totalViews", "+", 1))
} else{
   dynamodbMapper.set("totalViews", 1)
}

不幸的是,它最终会出现竞争条件,因此我计划使用这样的 SET 操作

dynamodbMapper.set("totalViews", new MathematicalExpression("totalViews", "+", 1))

由于该项目没有totalViews属性,因此我收到了类似的错误

在表中找不到带有密钥的项目。

那么 DynamoDB 是否不支持在不存在的键上递增数值?

我可以使用 ADD 操作,但 DynamoDB 建议使用 SET 而不是 ADD (来源)。

I have a use case where I need to store how many people view the blog post in DynamoDB.

Lets' say I have a table like below

blogId Total Views.
1 100

Now when a user views a new blog with ID 2 I have to store that in the table. I can do the following to achieve that:

isBlogExists = dynamodbMapper.get(BlogViews,{blogId: 2})
if (isBlogExists){
   dynamodbMapper.set("totalViews", new MathematicalExpression("totalViews", "+", 1))
} else{
   dynamodbMapper.set("totalViews", 1)
}

Unfortunately it ends up in race condition so I planned to use the SET operation like this

dynamodbMapper.set("totalViews", new MathematicalExpression("totalViews", "+", 1))

Since this item doesn't have the totalViews attribute, I am getting a error like

No item with the key found in Table.

So does DynamoDB doesn't support incrementing numeric values on key which doesn't exist?

I could use the ADD operation but DynamoDB recommends to use SET over ADD (source).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

溺ぐ爱和你が 2025-01-21 23:44:52

DynamoDB 提供了在 UpdateExpression 中使用 ADD 的简单方法,但 AWS 通常建议改为使用SET

注意

一般来说,我们建议使用 SET 而不是 ADD。

我不明白为什么,他们也没有详细说明。如果您想遵循他们的指导,您可以执行以下操作。

在某些情况下,简单的 SET attr = attr + 1 是不够的,因为它要求属性已经存在。如果不是这种情况,ADD 表达式会假定默认值为 0,而 SET 则不会。

幸运的是,我们可以使用 if_not_exists 功能。这是如何使用它的示例。它假设一个名为 pk-only 的表,只有一个名为 PK 的字符串类型分区键。

import boto3

TABLE_NAME = "pk-only"
TABLE_RESOURCE = boto3.resource("dynamodb").Table(TABLE_NAME)

def main():
    
    TABLE_RESOURCE.update_item(
        Key={"PK": "some_item"},
        UpdateExpression="SET #att = if_not_exists(#att, :start_value) + :inc",
        ExpressionAttributeNames={
            "#att": "counter"
        },
        ExpressionAttributeValues={
            ":inc": 1,
            ":start_value": 0
        }
    )

if __name__ == "__main__":
    main()

(这是 Python 中的示例,但您应该能够轻松地将其适应您的 Javascript 代码)

DynamoDB offers the straightforward way of using ADD in the UpdateExpression, but AWS generally recommends going with SET instead:

Note

In general, we recommend using SET rather than ADD.

I don't see why and they don't elaborate on that. If you want to follow their guidance, here is what you can do.

The straightforward SET attr = attr + 1 falls short in some cases because it requires the attribute to exist already. The ADD expression assumes a default of 0 if that's not the case, SET doesn't.

Fortunately, we can create a default for non-existent attributes using the if_not_exists function. Here's an example of how to use it. It assumes a table called pk-only with only a partition key called PK of type string.

import boto3

TABLE_NAME = "pk-only"
TABLE_RESOURCE = boto3.resource("dynamodb").Table(TABLE_NAME)

def main():
    
    TABLE_RESOURCE.update_item(
        Key={"PK": "some_item"},
        UpdateExpression="SET #att = if_not_exists(#att, :start_value) + :inc",
        ExpressionAttributeNames={
            "#att": "counter"
        },
        ExpressionAttributeValues={
            ":inc": 1,
            ":start_value": 0
        }
    )

if __name__ == "__main__":
    main()

(This is an example in Python, but you should be able to adapt it to your Javascript code quite easily)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文