Invalid UpdateExpression:两个文档路径相互重叠;必须删除或重写这些路径之一

Invalid UpdateExpression: Two document paths overlap with each other; must remove or rewrite one of these paths

我的 DynamoDB 请求中出现下一个错误:

{
   "__type":"com.amazon.coral.validate#ValidationException",
   "message":"Invalid UpdateExpression: 
        Two document paths overlap with each other; must remove or rewrite one of
        these paths; path one: [cart, items, [1], vat-item], path two: [cart, items]"
}

我正在使用下一个表达式:

"UpdateExpression":"SET
    cart.#listName[0].quantity = cart.#listName[0].quantity + :quantity1,
    cart.#listName[0].price = :price1,
    cart.#listName[0].#vatItem = :vatItem1,
    cart.#listName[1].quantity = cart.#listName[1].quantity + :quantity2, 
    cart.#listName[1].price = :price2,
    cart.#listName[1].#vatItem = :vatItem2,
    cart.#listName = list_append (cart.#listName, :jsonObject)"}

是否有任何 hack 可以很好地“设置元素并添加其他元素”?

我在 Whosebug 上找到了 ,但这个人正在尝试删除和设置,而我只设置。

在 python 中为愿意在家尝试的人添加了 MRE

import boto3

TABLE_NAME = "pk-only"

TABLE_RESOURCE = boto3.resource("dynamodb").Table(TABLE_NAME)
DDB_CLIENT = boto3.client("dynamodb")

def create_table():
    DDB_CLIENT.create_table(
        AttributeDefinitions=[{"AttributeName": "PK", "AttributeType": "S"}],
        TableName=TABLE_NAME,
        KeySchema=[{"AttributeName": "PK", "KeyType": "HASH"}],
        BillingMode="PAY_PER_REQUEST"
    )

def add_sample_item():
    TABLE_RESOURCE.put_item(
        Item={
            "PK": "append_and_update",
            "list": [
                {
                    "value": "a"
                }
            ]
        }
    )

def update():

    TABLE_RESOURCE.update_item(
        Key={
            "PK": "append_and_update"
        },
        UpdateExpression="SET #l = list_append(#l, :newItem), #l[0].#val = :newVal",
        ExpressionAttributeNames={
            "#l": "list",
            "#val": "value",
        },
        ExpressionAttributeValues={
            ":newVal": "b",
            ":newItem": {"M": {"value": {"S": "c"}}}
        }
    )

def main():
    # create_table()
    add_sample_item()
    update()

if __name__ == "__main__":
    main()

好吧,我想公开一下我所采用的解决这个问题的方法。

我在

中更改了这一行cart.#listName = list_append (cart.#listName, :jsonObject)
"UpdateExpression":"SET
    cart.#listName[0].quantity = cart.#listName[0].quantity + :quantity1,
    cart.#listName[0].price = :price1,
    cart.#listName[0].#vatItem = :vatItem1,
    cart.#listName[1].quantity = cart.#listName[1].quantity + :quantity2, 
    cart.#listName[1].price = :price2,
    cart.#listName[1].#vatItem = :vatItem2,
    cart.#listName = list_append (cart.#listName, :jsonObject)"}

来自 cart.#listName[2] = :jsonObject0, cart.#listName[3] = :jsonObject1, .....

"UpdateExpression":"SET
    cart.#listName[0].quantity = cart.#listName[0].quantity + :quantity1,
    cart.#listName[0].price = :price1,
    cart.#listName[0].#vatItem = :vatItem1,
    cart.#listName[1].quantity = cart.#listName[1].quantity + :quantity2, 
    cart.#listName[1].price = :price2,
    cart.#listName[1].#vatItem = :vatItem2,
    cart.#listName[2] = :jsonObject0, cart.#listName[3] = :jsonObject1"}

您需要知道列表中的项目数并将新元素添加到最后一个位置。我试过这个解决方案,你可以添加你想要的所有元素。

我知道这不是最好的解决方案,但对我来说效果很好,希望对你有所帮助

有趣的问题。

您想做的是:

"UpdateExpression":"SET
    cart.#listName[0].quantity = cart.#listName[0].quantity + :quantity1,
    cart.#listName[0].price = :price1,
    cart.#listName[0].#vatItem = :vatItem1,
    cart.#listName[1].quantity = cart.#listName[1].quantity + :quantity2, 
    cart.#listName[1].price = :price2,
    cart.#listName[1].#vatItem = :vatItem2,
    cart.#listName = list_append (cart.#listName, :jsonObject)"}

正如您所注意到的,这是不允许的 - 您不能替换 #listName(这是最后一个作业所做的) 更改特定的子属性#listName([0] 和 [1])在同一更新中。

但幸运的是,有一种不同的、相当晦涩的方法来附加到列表,适用于您的情况:

如果您的表达式要求设置 cart.#listName[1000],其中已知 1000 超出列表的长度(它可能比列表的长度高很多,与您的解决方案不同),则此元素附加在列表的末尾。它实际上附加在列表的末尾 - 如果列表只有 5 个项目,则元素添加为第 6 个,而不是第 1000 个。另一个需要注意的重要事项是,如果您在列表中设置元素 1000、1001 和 1002,它们将按此数字顺序附加。

了解这些事实后,您可以将代码更改为:

"UpdateExpression":"SET
    cart.#listName[0].quantity = cart.#listName[0].quantity + :quantity1,
    cart.#listName[0].price = :price1,
    cart.#listName[0].#vatItem = :vatItem1,
    cart.#listName[1].quantity = cart.#listName[1].quantity + :quantity2, 
    cart.#listName[1].price = :price2,
    cart.#listName[1].#vatItem = :vatItem2,
    cart.#listName[1000] = :jsonObject0,
    cart.#listName[1001] = :jsonObject1,
    cart.#listName[1002] = :jsonObject2"}

如果您担心 1000 可能不够高,只需将其替换为 1000000。实际数字无关紧要 - 该语句不会在数组中添加大量空元素。索引可以任意高 - 它们只需要高于现有列表的可能长度即可。