AWS DynamoDB扫描在iOS上失败,但适用于Android

时间:2016-04-18 00:18:29

标签: android ios amazon-web-services amazon-dynamodb

我正在使用DynamoDB作为我的移动应用程序的后端数据库,并且架构等在Android和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是一个String常量。此扫描保持返回零结果,即使我已经验证了所提供的条目我应该接收结果。我在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,但它没有什么区别。这是我在代码中进行的唯一扫描操作。

我的scanExpression for iOS是否有错误?有没有办法可以使用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}]

2 个答案:

答案 0 :(得分:1)

感谢来自@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
}

如果有更优雅的解决方案,我很乐意听到它。但至少它现在有效。

答案 1 :(得分:0)

您使用的Android代码与ObjectiveC版本之间存在一些差异。

  1. 在Android版中您使用较旧的过滤条件 API,而在ObjectiveC中您使用了更现代的过滤表达式 API;这并不一定会让新人失败,但这只是指出
  2. 在ExpressionAttributeValues的情况下,您传入的loginBehaviour FBSDKLoginBehaviorSystemAccountlocation的值应为event类型,而不是字符串;如果您进行此更改,您的查询很可能会开始工作。
  3. 我希望这可以回答你的问题,但不能确定,因为你只是说"这在Android中可以正常运行 - 我怎样才能让它在iOS" 中运行但是你并没有告诉我们什么是破碎的。