DynamoDB无需读库校验实现movies_watched map存储唯一影片的方法
实现方案
完全可以不用提前读取校验,直接使用DynamoDB原生的条件写入能力就能满足你的需求,实现原子性的唯一影片写入,避免并发冲突。
核心逻辑是在写入请求中加入ConditionExpression,判定待新增的影片ID对应的map键不存在时才执行写入,请求如果触发条件不满足的异常,就说明该影片已经存在,直接处理异常即可,不需要额外做读操作校验。
以下是Node.js环境下的代码示例:
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb"); const { DynamoDBDocumentClient, UpdateCommand } = require("@aws-sdk/lib-dynamodb"); // 初始化DynamoDB客户端 const client = new DynamoDBClient({ region: "替换为你的AWS区域" }); const docClient = DynamoDBDocumentClient.from(client); const addUniqueMovie = async (userId, dob, newMovieId, newMovieInfo) => { const params = { TableName: "替换为你的表名", Key: { user_id: userId, dob: dob }, // 写入新影片到map对应键位 UpdateExpression: `SET movies_watched.#movieId = :movieInfo`, ExpressionAttributeNames: { "#movieId": newMovieId // 用表达式别名规避数字作为属性名的语法问题 }, ExpressionAttributeValues: { ":movieInfo": newMovieInfo }, // 核心条件:只有该影片ID不存在时才执行写入 ConditionExpression: `attribute_not_exists(movies_watched.#movieId)` }; try { await docClient.send(new UpdateCommand(params)); return { success: true, msg: "影片新增成功" }; } catch (error) { if (error.name === "ConditionalCheckFailedException") { return { success: false, msg: "该影片已存在,无需重复添加" }; } throw error; } } // 调用示例 addUniqueMovie(1, "1991-09-12", "5", { movie_name: "星际穿越", movie_released_year: "2014", movie_genre: "科幻" });
注意事项
- 该操作是原子操作,即使同一时间有多个相同的写入请求,也只会有一个请求执行成功,不会出现重复写入的问题
- 条件写入的资源开销和普通写入完全一致,不会额外消耗读容量
- 如果你判断唯一的依据不是影片ID,而是影片名称等其他字段,只需要把对应字段作为map的键,或者额外新增一个字符串集合存储唯一标识,把条件表达式修改为
NOT contains(唯一标识集合字段, :待校验值)即可
内容的提问来源于stack exchange,提问作者PB384
相关产品推荐
相关产品推荐

