首页 > 解决方案 > 在将数据添加到 DynamoDB 之前检查数据是否有效的最佳方法是什么

问题描述

据我了解,Dynamo 中没有外键约束。

我们有用户、组。

由于用户和组彼此紧密相连,因此在此特定用例中它们被存储在同一个表中。但一般来说,它可以归因于同一张表或不同的表。

外汇:

将用户添加到具有给定 groupId 的组的请求。

将站点添加到组的请求。

检查我们将添加给用户的给定 groupId 是否确实存在的最佳和优化方法是什么。对于需要添加到给定组的具有给定 siteId 的站点也是如此。

在将数据插入数据库之前,我们是否会为每个此类字段发送一个 checkIfExists dynamoDB 查询?这听起来未经优化且丑陋。如何以更好的方式解决这个问题?

标签: amazon-web-servicesamazon-dynamodbserverlessdynamodb-queries

解决方案


您可以使用事务来执行此操作,这是 Python 中的示例:

import boto3
import botocore.exceptions

TABLE_NAME = "transaction"

def create_table():
    ddb = boto3.client("dynamodb")
    ddb.create_table(
        AttributeDefinitions=[
            {"AttributeName": "PK", "AttributeType": "S"},
            {"AttributeName": "SK", "AttributeType": "S"},
        ],
        TableName=TABLE_NAME,
        KeySchema=[{"AttributeName": "PK", "KeyType": "HASH"}, \
                  {"AttributeName": "SK", "KeyType": "RANGE"}],
        BillingMode="PAY_PER_REQUEST",
    )


def add_group(group_name: str):
    item = {
        "PK": f"G#{group_name}",
        "SK": "META",
        "groupName": group_name
    }
    boto3.resource("dynamodb").Table(TABLE_NAME).put_item(Item=item)

def add_user_to_group(user_name: str, group_name: str):

    print(f"Attempting to add user {user_name} to group {group_name}")
    
    membership_item = {
        "PK": {"S": f"G#{group_name}"},
        "SK": {"S": f"U#{user_name}"}
    }

    client = boto3.client("dynamodb")
    try:
        client.transact_write_items(
            TransactItems=[
                {
                    "ConditionCheck": {
                        "TableName": TABLE_NAME,
                        # Check if an item with this key exists
                        "Key": {
                            "PK": {"S": f"G#{group_name}"},
                            "SK": {"S": "META"}
                        },
                        "ConditionExpression": "attribute_exists(PK)"
                    }
                },
                {
                    "Put": {
                        "Item": membership_item,
                        "TableName": TABLE_NAME
                    }
                }
            ]
        )
    except botocore.exceptions.ClientError:
        return f"Group {group_name} doesn't exist!"

    return f"Added user {user_name} to group {group_name}"

if __name__ == "__main__":
    create_table()
    add_group("dummy")
    print(add_user_to_group("test", "dummy"))
    print(add_user_to_group("test", "does_not_exist"))

基本上,您创建一个包含两个项目的事务:

  1. ConditionCheck 测试组是否存在
  2. 放置/更新以创建您的会员资格

如果您运行代码,它将创建一个表,添加一个组,然后尝试将用户添加到该组。那行得通,然后它将用户添加到另一个不存在的组中,但失败了。

输出:

Attempting to add user test to group dummy
Added user test to group dummy
Attempting to add user test to group does_not_exist
Group does_not_exist doesn't exist!

推荐阅读