[英]AWS DynamoDB Scan failing on iOS but works on Android
我将DynamoDB用作移动应用程序的后端数据库,并且架构等在Android和iOS中是相同的。 对于特定的用例,我必须基于未索引的两个属性执行扫描。 对于iOS Objective C,我使用以下代码:
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
scanExpression.limit = [NSNumber numberWithInt:maxCount];
scanExpression.filterExpression = @"#l = :location AND event = :event";
scanExpression.expressionAttributeNames = @{@"#l":@"location"};
scanExpression.expressionAttributeValues = @{@":location":location,
@":event":EVENT_TASTING};
位置和事件都是字符串。 EVENT_TASTING是一个字符串常量。 即使我已经验证了所提供的条目我应该收到的结果,该扫描仍返回零结果。 我在Android Java中使用以下代码:
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
scanExpression.setLimit(maxCount);
scanExpression.addFilterCondition("location",
new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(location)));
scanExpression.addFilterCondition("event",
new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(Constants.EVENT_TASTING)));
扫描可以在Android中按预期进行。 要在iOS上正常运行,需要进行哪些更改? 我将iOS SDK更新为2.3.6,但没有任何改变。 这是我在代码中执行的唯一扫描操作。
iOS的scanExpression是否存在错误? 有没有一种方法可以使用Android样式的语法在iOS上实现此功能?
更新资料
我尝试了以下更改:
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
AWSDynamoDBAttributeValue *locationVal = [AWSDynamoDBAttributeValue new];
locationVal.S = location;
AWSDynamoDBAttributeValue *eventVal = [AWSDynamoDBAttributeValue new];
eventVal.S = EVENT_TASTING;
scanExpression.limit = [NSNumber numberWithInt:maxCount];
scanExpression.filterExpression = @"#l = :location AND event = :event";
scanExpression.expressionAttributeNames = @{@"#l":@"location"};
scanExpression.expressionAttributeValues = @{@":location":locationVal,
@":event":eventVal};
但是现在我得到一个错误:
The request failed. Error: [Error Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "(null)" UserInfo={message=ExpressionAttributeValues contains invalid value: Supplied AttributeValue is empty, must contain exactly one of the supported datatypes for key :location, __type=com.amazon.coral.validate#ValidationException}]
感谢@YosukeMatsuda的提示,我能够通过反复调用Scan直到LastEvaluatedKey为空来解决此问题。 我将其发布为答案,因为不幸的是,迈克的答案并未指出正确的问题,并且具有误导性。
这是我在iOS中更改代码的方式:
// In a different method (for first call):
AWSDynamoDBScanExpression *scanExpression = // See code in original question
// In a new method that can be called recursively:
// DynamoDBObjectMapper scan:class-for-model expression:scanExpression
// continueWithBlock -> if (task.result):
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
if (paginatedOutput.items.count != 0)
// Append the paginatedOutput.items to the cumulative array
else
// Replace the cumulative array with paginatedOutput.items
if (paginatedOutput.lastEvaluatedKey.count == 0) {
// Scan is complete - handle results
} else {
// Check if you have sufficient results
// In my case I had asked for 25 results but was getting 39
// So it doesn't seem to obey the scanExpression.limit value
// If more results are needed, continue the scan
[scanExpression setExclusiveStartKey:paginatedOutput.lastEvaluatedKey];
// Call this method recursively
}
如果有更优雅的解决方案,我很想听听。 但是至少现在可以了。
您使用的Android代码与ObjectiveC版本之间存在一些差异。
location
和event
的值应为AWSDynamoDBAttributeValue *
类型,而不是字符串; 如果进行此更改,您的查询很可能会开始工作。 我希望这能回答您的问题,但不能确定,因为您只说“这在Android中可以按预期工作-我如何使其在iOS中工作”,但您没有告诉我们有什么问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.