AWS DynamoDB 多个 "NE" 字符串过滤器?
AWS DynamoDB multiple "NE" string filters?
我正在尝试 scan/query AWS DynamoDB table 获取其中 id(单个字符串)不等于任何字符串 A、B、C、D、等等
我试过这样的事情:
for (String itemString : items) {
scanExpression.addFilterCondition("id",
new Condition().withComparisonOperator(ComparisonOperator.NE)
.withAttributeValueList(new AttributeValue().withS(itemString)));
}
PaginatedScanList<Items> result = mapper.scan(Item.class, scanExpression);
似乎发生的情况是,每次我添加过滤器时,它都会覆盖以前的值,因此扫描只检查一个 itemString,而不是多个。我是否遗漏了什么,或者这是 DynamoDB 的限制?
注意:如果重要的话,在我的示例中,我列出了四个值(A、B、C、D),但在生产中,这可能是一个包含数百个值的列表。
您说的是正确的 "overwrites the previous values"。这是 DynamoDBScanExpression
:
上 1.9.23 SDK 的相关代码
public void addFilterCondition(String attributeName, Condition condition) {
if ( scanFilter == null )
scanFilter = new HashMap<String, Condition>();
scanFilter.put(attributeName, condition);
}
由于您的 attributeName
对于两个 puts
都是 id
,在这种情况下,最后一个值将获胜。
在我看来,这是 DynamoDBScanExpression
的不良行为,我什至更倾向于说这是一个应该报告的错误。该文档没有说明何时添加重复 attributeName
并且方法名称使它看起来像是意外行为。
除了构建整个过滤器表达式之外,我没有找到解决此问题的好方法。
另一个注意事项:在 documentation 上,我没有看到过滤器表达式可以有多长以及允许多少 ExpressionAttributeNames
和 ExpressionAttributeValues
的长度限制根据要求。如果您试图过滤掉大量属性值,可能会考虑到这一点,但我还没有找到任何关于该限制可能是什么或您应该期望什么行为的文档。
StringJoiner filterExpression = new StringJoiner(" AND ");
Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
int itemAttributeSuffix = 0;
for (String itemString : items) {
StringBuilder expression = new StringBuilder("#idname")
.append(" ")
.append("<>")
.append(" ")
.append(":idval")
.append(itemAttributeSuffix);
filterExpression.add(expression);
expressionAttributeValues.put(":idval" + itemAttributeSuffix++,
new AttributeValue().withS(itemString));
}
Map<String, String> expressionAttributeNames = Collections.singletonMap("#idname", "id");
scanExpression.setFilterExpression(filterExpression.toString());
scanExpression.setExpressionAttributeNames(expressionAttributeNames);
scanExpression.setExpressionAttributeValues(expressionAttributeValues);
PaginatedScanList<Items> result = mapper.scan(Item.class, scanExpression);
我正在尝试 scan/query AWS DynamoDB table 获取其中 id(单个字符串)不等于任何字符串 A、B、C、D、等等
我试过这样的事情:
for (String itemString : items) {
scanExpression.addFilterCondition("id",
new Condition().withComparisonOperator(ComparisonOperator.NE)
.withAttributeValueList(new AttributeValue().withS(itemString)));
}
PaginatedScanList<Items> result = mapper.scan(Item.class, scanExpression);
似乎发生的情况是,每次我添加过滤器时,它都会覆盖以前的值,因此扫描只检查一个 itemString,而不是多个。我是否遗漏了什么,或者这是 DynamoDB 的限制?
注意:如果重要的话,在我的示例中,我列出了四个值(A、B、C、D),但在生产中,这可能是一个包含数百个值的列表。
您说的是正确的 "overwrites the previous values"。这是 DynamoDBScanExpression
:
public void addFilterCondition(String attributeName, Condition condition) {
if ( scanFilter == null )
scanFilter = new HashMap<String, Condition>();
scanFilter.put(attributeName, condition);
}
由于您的 attributeName
对于两个 puts
都是 id
,在这种情况下,最后一个值将获胜。
在我看来,这是 DynamoDBScanExpression
的不良行为,我什至更倾向于说这是一个应该报告的错误。该文档没有说明何时添加重复 attributeName
并且方法名称使它看起来像是意外行为。
除了构建整个过滤器表达式之外,我没有找到解决此问题的好方法。
另一个注意事项:在 documentation 上,我没有看到过滤器表达式可以有多长以及允许多少 ExpressionAttributeNames
和 ExpressionAttributeValues
的长度限制根据要求。如果您试图过滤掉大量属性值,可能会考虑到这一点,但我还没有找到任何关于该限制可能是什么或您应该期望什么行为的文档。
StringJoiner filterExpression = new StringJoiner(" AND ");
Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
int itemAttributeSuffix = 0;
for (String itemString : items) {
StringBuilder expression = new StringBuilder("#idname")
.append(" ")
.append("<>")
.append(" ")
.append(":idval")
.append(itemAttributeSuffix);
filterExpression.add(expression);
expressionAttributeValues.put(":idval" + itemAttributeSuffix++,
new AttributeValue().withS(itemString));
}
Map<String, String> expressionAttributeNames = Collections.singletonMap("#idname", "id");
scanExpression.setFilterExpression(filterExpression.toString());
scanExpression.setExpressionAttributeNames(expressionAttributeNames);
scanExpression.setExpressionAttributeValues(expressionAttributeValues);
PaginatedScanList<Items> result = mapper.scan(Item.class, scanExpression);