LoginSignup
8
2

More than 3 years have passed since last update.

【iOS】DynamoDBからデータを取得する方法

Posted at

はじめに

swiftでDynamoDBと連携するアプリの開発をすることがあると思いますが、記事が少なかったのでデータを取得する方法をまとめてみました。

開発環境

1. AWSの認証設定

こちらにまとめましたので参考にしてください。
【iOS】AWS DynamoDBからテーブル名を取得する方法

2. podにAWSDyanamoDBを追加

プロジェクトにすでにPodが導入されていることが前提です。
もしインストールされていなければ、インストールしてください。

PodfileにAWDDyanmoDBを追加します。

Podfile
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
email String
password String

スクリーンショット 2020-12-31 15.27.06.png

テーブルが作成されたら、項目のタブを選択します。
そして、項目の作成を押してデータを作成します。
下記のようなデータを作成しました。

カラム名
email test@test.com
password password

スクリーンショット 2020-12-31 15.27.45.png

4. modelを作成

DynamoDBのデータを取得するためにモデルを作成します。
クラス名やプロパティへ適宜変更してください。

@objcを付けないとデータを取得できません。
私はこれがわからずハマったので、忘れないように気をつけてください。。。

User.swift
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を使用しています。

ViewController.swift
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)
        }
    }
}

これでビルドするとコンソールにデータが表示されます。

スクリーンショット 2020-12-31 18.03.21.png

もしDyanmoDBに大量のデータがある場合

データが多いとscanでも、一度に全件取得できない可能性があります。(ここに気づかず、かなりハマった。。。)
一回のscanで1MBまでしか取得できません。

(DynamoDB でのスキャンの使用)

全件取得できていない場合は、task.result?.lastEvaluatedKeyというものが出現します。
つまり、これがnilにならない限り、全件取得できてきないということです。(ページネーションの現在のページのようなもの)

もしデータが大量にあるが、全件取得したい場合は、ページネーションを更新する必要があります。
下記のように、task.result?.lastEvaluatedKeyが存在すれば、スタートするページをtask.result?.lastEvaluatedKeyに更新して再度fetchします。

ViewController.swift
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

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2