Dynamodb ConditionExpression不生效,求排查及title唯一插入方案
问题排查与解决方案
现有测试代码的问题
测试代码1的问题
你用ConditionExpression="attribute_not_exists(PK)"的逻辑完全偏离需求:这个条件仅判断当前要写入的PK+SK组合对应的条目是否不存在(因为条目不存在时PK属性自然不存在)。但你每次生成的SK都是随机值,每条都是全新的PK+SK组合,所以这个条件永远满足,不会触发异常,和检查title是否存在毫无关系。
测试代码2的问题
你用ConditionExpression=Attr("PK").ne(pk)的逻辑完全错误:你写入的Item中PK就是pk,DynamoDB里,若目标条目不存在,PK属性不存在,和任何值比较结果都是false;若条目存在,PK等于pk,比较结果还是false。所以这个条件永远不满足,每次都会触发ConditionalCheckFailedException。
针对需求的解决方案
你的核心需求是仅当全局范围内没有任何记录的title与当前值重复时,才插入新记录,以下是两种可行方案:
方案1:利用GSI实现title全局唯一性(推荐)
DynamoDB主表的唯一性由PK+SK保证,要实现title全局唯一,需借助全局二级索引(GSI):
- 给
NewsTable创建一个GSI:- 索引名称:
TitleIndex - 键架构:将
title设为HASH键(分区键) - 投影类型:选择
KEYS_ONLY即可(仅投影主表的PK和SK,节省存储)
- 索引名称:
- 写入时使用以下代码,结合条件表达式实现唯一性校验:
import uuid from datetime import datetime from decimal import Decimal from boto3.dynamodb.conditions import Attr try: NewsTable.put_item( Item={ "PK": "intentional_id_to_check_failing_of_ConditionExpression", "SK": f"news#id#{uuid.uuid4().hex}", "model_type": "TEST_MODEL", "title": "dummy_title_1", "timestamp": Decimal(str(datetime.now().timestamp())), }, ConditionExpression=Attr("title").not_exists() ) except resource.meta.client.exceptions.ConditionalCheckFailedException as e: print("该title已存在,无法插入新记录")
注:若需要极高的一致性(避免并发写入导致的重复),可使用
transact_write_items包裹查询与写入操作,实现原子性校验。
方案2:调整数据模型(若业务允许)
如果业务可以接受将title作为主表的PK(分区键),那么主表的PK唯一性会自动阻止重复title的插入:
- 若允许覆盖已有记录:直接执行
put_item即可,已有相同title的记录会被覆盖。 - 若不允许覆盖:添加
ConditionExpression="attribute_not_exists(PK)",当title已存在时会触发异常。
内容的提问来源于stack exchange,提问作者hafiz ali
相关产品推荐
相关产品推荐

