为二级索引加载记录

Loading records for secondary index

我正在尝试使用 DynamoDB 实现用户注册和登录。用户可以通过三种方式登录。他们可以使用用户名、phone 号码或电子邮件 ID 登录。 我的 DynamoDB table 在主索引中有 Phone 数字作为散列,因此我可以使用 -

正确加载它
- (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 的详细信息

这是二级全球指数 -

(对不起,图片不是文字,我不确定如何在此处正确显示它。)

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

更新:
我的模型 class 对于不同的哈希键是不同的,因为哈希键是一种 class 方法。这是我的 parent class 的样子 -

//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 哈希键使用不同 class 的方式 -

//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 方法中,我只是为不同的用户传递了不同的 class(我已经用实际方法更新了它)。当我使用 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 散列键时,它不起作用并且 returns 出现 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 和随机 phone 数字标记)。

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

此错误消息表示您为 table(或索引属性)定义的键之一在发出的请求中没有正确的 AttributeValue 类型。请启用 logging 并查看您是否可以提供正在发出的实际 Put/Update/BatchWrite 项目请求的 JSON。

此外,您的 DynamoDBMapper 注释也可能与 table 的基本 table 和 GSI 模式不完全对齐。请在此处确认或 post 您注释 class 的重要细节。

真正的问题肯定是亚历山大所说的。我在 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];

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