加载二级索引的记录

时间:2015-04-27 14:01:36

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

我正在尝试使用DynamoDB实现用户注册和登录。用户可以通过三种方式登录。他们可以使用用户名,电话号码或电子邮件ID登录。 我的DynamoDB表在主索引中将电话号码作为哈希值,因此我可以使用 -

正确加载它
- (void)loadUser:(Class)userClass withHashKey:(NSString*)hashkey withBlock:(void(^)(id))completionBlock{
    [[dynamoDBObjectMapper load:userClass hashKey:hashkey rangeKey:nil]
     continueWithBlock:^id(BFTask *task) {
         if (task.error) {
             NSLog(@"The request failed. Error: [%@]", task.error);
         }
         if (task.exception) {
             NSLog(@"The request failed. Exception: [%@]", task.exception);
         }
         if (task.result) {
             if(completionBlock)
                 completionBlock(task.result);
         }
         return nil;
     }];
}

但我无法对用户名和电子邮件使用相同的方法。当我尝试使用用户名或电子邮件时,我收到以下错误 -

2015-04-27 19:01:42.549 Barnc[691:122171] AWSiOSSDKv2 [Verbose] AWSURLResponseSerialization.m line:86 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: [{"__type":"com.amazon.coral.validate#ValidationException","message":"The provided key element does not match the schema"}]
2015-04-27 19:01:42.556 Barnc[691:122171] The request failed. Error: [Error Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "The operation couldn’t be completed. (com.amazonaws.AWSDynamoDBErrorDomain error 0.)" UserInfo=0x17b96ed0 {message=The provided key element does not match the schema, __type=com.amazon.coral.validate#ValidationException}]

这是表格的详细信息 Table Details

这是二级全球指数 - Secondary Indices

(抱歉图片而不是文字,我不知道如何在这里正确显示。)

访问二级索引是否还需要其他东西?我有兴趣使用最后两个索引来使用用户名或电子邮件加载用户。

更新
我的模型类对于不同的散列键是不同的,因为散列键是一种类方法。这是我的父类看起来的样子 -

//AmazonUser.h
#import <Foundation/Foundation.h>
#import <AWSDynamoDB/AWSDynamoDB.h>
@class BarncUser;

@interface AmazonUser : AWSDynamoDBObjectModel <AWSDynamoDBModeling>

@property (nonatomic, strong) NSString *phone_no;
@property (nonatomic, strong) NSString *password;
@property (nonatomic, strong) NSString *c2CallPassword;
@property (nonatomic, strong) NSString *activated;
@property (nonatomic, strong) NSMutableArray *catalog_ids;
@property (nonatomic, strong) NSNumber *defaultOnlineStatus;
@property (nonatomic, strong) NSNumber *signed_in_counts;
@property (nonatomic, strong) NSNumber *total_referrals;
@property (nonatomic, strong) NSString *account_creation_date;
@property (nonatomic, strong) NSString *email_id;
@property (nonatomic, strong) NSString *account_owner;
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSString *first_name;
@property (nonatomic, strong) NSString *chat_enabled;
@property (nonatomic, strong) NSString *last_name;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *last_date_of_sign_out;
@property (nonatomic, strong) NSString *date_of_birth;
@property (nonatomic, strong) NSString *last_date_signed_in;
@property (nonatomic, strong) NSString *address_line1;

@property (nonatomic, strong) NSString *gplus_user_id;
@property (nonatomic, strong) NSString *fb_user_id;

- (void)createDummy;
- (void)loadFromUser:(BarncUser*)user;
- (void)loadToUser:(BarncUser*)user;
@end

//AmazonUser.m
@implementation AmazonUser  
+ (NSString *)dynamoDBTableName {
    return @"Users";
}
+ (NSString *)hashKeyAttribute {
    return @"phone_no";
}
//implementation of the methods which is not included here.
@end

这就是我为phone_no和email_id哈希键使用不同类的方法 -

//AWSUserWithPhone.m
#import "AWSUserWithPhone.h"

@implementation AWSUserWithPhone

+ (NSString *)hashKeyAttribute {
    return @"phone_no";
}

@end


//AWSUserWIthEmail
#import "AWSUserWithEmail.h"

@implementation AWSUserWithEmail

+ (NSString *)hashKeyAttribute {
    return @"email_id";
}

@end

在Load方法中,我只为不同的用户传递不同的类(我已经用实际方法更新了它)。当我使用phone_no hashkey时,一切运行良好,我得到以下输出 -

2015-04-28 13:26:58.908 Barnc[1359:264405] AWSiOSSDKv2 [Verbose] AWSURLRequestSerialization.m line:111 | -[AWSJSONRequestSerializer serializeRequest:headers:parameters:] | Request body: [{"IdentityId":"us-east-1:xxx"}]
2015-04-28 13:27:01.590 Barnc[1359:264405] AWSiOSSDKv2 [Debug] AWSURLResponseSerialization.m line:81 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response header: [{
    "Content-Length" = 1052;
    "Content-Type" = "application/x-amz-json-1.1";
    Date = "Tue, 28 Apr 2015 07:57:01 GMT";
    "x-amzn-RequestId" = "xxx";
}]
2015-04-28 13:27:01.591 Barnc[1359:264405] AWSiOSSDKv2 [Verbose] AWSURLResponseSerialization.m line:86 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: [{"Credentials":{"AccessKeyId":"xxx","Expiration":1.430211421E9,"SecretKey":"xxx"},"IdentityId":"us-east-1:xxx"}]
2015-04-28 13:27:01.648 Barnc[1359:264405] AWSiOSSDKv2 [Verbose] AWSURLRequestSerialization.m line:111 | -[AWSJSONRequestSerializer serializeRequest:headers:parameters:] | Request body: [{"Key":{"phone_no":{"S":"+912222"}},"TableName":"Users"}]
2015-04-28 13:27:01.661 Barnc[1359:264405] AWSiOSSDKv2 [Debug] AWSSignature.m line:305 | -[AWSSignatureV4Signer signRequestV4:] | AWS4 Canonical Request: [POST
/

accept-encoding:
content-type:application/x-amz-json-1.0
host:dynamodb.us-east-1.amazonaws.com
user-agent:aws-sdk-iOS/2.1.0 iPhone-OS/8.3 en_IN
x-amz-date:20150428T075701Z
x-amz-security-token:xxx
x-amz-target:DynamoDB_20120810.GetItem

accept-encoding;content-type;host;user-agent;x-amz-date;x-amz-security-token;x-amz-target
xxx]
2015-04-28 13:27:01.663 Barnc[1359:264405] AWSiOSSDKv2 [Debug] AWSSignature.m line:306 | -[AWSSignatureV4Signer signRequestV4:] | payload {"Key":{"phone_no":{"S":"+912222"}},"TableName":"Users"}
2015-04-28 13:27:01.665 Barnc[1359:264405] AWSiOSSDKv2 [Debug] AWSSignature.m line:322 | -[AWSSignatureV4Signer signRequestV4:] | AWS4 String to Sign: [AWS4-HMAC-SHA256
20150428T075701Z
20150428/us-east-1/dynamodb/aws4_request
xxx]
2015-04-28 13:27:03.738 Barnc[1359:264405] AWSiOSSDKv2 [Debug] AWSURLResponseSerialization.m line:81 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response header: [{
    "Content-Length" = 593;
    "Content-Type" = "application/x-amz-json-1.0";
    Date = "Tue, 28 Apr 2015 07:57:03 GMT";
    "x-amz-crc32" = 2404923750;
    "x-amzn-RequestId" = xxx;
}]
2015-04-28 13:27:03.739 Barnc[1359:264405] AWSiOSSDKv2 [Verbose] AWSURLResponseSerialization.m line:86 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: [{"Item":{"fb_user_id":{"S":"null"},"catalog_ids":{"L":[{"S":"0"},{"S":"1"}]},"first_name":{"S":"xxx"},"email_id":{"S":"xxx"},"password":{"S":"xxx"},"date_of_birth":{"S":"xxx"},"phone_no":{"S":"+912222"},"chat_enabled":{"S":"Yes"},"account_creation_date":{"S":"25-Apr-2015"},"title":{"S":"mr"},"last_name":{"S":"xxx"},"account_owner":{"S":"null"},"address_line1":{"S":"null"},"last_date_signed_in":{"S":"25-Apr-2015"},"last_date_of_sign_out":{"S":"25-Apr-2015"},"gplus_user_id":{"S":"null"},"activated":{"S":"Yes"},"c2CallPassword":{"S":"xxx"}}}]
2015-04-28 13:27:03.768 Barnc[1359:264405] logged
2015-04-28 13:27:03.771 Barnc[1359:264405] This is a block
2015-04-28 13:27:05.797 Barnc[1359:263979] observeValueForKeyPath : sessionId
2015-04-28 13:27:06.189 Barnc[1359:264534] observeValueForKeyPath : ownNumberVerified
2015-04-28 13:27:06.190 Barnc[1359:264534] ownNumberVerified : 0
AudioUnitGraph 0x54F000:
  Member Nodes:
    node 1: 'auou' 'rioc' 'appl', instance 0x171dab00 O  
    node 2: 'aumx' 'mcmx' 'appl', instance 0x15fea630 O  
    node 3: 'aufc' 'conv' 'appl', instance 0x171b23e0 O  
  Connections:
    node   2 bus   0 => node   1 bus   0  [ 1 ch,  48000 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer]
    node   3 bus   0 => node   2 bus   0  [ 1 ch,  48000 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer]
  Input Callbacks:
    {0x18d755, 0x172bbf80} => node   2 bus   1  [1 ch, 48000 Hz]
    {0x18d755, 0x172bbf80} => node   3 bus   0  [1 ch, 8000 Hz]
  CurrentState:
    mLastUpdateError=0, eventsToProcess=F, isInitialized=F, isRunning=F

但是当我使用email_id哈希键时,它不起作用并返回ValidationException。这是完整的详细日志 -

2015-04-28 13:31:11.432 Barnc[1359:263979] AWSiOSSDKv2 [Verbose] AWSURLRequestSerialization.m line:111 | -[AWSJSONRequestSerializer serializeRequest:headers:parameters:] | Request body: [{"Key":{"email_id":{"S":"xxx"}},"TableName":"Users"}]
2015-04-28 13:31:11.443 Barnc[1359:263979] AWSiOSSDKv2 [Debug] AWSSignature.m line:305 | -[AWSSignatureV4Signer signRequestV4:] | AWS4 Canonical Request: [POST
/

accept-encoding:
content-type:application/x-amz-json-1.0
host:dynamodb.us-east-1.amazonaws.com
user-agent:aws-sdk-iOS/2.1.0 iPhone-OS/8.3 en_IN
x-amz-date:20150428T080111Z
x-amz-security-token:xxx
x-amz-target:DynamoDB_20120810.GetItem

accept-encoding;content-type;host;user-agent;x-amz-date;x-amz-security-token;x-amz-target
830520dc23c906e3612ed64618172cd60661698f151658092eb879bcda635827]
2015-04-28 13:31:11.445 Barnc[1359:263979] AWSiOSSDKv2 [Debug] AWSSignature.m line:306 | -[AWSSignatureV4Signer signRequestV4:] | payload {"Key":{"email_id":{"S":"xxx"}},"TableName":"Users"}
2015-04-28 13:31:11.446 Barnc[1359:263979] AWSiOSSDKv2 [Debug] AWSSignature.m line:322 | -[AWSSignatureV4Signer signRequestV4:] | AWS4 String to Sign: [AWS4-HMAC-SHA256
20150428T080111Z
20150428/us-east-1/dynamodb/aws4_request
xxx]
2015-04-28 13:31:11.453 Barnc[1359:265181] plugin com.swiftkey.SwiftKeyApp.Keyboard invalidated
2015-04-28 13:31:13.291 Barnc[1359:265197] AWSiOSSDKv2 [Debug] AWSURLResponseSerialization.m line:81 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response header: [{
    "Content-Length" = 121;
    "Content-Type" = "application/x-amz-json-1.0";
    Date = "Tue, 28 Apr 2015 08:01:12 GMT";
    "x-amz-crc32" = 3485231410;
    "x-amzn-RequestId" = xxx;
}]
2015-04-28 13:31:13.292 Barnc[1359:265197] AWSiOSSDKv2 [Verbose] AWSURLResponseSerialization.m line:86 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: [{"__type":"com.amazon.coral.validate#ValidationException","message":"The provided key element does not match the schema"}]
2015-04-28 13:31:13.301 Barnc[1359:265197] The request failed. Error: [Error Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "The operation couldn’t be completed. (com.amazonaws.AWSDynamoDBErrorDomain error 0.)" UserInfo=0x1727b680 {message=The provided key element does not match the schema, __type=com.amazon.coral.validate#ValidationException}]

PS:出于安全原因,隐藏了某些信息(标有xxx和随机电话号码)。

2 个答案:

答案 0 :(得分:1)

感谢您提供有关架构的详细信息。

此错误消息表示您为表(或索引属性)定义的其中一个键在正在进行的请求中没有正确的AttributeValue类型。请启用logging,看看是否可以提供正在进行的实际Put / Update / BatchWrite Item请求的JSON。

此外,您的DynamoDBMapper注释也可能与表的基表和GSI模式完全对齐。请在此确认或发布带注释课程的重要细节。

答案 1 :(得分:0)

真正的问题绝对是亚历山大所提到的。我在iOS代码的上下文中发布此答案。 Global Secondary Index无法使用load操作。我们需要query。以下是我通过电子邮件加载用户的当前代码如何 -

- (void)loadUserWithQuery:(Class)userClass withHashKey:(NSString*)hashkey withIndexName:(NSString*)indexName withBlock:(void(^)(id))completionBlock{
    AWSDynamoDBQueryExpression* expression = [AWSDynamoDBQueryExpression new];
    expression.hashKeyValues = hashkey;
    expression.indexName = indexName;
    expression.scanIndexForward = @YES;
    expression.limit = @1;

    [[dynamoDBObjectMapper query:userClass expression:expression] continueWithBlock:^id(BFTask *task) {
        if (task.error) {
            NSLog(@"The request failed. Error: [%@]", task.error);
        }
        if (task.exception) {
            NSLog(@"The request failed. Exception: [%@]", task.exception);
        }
        if (task.result) {
            if(completionBlock)
                completionBlock(task.result);
        }
        return nil;
    }];
}

结果来自AWSDynamoDBPaginatedOutput,因此您需要从那里提取结果。我使用以下代码 -

AWSDynamoDBPaginatedOutput *output = (AWSDynamoDBPaginatedOutput*)result;
AmazonUser* user = (AmazonUser*)[output.items objectAtIndex:0];

您可以通过添加检查来查看输出中是否至少包含一个项目来进一步增强它。