はじめに
swiftでDynamoDBと連携するアプリの開発をすることがあると思いますが、記事が少なかったのでデータを取得する方法をまとめてみました。
開発環境
- Swift 5
- Xcode 12
- aws-amplify/aws-sdk-ios
- cocoapods
1. AWSの認証設定
こちらにまとめましたので参考にしてください。
【iOS】AWS DynamoDBからテーブル名を取得する方法
2. podにAWSDyanamoDBを追加
プロジェクトにすでにPodが導入されていることが前提です。
もしインストールされていなければ、インストールしてください。
PodfileにAWDDyanmoDB
を追加します。
target 'aws-sdk' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
pod 'AWSDynamoDB'
end
podインストールしてXcodeを開き直します。
$ pod install --repo-update
$ xed .
3. AWS DynamoDBでテーブル作成・データ挿入
テーブルの作成を押して、テーブルを作成します。
今回はテーブル名をuserにしました。
Userテーブル
カラム名 | 型 | プライマリパーティションキー |
---|---|---|
id | Number | ○ |
String | ||
password | String |
テーブルが作成されたら、項目のタブを選択します。
そして、項目の作成を押してデータを作成します。
下記のようなデータを作成しました。
カラム名 | 値 |
---|---|
test@test.com | |
password | password |
4. modelを作成
DynamoDBのデータを取得するためにモデルを作成します。
クラス名やプロパティへ適宜変更してください。
@objcを付けないとデータを取得できません。
私はこれがわからずハマったので、忘れないように気をつけてください。。。
import AWSDynamoDB
class User: AWSDynamoDBObjectModel, AWSDynamoDBModeling {
@objc private var id: NSNumber = 0
@objc private var email: String = ""
@objc private var password: String = ""
class func dynamoDBTableName() -> String {
return "user" // DyanmoDBに作成したテーブル名を記載
}
class func hashKeyAttribute() -> String {
return "id"
}
}
5. データを取得するメソッドを作成
今回はデータを全件取得するのでscanを使用しています。
import UIKit
import AWSDynamoDB
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
fetchDynamoDBData()
}
private func fetchDynamoDBData() {
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
let scanExpression = AWSDynamoDBScanExpression()
// Userの部分は作成したModelのクラス名
dynamoDBObjectMapper.scan(User.self, expression: scanExpression).continueWith() { (task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Void in
guard let items = task.result?.items as? [User] else { return }
if let error = task.error as NSError? {
print("The request failed. Error: \(error)")
return
}
print(items)
}
}
}
これでビルドするとコンソールにデータが表示されます。
もしDyanmoDBに大量のデータがある場合
データが多いとscanでも、一度に全件取得できない可能性があります。(ここに気づかず、かなりハマった。。。)
一回のscanで1MBまでしか取得できません。
全件取得できていない場合は、task.result?.lastEvaluatedKey
というものが出現します。
つまり、これがnilにならない限り、全件取得できてきないということです。(ページネーションの現在のページのようなもの)
もしデータが大量にあるが、全件取得したい場合は、ページネーションを更新する必要があります。
下記のように、task.result?.lastEvaluatedKey
が存在すれば、スタートするページをtask.result?.lastEvaluatedKey
に更新して再度fetchします。
func fetchDynamoDBData() {
dynamoDBObjectMapper.scan(User.self, expression: scanExpression).continueWith() { (task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Void in
guard let key = task.result?.lastEvaluatedKey else {
print("scan終了")
return
}
if key != nil {
// MEMO: スタートするページを更新
scanExpression.exclusiveStartKey = key
fetchDynamoDBData()
}
}
}
リポジトリ
参考までに。
https://github.com/shungo0525/aws-sdk
参考記事
https://stackoverflow.com/questions/26958637/best-way-to-make-amazon-aws-dynamodb-queries-using-swift
https://stackoverflow.com/questions/34049054/aws-dynamodb-swift-query-with-multiple-hashkeyvalues