如何将 DynamoDB 属性设置为空列表?
How do I set a DynamoDB attribute to an empty list?
我正在尝试使用适用于 .NET 的 AWS 开发工具包中的 DynamoDBv2 库,通过更新请求将 DynamoDB 文档中的属性设置为空列表。
我尝试了明显的更新表达式,但没有成功:
// Fails, expression attribute values cannot contain an empty list
...
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{ ":empty", new AttributeValue { L = new List<AttributeValue> { } } },
},
UpdateExpression = "SET #P.MyList = :empty",
...
我怎样才能做到这一点?
我在深入了解 AWS SDK 源代码后找到了答案。关键是 IsLSet
属性 是可设置的。这会调用以下代码:
public static void SetIsSet<T>(bool isSet, ref List<T> field)
{
if (isSet)
field = new AlwaysSendList<T>(field);
else
field = new List<T>();
}
在确定您的 AttributeValue 是否已初始化时,使用以下代码:
public static bool GetIsSet<T>(List<T> field)
{
if (field == null)
return false;
if (field.Count > 0)
return true;
var sl = field as AlwaysSendList<T>;
if (sl != null)
return true;
return false;
}
这也说明了为什么使用 new AttributeValue { L = new List<AttributeValue> { } }
没有达到预期效果 - 由于 Count
为 0,此方法将 return 错误。但是,检查特殊 AlwaysSendList
如果您设置了 IsLSet
属性.
,则类型将 return 为真
回到你的代码,答案是使用下面的:
...
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{ ":empty", new AttributeValue { IsLSet = true } },
},
UpdateExpression = "SET #P.MyList = :empty",
...
我自己刚刚 运行 解决了这个问题。看起来像是至少从 2018 年 11 月开始就存在的错误 (https://github.com/aws/aws-sdk-net/issues/1116)。我的解决方法是在设置 L
.
的值后立即手动设置 IsLSet = true
例如,这是创建空列表属性的方法:
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":empty", new AttributeValue { L = new List<AttributeValue>(), IsLSet = true }},
},
UpdateExpression = "SET #P.MyList = :empty",
无论您的列表是否为空,您都应该能够使用上述语法。例如:
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":MyListOfValues", new AttributeValue { L = listValues, IsLSet = true }},
},
UpdateExpression = "SET #P.MyList = :MyListOfValues",
对于那些在 Java SDK 中遇到此问题的人,我找到了解决方案。 Java 的库中似乎没有 IsLSet
类比。要使用 Java 为 DynamoDB 指定一个空的 AttributeValue 列表,以下工作:
AttributeValue.builder().l(new ArrayList<AttributeValue>()).build();
例如,
String updateExpression = "SET my_list = :empty_list";
Map<String, AttributeValue> expressionAttributeValues = Map.of(
":empty_list", AttributeValue.builder().l(new ArrayList<AttributeValue>()).build()
);
我正在尝试使用适用于 .NET 的 AWS 开发工具包中的 DynamoDBv2 库,通过更新请求将 DynamoDB 文档中的属性设置为空列表。
我尝试了明显的更新表达式,但没有成功:
// Fails, expression attribute values cannot contain an empty list
...
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{ ":empty", new AttributeValue { L = new List<AttributeValue> { } } },
},
UpdateExpression = "SET #P.MyList = :empty",
...
我怎样才能做到这一点?
我在深入了解 AWS SDK 源代码后找到了答案。关键是 IsLSet
属性 是可设置的。这会调用以下代码:
public static void SetIsSet<T>(bool isSet, ref List<T> field)
{
if (isSet)
field = new AlwaysSendList<T>(field);
else
field = new List<T>();
}
在确定您的 AttributeValue 是否已初始化时,使用以下代码:
public static bool GetIsSet<T>(List<T> field)
{
if (field == null)
return false;
if (field.Count > 0)
return true;
var sl = field as AlwaysSendList<T>;
if (sl != null)
return true;
return false;
}
这也说明了为什么使用 new AttributeValue { L = new List<AttributeValue> { } }
没有达到预期效果 - 由于 Count
为 0,此方法将 return 错误。但是,检查特殊 AlwaysSendList
如果您设置了 IsLSet
属性.
回到你的代码,答案是使用下面的:
...
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{ ":empty", new AttributeValue { IsLSet = true } },
},
UpdateExpression = "SET #P.MyList = :empty",
...
我自己刚刚 运行 解决了这个问题。看起来像是至少从 2018 年 11 月开始就存在的错误 (https://github.com/aws/aws-sdk-net/issues/1116)。我的解决方法是在设置 L
.
IsLSet = true
例如,这是创建空列表属性的方法:
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":empty", new AttributeValue { L = new List<AttributeValue>(), IsLSet = true }},
},
UpdateExpression = "SET #P.MyList = :empty",
无论您的列表是否为空,您都应该能够使用上述语法。例如:
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":MyListOfValues", new AttributeValue { L = listValues, IsLSet = true }},
},
UpdateExpression = "SET #P.MyList = :MyListOfValues",
对于那些在 Java SDK 中遇到此问题的人,我找到了解决方案。 Java 的库中似乎没有 IsLSet
类比。要使用 Java 为 DynamoDB 指定一个空的 AttributeValue 列表,以下工作:
AttributeValue.builder().l(new ArrayList<AttributeValue>()).build();
例如,
String updateExpression = "SET my_list = :empty_list";
Map<String, AttributeValue> expressionAttributeValues = Map.of(
":empty_list", AttributeValue.builder().l(new ArrayList<AttributeValue>()).build()
);