iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0
Software Development

NoSQL: Not Only SQL系列 第 15

[Day 15] Key-Value Database: 以 DynamoDB 為例

  • 分享至 

  • xImage
  •  

建立本機環境

DynamoDB 現在有提供本地端使用的 docker image,接下來我們就使用它來進行練習吧。

本機 DynamoDB 表現和 AWS 上的 DynamoDB 有一些差異,不過只是基本操作練習的話不影響。
預設資料都會被儲存在記憶體中,所以重開資料就會消失。

Docker

安裝 Docker 的部分網路上有很多相關教學,這邊就不贅述了,如果不熟指令的人可以選擇安裝 Docker Desktop 使用它提供的畫面操作。

Pull Image

取得 dynamodb-local 的 image。

> docker pull amazon/dynamodb-local

Run Image

將該 image run 起來,指定 port 1234 (或其他你想要的 port 也可以),並命名為 ironman-dynamodb-demo

> docker run -p 1234:8000 --name ironman-dynamodb-demo amazon/dynamodb-local

AWS CLI

接著安裝 AWS CLI 並設定 Configure,讓我們可以透過 CLI 對剛剛 run 起來的 dynamodb-local 進行操作。

安裝 AWS CLI

下載位置
可以執行 aws --version 看看有沒有顯示版本,來確認是否安裝成功。

> aws --version

得到結果:

aws-cli/2.7.31 Python/3.9.11 Windows/10 exe/AMD64 prompt/off

設定 Configure

其中的 AWS Access Key IDAWS Secret Access Key 隨意設定,Default region name 可從 AWS Region 清單中任意挑一個。

> aws cofigure
AWS Access Key ID [None]: JustTypeSomething
AWS Secret Access Key [None]: JustTypeSomething
Default region name [None]: ap-southeast-1
Default output format [None]:

基本操作

建立好環境之後,我們就可以透過 CLI 對 DB 進行操作了。假設我們要建立一個「使用者通知設定」的系統,資料表設計如下:

  • Table Name: NotificationSettings
  • PK
    • Partition Key
      • Name: UserId
      • Data Type: String
    • Sort Key
      • Name: NotificationType
      • Data Type: String
  • Throughput
    • Read: 5
    • Write: 5

Throughput 相關資訊這邊不再花篇幅描述,請見官方文件

建立 Table

> aws dynamodb create-table --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --attribute-definitions ^
        AttributeName=UserId,AttributeType=S ^
        AttributeName=NotificationMethod,AttributeType=S ^
    --key-schema ^
        AttributeName=UserId,KeyType=HASH ^
        AttributeName=NotificationMethod,KeyType=RANGE ^
    --provisioned-throughput ^
        ReadCapacityUnits=5,WriteCapacityUnits=5

成功建立的話,會輸出該 Table 的資訊。

{
    "TableDescription": {
        "AttributeDefinitions": [
            {
                "AttributeName": "UserId",
                "AttributeType": "S"
            },
            {
                "AttributeName": "NotificationMethod",
                "AttributeType": "S"
            }
        ],
        "TableName": "NotificationSettings",
        "KeySchema": [
            {
                "AttributeName": "UserId",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "NotificationMethod",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2022-09-16T00:52:29.563000+08:00",
        "ProvisionedThroughput": {
            "LastIncreaseDateTime": "1970-01-01T08:00:00+08:00",
            "LastDecreaseDateTime": "1970-01-01T08:00:00+08:00",
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 5,
            "WriteCapacityUnits": 5
        },
        "TableSizeBytes": 0,
        "ItemCount": 0,
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/NotificationSettings"
    }
}

也可以透過查看現有的 Table 清單,確認是否建立成功。

> aws dynamodb list-tables --endpoint-url http://localhost:1234

得到結果:

{
    "TableNames": [
        "NotificationSettings"
    ]
}

建立資料

使用者 Anderson 設定以 Email 接收通知。

> aws dynamodb put-item  --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --item ^
        "{\"UserId\":{\"S\":\"Anderson\"},\"NotificationMethod\":{\"S\":\"Email\"},\"Address\":{\"S\":\"anderson123@mail.com\"}}"

使用者 Betty 設定以 Email 和 Android App 推播接收通知。

> aws dynamodb put-item  --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --item ^
        "{\"UserId\":{\"S\":\"Betty\"},\"NotificationMethod\":{\"S\":\"Email\"},\"Address\":{\"S\":\"betty456@mail.com\"}}"
> aws dynamodb put-item  --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings  ^
    --item ^
        "{\"UserId\":{\"S\":\"Betty\"},\"NotificationMethod\":{\"S\":\"Android\"},\"RegistrationId\":{\"S\":\"b2fe650c-b19a-4556-b5c4-43fcbd6b478e\"}}"

查詢資料

接著我們查詢看看剛剛新增的資料是否都有成功寫入資料庫中。
查詢 Anderson 的 Email 通知設定:

> aws dynamodb get-item --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --key "{\"UserId\":{\"S\":\"Anderson\"},\"NotificationMethod\":{\"S\":\"Email\"}}"

得到結果:

{
    "Item": {
        "Address": {
            "S": "anderson123@mail.com"
        },
        "UserId": {
            "S": "Anderson"
        },
        "NotificationMethod": {
            "S": "Email"
        }
    }
}

查詢 Betty 的 Email 通知設定:

> aws dynamodb get-item --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --key "{\"UserId\":{\"S\":\"Betty\"},\"NotificationMethod\":{\"S\":\"Email\"}}"

得到結果:

{
    "Item": {
        "Address": {
            "S": "betty456@mail.com"
        },
        "UserId": {
            "S": "Betty"
        },
        "NotificationMethod": {
            "S": "Email"
        }
    }
}

查詢 Betty 的 Android App 推播通知設定:

> aws dynamodb get-item --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --key "{\"UserId\":{\"S\":\"Betty\"},\"NotificationMethod\":{\"S\":\"Android\"}}"

得到結果:

{
    "Item": {
        "UserId": {
            "S": "Betty"
        },
        "NotificationMethod": {
            "S": "Android"
        },
        "RegistrationId": {
            "S": "b2fe650c-b19a-4556-b5c4-43fcbd6b478e"
        }
    }
}

查詢不存在的資料,如 Anderson 的 Android App 推播通知設定,則不會有任何回傳。
只指定 Partition Key 進行查詢,可以取得該 Partition Key 下的所有 Items。
查詢 Betty 的所有通知設定:

> aws dynamodb query --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --key-condition-expression "UserId = :name" ^
    --expression-attribute-values  "{\":name\":{\"S\":\"Betty\"}}"

得到結果:

{
    "Items": [
        {
            "UserId": {
                "S": "Betty"
            },
            "NotificationMethod": {
                "S": "Android"
            },
            "RegistrationId": {
                "S": "b2fe650c-b19a-4556-b5c4-43fcbd6b478e"
            }
        },
        {
            "Address": {
                "S": "betty456@mail.com"
            },
            "UserId": {
                "S": "Betty"
            },
            "NotificationMethod": {
                "S": "Email"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2,
    "ConsumedCapacity": null
}

修改資料

接著試著修改 Betty 的 Email,更多的表達式規格請見官方文件,另外透過參數 --return-value ALL_NEW 要求回傳新資料。

> aws dynamodb update-item --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --key "{\"UserId\":{\"S\":\"Betty\"},\"NotificationMethod\":{\"S\":\"Email\"}}" ^
    --update-expression "SET Address = :newval" ^
    --expression-attribute-values "{\":newval\":{\"S\":\"new_betty456@mail.com\"}}" ^
    --return-values ALL_NEW

得到結果:

{
    "Attributes": {
        "Address": {
            "S": "new_betty456@mail.com"
        },
        "UserId": {
            "S": "Betty"
        },
        "NotificationMethod": {
            "S": "Email"
        }
    }
}

刪除一筆資料

最後透過 CLI 將 Anderson 的資料刪除。

> aws dynamodb delete-item --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --key "{\"UserId\":{\"S\":\"Anderson\"},\"NotificationMethod\":{\"S\":\"Email\"}}"

Secondary Index

除了最基本的 CRUD 操作,多數應用情境同時也會有一些非 PK 的查詢的需求,這時就需要透過 Secondary Index 達成。
建立 Address 欄位的 Global Secondary Index:

> aws dynamodb update-table --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --attribute-definitions AttributeName=Address,AttributeType=S ^
    --global-secondary-index-updates "[{\"Create\":{\"IndexName\":\"Address-Index\",\"KeySchema\":[{\"AttributeName\":\"Address\",\"KeyType\":\"HASH\"}],\"ProvisionedThroughput\":{\"ReadCapacityUnits\":10,\"WriteCapacityUnits\":5},\"Projection\":{\"ProjectionType\":\"ALL\"}}}]"

得到結果:

{
    "TableDescription": {
        "AttributeDefinitions": [
            {
                "AttributeName": "Address",
                "AttributeType": "S"
            },
            {
                "AttributeName": "UserId",
                "AttributeType": "S"
            },
            {
                "AttributeName": "NotificationMethod",
                "AttributeType": "S"
            }
        ],
        "TableName": "NotificationSettings",
        "KeySchema": [
            {
                "AttributeName": "UserId",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "NotificationMethod",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2022-09-17T02:48:57.773000+08:00",
        "ProvisionedThroughput": {
            "LastIncreaseDateTime": "1970-01-01T08:00:00+08:00",
            "LastDecreaseDateTime": "1970-01-01T08:00:00+08:00",
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 5,
            "WriteCapacityUnits": 5
        },
        "TableSizeBytes": 327,
        "ItemCount": 5,
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/NotificationSettings",
        "GlobalSecondaryIndexes": [
            {
                "IndexName": "Address-Index",
                "KeySchema": [
                    {
                        "AttributeName": "Address",
                        "KeyType": "HASH"
                    }
                ],
                "Projection": {
                    "ProjectionType": "ALL"
                },
                "IndexStatus": "CREATING",
                "Backfilling": false,
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": 10,
                    "WriteCapacityUnits": 5
                },
                "IndexArn": "arn:aws:dynamodb:ddblocal:000000000000:table/NotificationSettings/index/Address-Index"
            }
        ]
    }
}

建立好 Address 的 Index 後,就可以使用 Address 進行查詢:

> aws dynamodb query --endpoint-url http://localhost:1234 ^
    --table-name NotificationSettings ^
    --index-name Address-Index ^
    --key-condition-expression "Address = :addr" ^
    --expression-attribute-values "{\":addr\":{\"S\":\"new_betty456@mail.com\"}}"

得到結果:

{
    "Items": [
        {
            "Address": {
                "S": "new_betty456@mail.com"
            },
            "UserId": {
                "S": "Betty"
            },
            "NotificationMethod": {
                "S": "Email"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

上一篇
[Day 14] Key-Value Database: 以 DynamoDB 為例
下一篇
[Day 16] Key-Value Database: 以 DynamoDB 為例
系列文
NoSQL: Not Only SQL30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言