1

J'essaie de mettre en œuvre l'enregistrement des utilisateurs et la connexion à l'aide de DynamoDB. L'utilisateur peut se connecter de trois manières différentes. Ils peuvent utiliser le nom d'utilisateur, le numéro de téléphone ou l'adresse électronique pour se connecter. Ma table DynamoDB a le numéro de téléphone comme hachage dans l'index primaire et donc je suis en mesure de le charger correctement à l'aide -Chargement des enregistrements pour l'index secondaire

- (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; 
    }]; 
} 

Mais je ne peux pas utiliser la même méthode pour nom d'utilisateur et e-mail. Je reçois l'erreur suivante lorsque je tente nom d'utilisateur ou e-mail à la place -

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}] 

Voilà les détails de la table Table Details

et voici les indices globaux secondaires - Secondary Indices

(Désolé pour les images au lieu de texte, je ne savais pas comment le montrer correctement ici.)

Existe-t-il autre chose nécessaire pour accéder aux index secondaires? Je suis intéressé à utiliser les deux derniers indices pour charger l'utilisateur en utilisant un nom d'utilisateur ou un e-mail.

Mise à jour:
Ma classe de modèle est différent selon la clé de hachage, car la clé de hachage est une méthode de classe. Voici ce que ma classe parente ressemble -

//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 

Et voilà comment je l'ai utilisé différentes classes pour PHONE_NO et la clé de hachage 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 

Dans la méthode Load Je passe juste différentes classes pour différents utilisateurs (Je l'ai mis à jour avec la méthode actuelle). Quand j'utilise PHONE_NO hashkey, tout fonctionne bien et je reçois la sortie suivante -

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 

Mais quand j'utilise la clé de hachage email_id, il ne fonctionne pas et renvoie le ValidationException. Voici le journal détaillé complet -

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: Certaines informations sont cachées (marquée par le numéro de téléphone xxx et aléatoire) pour des raisons de sécurité.

+0

Je ne connais pas le mappeur iOS, mais je suppose qu'il est très similaire au SDK Java, mais pourriez-vous afficher votre classe 'AWSUserWithPhone'? – mkobit

+0

@MikeKobit J'ai ajouté plus de détails dans la question, pouvez-vous s'il vous plaît jeter un oeil à maintenant? – noob

Répondre

1

Merci d'avoir fourni des détails sur votre schéma.

Ce message d'erreur signifie que l'une des clés que vous avez définies pour votre table (ou attributs indexés) n'a pas le type AttributeValue correct dans la demande en cours. Veuillez activer logging et voir si vous pouvez fournir le JSON de la demande Put/Update/BatchWrite Item en cours.

De plus, il est également possible que vos annotations DynamoDBMapper ne s'alignent pas parfaitement avec la table de base et les schémas GSI de votre table. Veuillez confirmer ou afficher les détails importants de votre classe annotée ici.

+0

Merci pour la réponse Alex. J'ai mis à jour ma question avec plus de détails, pouvez-vous regarder cela? – noob

+0

En fonction de votre trace de connexion, vous appelez GetItem et obtenez une exception de validation. GetItem ne fonctionne que sur la table de base, pas GSI. Vous pouvez utiliser l'appel [Query] (http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) pour obtenir les informations dont vous avez besoin dans l'index. Set 'KeyConditionExpression =" # emailIdPath =: email "', 'ExpressionAttributeNames = {" # emailIdPath ":" email_id "}', 'ExpressionAttributeValues ​​= {": email ":" [email protected] "}', 'TableName = users' et 'IndexName = email_id-index' et essayez une requête à la place. –

+0

Merci, c'était mon problème à coup sûr. J'utilise maintenant Query au lieu de load. Je suis sûr que cela vaut également pour l'opération de sauvegarde. – noob

0

Le vrai problème était définitivement ce qu'Alexandre a mentionné. Je poste cette réponse dans le contexte du code iOS. Global Secondary Index ne peut pas utiliser l'opération load. Nous avons besoin de query pour cela.Voici comment mon code actuel pour charger l'utilisateur par e-mail ressemble -

- (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; 
    }]; 
} 

Le résultat est en AWSDynamoDBPaginatedOutput, vous aurez donc besoin d'extraire le résultat à partir de là. J'utilise le code ci-dessous -

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

Vous pouvez encore l'améliorer en ajoutant des contrôles pour voir si la sortie a au moins un élément en elle.