DynamoDB.DocumentClient动态属性upsert搭配原子计数器不生效问题
问题根因
你的代码存在2个核心错误导致计数器无法自增:
- 硬编码了表达式变量
:nImports的值为0,导致每次执行更新时逻辑固定为0 + 1,永远不会读取数据库中已存储的计数器旧值 - 没有兼容新item插入的场景,首次插入item时
nImports字段不存在会导致表达式执行异常
修复方案
调整计数器更新逻辑,使用DynamoDB内置的if_not_exists函数兼容存量更新和新增插入两种场景,同时避免和动态字段更新逻辑冲突,修复后的完整代码如下:
async function update (tableName, item, idAttributeNames) { const counterAttrName = 'nImports' var params = { TableName: tableName, Key: {}, ExpressionAttributeValues: {}, ExpressionAttributeNames: {}, UpdateExpression: "", ReturnValues: "UPDATED_NEW" }; for (const attname of idAttributeNames) { params["Key"][attname] = item[attname]; } let prefix = "set "; let attributes = Object.keys(item); for (let i=0; i<attributes.length; i++) { let attribute = attributes[i]; // 同时排除主键和计数器字段,避免动态更新和计数器逻辑冲突 if (!idAttributeNames.includes(attribute) && attribute !== counterAttrName) { params["UpdateExpression"] += prefix + "#" + attribute + " = :" + attribute; params["ExpressionAttributeValues"][":" + attribute] = item[attribute]; params["ExpressionAttributeNames"]["#" + attribute] = attribute; prefix = ", "; } } // 调整计数器表达式:如果计数器不存在用初始值0,否则用已有值,再加增量1 params["UpdateExpression"] += `, #${counterAttrName} = if_not_exists(#${counterAttrName}, :counterInit) + :counterIncr`; params["ExpressionAttributeValues"][":counterIncr"] = 1; params["ExpressionAttributeValues"][":counterInit"] = 0; params["ExpressionAttributeNames"][`#${counterAttrName}`] = counterAttrName return await docClient.update(params).promise(); }
改动说明
- 移除了原代码中硬编码
:nImports = 0的错误逻辑,改为直接引用字段本身的存储值 - 新增
if_not_exists逻辑兼容新增item场景,首次插入时计数器会自动初始化为1 - 动态字段遍历逻辑新增排除计数器字段,避免传入的item中带
nImports字段时和计数器逻辑冲突 - 删除了原代码中冗余的空调用
await docClient.update行
内容的提问来源于stack exchange,提问作者rpc
相关产品推荐
相关产品推荐

