Best way to make Amazon AWS DynamoDB queries using Swift?

I recently implemented the AWS SDK for my iOS app that I am developing in Swift. I contacted my instance of the database instance, which was able to get a response to the request, however I am struggling to convert it into usable data. I am relatively new to Swift, AWS, and programming in general, so something obvious may be missing!

My code is as follows:

let atVal = AWSDynamoDBAttributeValue() atVal.S = "123456abc" let condition = AWSDynamoDBCondition() condition.comparisonOperator = AWSDynamoDBComparisonOperator.EQ condition.attributeValueList = [atVal] let myDic: [String: AWSDynamoDBCondition] = ["userid": condition] let query = AWSDynamoDBQueryInput() query.indexName = "userid-index" query.tableName = "users" query.keyConditions = myDic query.limit = 1 dynamoDB.query(query).continueWithBlock { (task: BFTask!) -> AnyObject! in let results = task.result as AWSDynamoDBQueryOutput let myResults = results.items println("object: \(myResults.description)") return nil } 

And console output for this:

object: [{area = "{\ n S = \" West Hampstead \ "; \ n}"; name = "{\ n S = \" Olly Mayes \ "; \ n}"; userid = "{\ n S = \" 123456abc \ "; \ n}"; }]

It seems that using AWS and Swift does not seem to have much priority, so any help would be greatly appreciated!

+8
amazon-web-services amazon-dynamodb swift
source share
1 answer

A simple answer to your question: convert the JSON string returned to the Dictionary object. Something like that:

 let data = jsonDataItem.dataUsingEncoding(NSUTF8StringEncoding) if data != nil { var error : NSError? let dict = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments, error: &error) as? NSDictionary if let e = error { ... } else { ... } 

However, I highly recommend that you take a look at the Dynamo Dynamo mapping class. When using the DynamoDB mapper class, you define the data structure and simply specify DynamoDB Mapper . Here is a complete example: from creating a table to deleting a table. An example inserts, deletes, scans, and queries a table using DynamoDB Mapper.

First you need to initialize the client SDK

  let cp = AWSStaticCredentialsProvider(accessKey: "AK...", secretKey: "xxx") let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: cp) AWSServiceManager.defaultServiceManager().setDefaultServiceConfiguration(configuration) 

This is just a sample. Incorrect use of the built-in passkey and secret key. Best practice would be to use AWSCognitoCredentialsProvider instead of more about Cognito ).

Define a class that displays your items in a table

 class Item : AWSDynamoDBModel, AWSDynamoDBModeling { var email : String = "" var date : String = "" var note : String = "" var number : Double = 0.0 override init!() { super.init() } required init!(coder: NSCoder!) { fatalError("init(coder:) has not been implemented") } class func dynamoDBTableName() -> String! { return "Demo" } class func hashKeyAttribute() -> String! { return "email" } class func rangeKeyAttribute() -> String! { return "date" } //required to let DynamoDB Mapper create instances of this class override init(dictionary dictionaryValue: [NSObject : AnyObject]!, error: NSErrorPointer) { super.init(dictionary: dictionaryValue, error: error) } //workaround to possible XCode 6.1 Bug : "Type NotificationAck" does not conform to protocol "NSObjectProtocol" override func isEqual(anObject: AnyObject?) -> Bool { return super.isEqual(anObject) } } 

To create a table

 self.createTable().continueWithSuccessBlock {(task: BFTask!) -> BFTask! in NSLog("Create table - success") return nil } func createTable() -> BFTask! { let pt = AWSDynamoDBProvisionedThroughput() pt.readCapacityUnits = 10 pt.writeCapacityUnits = 10 let emailAttr = AWSDynamoDBAttributeDefinition() emailAttr.attributeName = "email" emailAttr.attributeType = AWSDynamoDBScalarAttributeType.S let dateAttr = AWSDynamoDBAttributeDefinition() dateAttr.attributeName = "date" dateAttr.attributeType = AWSDynamoDBScalarAttributeType.S let emailKey = AWSDynamoDBKeySchemaElement() emailKey.attributeName = "email" emailKey.keyType = AWSDynamoDBKeyType.Hash let dateKey = AWSDynamoDBKeySchemaElement() dateKey.attributeName = "date" dateKey.keyType = AWSDynamoDBKeyType.Range let ct = AWSDynamoDBCreateTableInput() ct.tableName = "Demo" ct.provisionedThroughput = pt ct.attributeDefinitions = [emailAttr, dateAttr] ct.keySchema = [ emailKey, dateKey ] NSLog("Creating table") let client = AWSDynamoDB.defaultDynamoDB() return client.createTable(ct) } 

To delete a table

 self.deleteTable().continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in NSLog("Delete table - success") return nil }) func deleteTable() -> BFTask! { let dt = AWSDynamoDBDeleteTableInput() dt.tableName = "Demo" NSLog("Deleting table") let client = AWSDynamoDB.defaultDynamoDB() return client.deleteTable(dt) } 

Insert items

 self.insertSomeItems().continueWithBlock({ (task: BFTask!) -> BFTask! in if (task.error != nil) { NSLog(task.error.description) } else { NSLog("DynamoDB save succeeded") } return nil; }) func insertSomeItems() -> BFTask! { let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper() var item = Item() item.email = "stormacq@amazon.com" item.date = "20141101" item.note = "This is item #1" item.number = 1.0 let task1 = mapper.save(item) item = Item() item.email = "stormacq@amazon.com" item.date = "20141102" item.note = "This is item #2" item.number = 2.0 let task2 = mapper.save(item) item = Item() item.email = "stormacq@amazon.lu" item.date = "20141103" item.note = "This is item #3" item.number = 3.0 let task3 = mapper.save(item) return BFTask(forCompletionOfAllTasks: [task1, task2, task3]) } 

To load one item

 self.load("stormacq@amazon.com", range:"20141101").continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in NSLog("Load one value - success") let item = task.result as Item print(item) return nil }) func load(hash: String, range: String) -> BFTask! { let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper() return mapper.load(Item.self, hashKey: hash, rangeKey: range) } 

Hash request and range key

 /* keyConditions http://docs.aws.amazon.com/AWSiOSSDK/latest/Classes/AWSDynamoDBQueryInput.html#//api/name/keyConditions */ let cond = AWSDynamoDBCondition() let v1 = AWSDynamoDBAttributeValue(); v1.S = "20141101" cond.comparisonOperator = AWSDynamoDBComparisonOperator.EQ cond.attributeValueList = [ v1 ] let c = [ "date" : cond ] self.query("stormacq@amazon.com", keyConditions:c).continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in NSLog("Query multiple values - success") let results = task.result as AWSDynamoDBPaginatedOutput for r in results.items { print(r) } return nil }) func query(hash: String, keyConditions:[NSObject:AnyObject]) -> BFTask! { let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper() let exp = AWSDynamoDBQueryExpression() exp.hashKeyValues = hash exp.rangeKeyConditions = keyConditions return mapper.query(Item.self, expression: exp) } 

Scan objects (full table scan)

 let cond = AWSDynamoDBCondition() let v1 = AWSDynamoDBAttributeValue(); v1.S = "20141101" cond.comparisonOperator = AWSDynamoDBComparisonOperator.GT cond.attributeValueList = [ v1 ] let exp = AWSDynamoDBScanExpression() exp.scanFilter = [ "date" : cond ] self.scan(exp).continueWithSuccessBlock({ (task: BFTask!) -> BFTask! in NSLog("Scan multiple values - success") let results = task.result as AWSDynamoDBPaginatedOutput for r in results.items { print(r) } return nil }) func scan(expression : AWSDynamoDBScanExpression) -> BFTask! { let mapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper() return mapper.scan(Item.self, expression: expression) } 

Unless you have another use of DynamoDB in US EAST 1, there is no cost associated with running this sample because it drops to the free DynamoDB level .

+27
source share

All Articles