使用Swift进行Amazon AWS DynamoDB查询的最佳方法?

时间:2014-11-16 15:32:12

标签: amazon-web-services swift amazon-dynamodb

我最近为我的iOS应用程序实现了AWS SDK,我正在Swift中开发。我已经连接到我的数据库实例广告,我可以获得查询响应,但是我很难将其转换为可用数据。我对Swift,AWS和编程都比较新,所以可能会遗漏一些明显的东西!

我的代码如下:

    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
    }

控制台的输出是:

对象:[{     area =" {\ n S = \" West Hampstead \"; \ n}&#34 ;;     name =" {\ n S = \" Olly Mayes \"; \ n}&#34 ;;     userid =" {\ n S = \" 123456abc \"; \ n}&#34 ;; }]

使用AWS和Swift似乎没有多少优先权,这是可以理解的,所以任何帮助都会非常感激!

1 个答案:

答案 0 :(得分:28)

您的问题的简单答案是:将返回的JSON字符串转换为Dictionary对象。 像这样:

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 {
            ...
        }

但是,我强烈建议您查看更高级别的DynamoDB映射器类 使用DynamoDB映射器类时,您可以定义数据结构,并将其提供给DynamoDB Mapper。这是一个完整的示例,从表创建到表删除。该示例使用DynamoDB Mapper插入,删除,扫描和查询表。

首先,您需要初始化客户端SDK

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

这只是一个示例。在代码中嵌入Access Key和Secret Key并不是一个好习惯。最佳做法是使用AWSCognitoCredentialsProvider代替(read more about Cognito)。

定义一个用于在表格中映射项目的类

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

创建表格

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

删除表格

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

插入项目

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

加载一个项目

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)

}

查询哈希和范围键

/* 
   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)
}

扫描项目(全表扫描)

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

如果您在美国EAST 1中没有使用DynamoDB,则运行此示例不会产生任何费用,因为它会落入DynamoDB's free tier