amazon-web-services - 是否可以在更新表达式中添加两个以上的属性/操作数来设置 DynamoDB 中的另一个属性?
问题描述
我试图在 DynamoDB 表的列中存储一个数值,该数值是该表中其他数值列的加法。
我读到这个:https ://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html虽然似乎没有明确提到两个以上的操作数不能与“+”中的操作相结合连续,当我尝试这样做时它确实失败了。
虽然我可能不应该将聚合值存储在列中,并且只有存储粒度值的列,但是这里有解决方法吗?
编辑: 这就是我想要做的
aws dynamodb --endpoint-url http://localhost:8042 update-item --table-name custom_table --key "{\"main_part\":{\"S\":\"hash_key\"},\"sort_part\":{\"S\":\"range_key\"}}" --update-expression "SET #A = #B + #C + :val" --expression-attribute-names "{\"#A\":\"column_1\",\"#B\":\"column_2\",\"#C\":\"column_3\"}" --expression-attribute-values "{\":val\":{\"N\":\"10\"}}"
这给出了以下错误:
An error occurred (ValidationException) when calling the UpdateItem operation: Invalid UpdateExpression: Syntax error; token: "+", near: "#C + :val"
解决方案
围绕UpdateItem 的 SET 操作的+
文档明确表示,当使用 a或 a-
作为表达式的一部分时,您只能有一个两个操作数。请注意,文档将操作描述value
为SET
:
value ::=
operand
| operand '+' operand
| operand '-' operand
如果它支持两个以上的操作数,你会在那里看到它。另外,您的示例很好地证明了它不起作用。
为了完成(我认为)您想要的,我认为您需要将临时操作数存储为项目的一部分。下面是一个示例,我正在创建和更新一个项目以保持水果计数。该项目具有以下属性:greenApples
、redApples
、apples
和。 应该始终是绿色和红色苹果的总和。 应始终是 、 和的总和。您的问题中有趣的一点是,当您只知道要增加其中一个组件属性的数量时,如何更新此项目。bananas
fruit
apples
fruit
greenApples
redApples
bananas
要考虑的一种选择是在您的命令中使用多个操作,您可以在一个语句中UpdateItem
同时更新组件值 ( redApples
) 以及聚合值 (apples
和)。fruit
这是使用AWS SDK V3的完整 TypeScript 代码示例:
const tableName = getFromEnv(`TABLE_NAME`);
const client = new DynamoDBClient({});
const PK = `FRUIT_COUNT`;
const SK = `FRUIT_COUNT`;
interface FruitOnHand {
bananas: number;
greenApples: number;
redApples: number;
}
interface FruitCount extends FruitOnHand {
apples: number;
fruit: number;
}
async function createItem({ bananas, greenApples, redApples }: FruitOnHand): Promise<FruitCount> {
const apples = greenApples + redApples;
const fruit = greenApples + redApples + bananas;
const appleCount = { apples, fruit, greenApples, redApples, bananas };
const item = { PK, SK, ...appleCount };
const putCommand = new PutItemCommand({
TableName: tableName,
Item: marshall(item)
});
await client.send(putCommand);
log(`Created item: ${inspect(item)}`);
return appleCount;
}
async function addRedApples(toAdd: number): Promise<FruitCount> {
const valueToAdd = { N: String(toAdd) };
const updateCommand = new UpdateItemCommand({
TableName: tableName,
Key: marshall({ PK, SK }),
UpdateExpression: `SET #APPLES = #APPLES + :val, #FRUIT = #FRUIT + :val, #RED = #RED + :val`,
ExpressionAttributeNames: {
'#APPLES': `apples`,
'#FRUIT': `fruit`,
'#RED': `redApples`,
},
ExpressionAttributeValues: {
':val': valueToAdd,
},
ReturnValues: 'ALL_NEW',
});
log(`Adding ${toAdd} red apples`)
const { Attributes } = await client.send(updateCommand);
const fruitCount = unmarshall(Attributes) as unknown as FruitCount;
log(`Updated item:`, inspect(fruitCount));
return fruitCount;
}
async function run() {
const initial = await createItem({
bananas: 2,
greenApples: 5,
redApples: 3,
});
assert(initial.redApples + initial.greenApples === initial.apples);
assert(initial.fruit === initial.apples + initial.bananas);
const updated = await addRedApples(8);
assert(updated.redApples + updated.greenApples === updated.apples);
assert(updated.fruit === updated.apples + updated.bananas);
}
很多代码只是设置示例并让 TypeScript 编译器满意;有趣的是在addRedApples(...)
功能中,我将其用作UpdateExpression
...
`SET #APPLES = #APPLES + :val, #FRUIT = #FRUIT + :val, #RED = #RED + :val`
...将组件属性的值以及两个聚合属性的值增加相同的数量。
执行run()
函数的结果显示项目的初始和更新内容:
Created item: {
PK: 'FRUIT_COUNT',
SK: 'FRUIT_COUNT',
apples: 8,
fruit: 10,
greenApples: 5,
redApples: 3,
bananas: 2
}
Adding 8 red apples
Updated item: {
apples: 16,
fruit: 18,
bananas: 2,
SK: 'FRUIT_COUNT',
redApples: 11,
PK: 'FRUIT_COUNT',
greenApples: 5
}
推荐阅读
- webpack - 如何在不使用 webpack 生成新块的情况下拆分 webpack 条目
- android-studio - 在没有白色背景的android studio中显示imageview
- c - 一次释放堆上多个区域的机制
- java - Hybris 后台:WYSIWYG 中的图像配置不起作用
- python - 我想打印 json.how 中存在的特定字段的计数以搜索该字段并打印与该字段关联的所有 avlues 的总和
- opencv - 如何将包含图像信息的 .xml 文件转换为 jpeg 或 png
- redux - 组合多个减速器时无法更改状态
- c++ - 识别打开共享内存状态的方法
- python - 为什么不允许字符串像值一样嵌入到 f 字符串中?
- wordpress - 如何合并两个 .PO wordpress 语言文件?