在将链接项目放入 AWS DynamoDB 之前检查父项目是否存在

问题描述 投票:0回答:1

一个订单可以包含一种或多种产品。订单也属于客户。订单、产品和客户是我们在数据库中的项目模型。新订单创建接受如下请求。

{
    "customer_id": "c8fb0e64-43b0-45b1-a9e7-fe2ce61c2c1f",
    ...
    "products": [
        {
            "id": "7362ea92-2063-48ad-9bfe-c91a5d9af4a6",
            ...
        },
        {
            "id": "83e38b2f-2839-43c5-a834-0834d841e566",
            ...
        }
    ]
}

当我创建新订单时,我使用

TransactWriteItems
操作,到目前为止效果很好(见下图)。然而,目前我检查是否存在:

  1. 客户(
    c8fb0e64-43b0-45b1-a9e7-fe2ce61c2c1f
    )。
  2. 产品(
    7362ea92-2063-48ad-9bfe-c91a5d9af4a6
    83e38b2f-2839-43c5-a834-0834d841e566

将项目放入数据库时。

如图所示,客户(底部的一个)和产品项目(顶部的两个)已经在同一张表中。客户可通过

part_key
和/或
customer_id
属性来识别,而产品可通过
part_key
和/或
product_id
属性来识别。此外,表中的每个项目都有一个
_type
属性来表示它们是什么。

enter image description here

问题是,在使用事务将新项目插入数据库之前,我们通常如何管理存在性检查?我知道

attribute_exists
和条件检查,但不确定就性能和成本考虑而言正确的方法。

这是我的代码,如果有帮助的话,仅供参考。

func (d DynamoDB) CreateOrder(ctx context.Context, model database.Order) error {
    items := make([]types.TransactWriteItem, 0, len(model.Products)+1)

    for _, product := range model.Products {
        product.Key = database.Key{
            PartKey: "order#" + product.OrderID,
            SortKey: "product#" + product.ID,
        }
        product.Type = "order_product"

        item, err := attributevalue.MarshalMap(product)
        if err != nil {
            return err
        }

        items = append(items, types.TransactWriteItem{
            Put: &types.Put{
                TableName: aws.String(d.Table),
                Item:      item,
            },
        })
    }

    model.Key = database.Key{
        PartKey: "order#" + model.ID,
        SortKey: "order#" + model.ID,
    }
    model.Type = "order"

    item, err := attributevalue.MarshalMap(model)
    if err != nil {
        return err
    }

    items = append(items, types.TransactWriteItem{
        Put: &types.Put{
            TableName: aws.String(d.Table),
            Item:      item,
        },
    })

    _, err = d.Client.TransactWriteItems(ctx, &dynamodb.TransactWriteItemsInput{
        TransactItems: items,
    })
    if err != nil {
        return err
    }

    return nil
}
amazon-web-services go amazon-dynamodb
1个回答
0
投票

attribute_not_exists () 带有条件表达式来检查项目是否存在。添加条件表达式没有额外成本。但是,即使您的条件失败,您也将需要为写入操作(放置/交易)付费,就像成功写入时所产生的费用一样。这种条件检查失败在分布式系统中最有用,以避免竞争条件。

避免写入成本(如果写入成本变得成本密集)的另一种方法是简单地执行 get 请求来检查是否存在,因为读取成本会更低。 Dynamodb WCU-RCU

© www.soinside.com 2019 - 2024. All rights reserved.