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。实际数字无关紧要 - 该语句不会在数组中添加大量空元素。索引可以任意高 - 它们只需要高于现有列表的可能长度即可。
我的 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。实际数字无关紧要 - 该语句不会在数组中添加大量空元素。索引可以任意高 - 它们只需要高于现有列表的可能长度即可。