Reputation: 5782
Firstly, what I am trying to achieve with DynamoDB:
-> (I am trying to include username and password in scan filter for login system. So if for email/user and password combination, scan
method of AWSDynamoDBObjectMapper
returns an object, login is successful otherwise no.)
What's going wrong?
I have been trying to read documentation and sample code on Github for this but none seems to have example of proper use of it. From documentation I only found that scanFilter
is of type NSDictionary. So I tried to include multiple parameters for filtering (UserName/UserEmail and Password
) and it is failing to scan results.
scanExpression.scanFilter = @{@"Password": passwordCondition, UserNameOrUserEmail : usernameOrEmailCondition};
However if I pass only one parameter it works and returns an object, or lets say a row of a database.
scanExpression.scanFilter = @{@"Password": passwordCondition};
Full code for reference (Similar code for Android works fine, when I referred to colleague's, who is doing Android.):
// Check if email or username and decide DynamoDB Attribute accordingly.
NSString *UserNameOrUserEmail;
if ([usernameOrEmail rangeOfString:@"@"].location == NSNotFound)
UserNameOrUserEmail = @"UserName";
else
UserNameOrUserEmail = @"UserEmail";
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
AWSDynamoDBCondition *passwordCondition = [AWSDynamoDBCondition new];
AWSDynamoDBAttributeValue *passwordAttribute = [AWSDynamoDBAttributeValue new];
passwordAttribute.S = password;
passwordCondition.attributeValueList = @[passwordAttribute];
passwordCondition.comparisonOperator = AWSDynamoDBComparisonOperatorEQ;
AWSDynamoDBCondition *usernameOrEmailCondition = [AWSDynamoDBCondition new];
AWSDynamoDBAttributeValue *usernameOrEmailAttribute = [AWSDynamoDBAttributeValue new];
usernameOrEmailAttribute.S = @"[email protected]";//usernameOrEmail;
usernameOrEmailCondition.attributeValueList = @[usernameOrEmailAttribute];
usernameOrEmailCondition.comparisonOperator = AWSDynamoDBComparisonOperatorEQ;
//Apply filter condtions: http://stackoverflow.com/a/27856299/818506
scanExpression.scanFilter = @{@"Password": passwordCondition, UserNameOrUserEmail : usernameOrEmailCondition}; //@{@"UserEmail": usernameOrEmailCondition};//
//^^^^^^^^^^^^^^^^^^^^^^^^^^^Is this correct?^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//Perform a scan:
[[dynamoDBObjectMapper scan:[User class] expression:scanExpression]continueWithBlock: ^id (AWSTask *task){
if (task.error) {
NSLog(@"The request failed. Error: [%@]", task.error);
}
if (task.exception) {
NSLog(@"The request failed. Exception: [%@]", task.exception);
}
if (task.result) {
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
for (User *user in paginatedOutput.items) {
isLoginSuccessful = YES;
}
completionHandler(isLoginSuccessful);
}
return nil;
}];
Any suggestion/idea/comment would be appreciate.
Thanks, Rohan.
Upvotes: 1
Views: 578
Reputation: 7463
I stubbled on this thread while working on a similar problem. Here is how I solved it:
let objectMapper = AWSDynamoDBObjectMapper.default()
let scanExpression = AWSDynamoDBScanExpression()
scanExpression.filterExpression = "#UserNameOrUserEmail = :UserNameOrUserEmail AND #password = :follows"
scanExpression.expressionAttributeNames = ["#UserNameOrUserEmail": "UserNameOrUserEmail" , "#password": "password" ,]
scanExpression.expressionAttributeValues = [":UserNameOrUserEmail": "[email protected]", ":password": password ,]
objectMapper.scan(User.self, expression: scanExpression) { (response: AWSDynamoDBPaginatedOutput?, error: Error?) in
// handle data or error here...
}
Just it case it helps someone else.
Upvotes: 0
Reputation: 264
Have you considered using AWSDynamoDBScanInput
and a NSMutableDictionary
? I have the following example in Swift that should be fairly easy to translate to Objective-C:
// create password condition
let passwordCondition = AWSDynamoDBCondition()
let v1 = AWSDynamoDBAttributeValue(); v1.S = password
passwordCondition.comparisonOperator = AWSDynamoDBComparisonOperator.EQ
passwordCondition.attributeValueList = [ v1 ]
// create username condition
let usernameCondition = AWSDynamoDBCondition()
let v2 = AWSDynamoDBAttributeValue(); v2.S = "[email protected]"
usernameCondition.comparisonOperator = AWSDynamoDBComparisonOperator.EQ
usernameCondition.attributeValueList = [ v2 ]
// add these conditions to a NSMutableDictionary
var scanFilterDict : NSMutableDictionary! = NSMutableDictionary()
scanFilterDict.addEntriesFromDictionary(["password": passwordCondition])
scanFilterDict.addEntriesFromDictionary(["UserNameOrUserEmail": usernameCondition])
// use the mutable dictionary as scan filter
scanInput.scanFilter = scanFilterDict as Dictionary<NSObject, AnyObject>
scanInput.exclusiveStartKey = self.lastEvaluatedKey
scanInput.limit = 20
scanInput.tableName = "yourDynamoDBTable"
// apply AND operator on both conditions
scanInput.conditionalOperator = AWSDynamoDBConditionalOperator.And
AWSDynamoDB.defaultDynamoDB().scan(input)
Upvotes: 1