如何通过boto3使用Attr.exists()筛选获取DynamoDB记录?
问题:Boto3使用Attr语法筛选DynamoDB属性存在的记录返回空,原生表达式却正常?
我使用boto3 v1.28.44版本,尝试筛选DynamoDB中存在指定属性的记录,第一段用Attr语法的代码运行后返回空列表:
import boto3 from boto3.dynamodb.conditions import Attr resource = boto3.resource("dynamodb") table = resource.Table(MY_TABLE_NAME) records = [] pagination = {} while True: response = table.scan(FilterExpression=Attr(attr_name).exists(), **pagination) records += response["Items"] if response.get("LastEvaluatedKey"): pagination = {"ExclusiveStartKey": response["LastEvaluatedKey"]} else: break
但第二段使用原生表达式的代码却能正常获取所有包含指定属性的记录:
resource = boto3.resource("dynamodb") table = resource.Table(MY_TABLE_NAME) records = [] pagination = {} while True: response = table.scan( FilterExpression="attribute_exists(#1)", ExpressionAttributeNames={"#1": attr_name}, **pagination ) records += response["Items"] if response.get("LastEvaluatedKey"): pagination = {"ExclusiveStartKey": response["LastEvaluatedKey"]} else: break
我偏好简洁的Attr语法,希望统一代码风格,请问第一种写法是否存在问题?
解答
第一种写法的问题在于:当attr_name是DynamoDB保留字(如Name、Timestamp)或包含特殊字符(空格、点号等)时,Attr(attr_name).exists()不会自动处理属性名的转义,而原生表达式写法通过ExpressionAttributeNames做了转义,这是两者结果不同的核心原因。
要让Attr语法正常工作,只需补充ExpressionAttributeNames来转义属性名,和原生表达式逻辑对齐,修改后的代码如下:
import boto3 from boto3.dynamodb.conditions import Attr resource = boto3.resource("dynamodb") table = resource.Table(MY_TABLE_NAME) records = [] pagination = {} # 定义属性名占位符与真实名称的映射 expr_attr_names = {"#target_attr": attr_name} while True: response = table.scan( FilterExpression=Attr("#target_attr").exists(), ExpressionAttributeNames=expr_attr_names, **pagination ) records += response["Items"] if response.get("LastEvaluatedKey"): pagination = {"ExclusiveStartKey": response["LastEvaluatedKey"]} else: break
这段代码通过#target_attr作为占位符,在ExpressionAttributeNames中映射到真实的attr_name,解决了保留字和特殊字符的转义问题,能和原生表达式写法得到一致的结果。
内容的提问来源于stack exchange,提问作者MartinSolie
相关产品推荐
相关产品推荐

