

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 監控 DynamoDB 中的裝置狀態更新
<a name="data-modeling-device-status"></a>

本使用案例將說明如何使用 DynamoDB 監控 DynamoDB 中的裝置狀態更新 (或裝置狀態變更)。

## 使用案例
<a name="data-modeling-schema-device-status-use-case"></a>

在 IoT 使用案例 (例如智慧工廠) 中，許多裝置需要由作業員監控，並定期將其狀態或日誌傳送至監控系統。當裝置發生問題時，裝置的狀態會從*正常*轉為*警告*。根據裝置中異常行為的嚴重性和類型，會有不同的日誌層級或狀態。然後，系統會指派作業員檢查裝置，並在需要時將問題呈報給主管。

此系統的典型存取模式包括：
+ 建立裝置的日誌項目
+ 取得特定裝置狀態的所有日誌，並顯示最新日誌
+ 取得兩個日期之間，給指定作業員的所有日誌
+ 取得呈報給指定主管的所有日誌
+ 取得呈報給指定主管，並包含特定裝置狀態的所有日誌
+ 取得呈報給指定主管，並包含特定日期之特定裝置狀態的所有日誌

## 實體關係圖
<a name="data-modeling-schema-device-status-erd"></a>

這是用於監控裝置狀態更新實體關係圖 (ERD)。

![\[裝置狀態更新的 ERD。其中顯示的實體：裝置和運算子。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-1-ERD.jpg)


## 存取模式
<a name="data-modeling-schema-device-status-access-patterns"></a>

須使用此存取模式監控裝置狀態更新。

1. `createLogEntryForSpecificDevice`

1. `getLogsForSpecificDevice`

1. `getWarningLogsForSpecificDevice`

1. `getLogsForOperatorBetweenTwoDates`

1. `getEscalatedLogsForSupervisor`

1. `getEscalatedLogsWithSpecificStatusForSupervisor`

1. `getEscalatedLogsWithSpecificStatusForSupervisorForDate`

## 架構設計演進
<a name="data-modeling-schema-device-status-design-evolution"></a>

**步驟 1：位址存取模式 1 (`createLogEntryForSpecificDevice`) 和 2 (`getLogsForSpecificDevice`)**

裝置追蹤系統的擴展單位為個別裝置。在這個系統中，`deviceID` 會唯一識別裝置，進一步讓 `deviceID` 成為分割區索引鍵的理想候選者。每個設備會定期向追蹤系統發送資訊 (例如每五分鐘左右)，而這類排序會依日期為邏輯排序準則，因此成為排序索引鍵。此使用案例中的範例資料看起來應會與以下內容相似：

![\[儲存多個裝置狀態的資料表。DeviceID 是主索引鍵，而狀態更新日期是排序索引鍵。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-2-Step1.png)


若要擷取特定裝置的日誌項目，可以使用分割區索引鍵 `DeviceID="d#12345"` 執行[查詢](Query.md)操作。

**步驟 2：位址存取模式 3 (`getWarningLogsForSpecificDevice`)**

由於 `State` 是非索引鍵屬性，必須使用[篩選條件表達式](Query.FilterExpression.md)，才可利用目前的結構描述處理存取模式 3。在 DynamoDB 中，使用索引鍵條件表達式讀取資料後，才會套用篩選條件表達式。例如若想針對 `d#12345` 擷取警告日誌，利用分割區索引鍵 `DeviceID="d#12345"` 進行的查詢操作會讀取上表中的四個項目，然後篩選掉非處於*警告*狀態的項目。這種方法無法有效地大規模進行。如果排除項目的比例較低或不常執行查詢，則篩選條件表達式是排除查詢項目的好方法。但是，我們可以持續改善資料表設計，以便更有效率地從資料表中擷取大量項目，並篩選掉大部分的項目。

若想改變存取模式的處理方法，可以透過[複合排序索引鍵](data-modeling-blocks.md#data-modeling-blocks-composite)。您可以從排序索引鍵已改為 `State#Date` 的 [DeviceStateLog\$13.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_3.json) 匯入範例資料。此排序索引鍵結合了 `State`、`#` 以及 `Date` 屬性。此範例中，`#` 用來作為分隔符。資料現在看起來會像這樣：

![\[使用複合排序索引鍵 State#Date 擷取的裝置 d#12345 狀態更新資料。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-3-Step2.png)


若僅想擷取裝置的警告日誌，可利用此結構描述更切合查詢。查詢的索引鍵條件使用分割區索引鍵 `DeviceID="d#12345"` 與排序索引鍵 `State#Date begins_with “WARNING”`。此查詢只會讀取三個與*警告*狀態相關的項目。

**步驟 3：位址存取模式 4 (`getLogsForOperatorBetweenTwoDates`)**

您可以匯入 [DeviceStateLog\$14.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_4.json)，其中 `Operator` 屬性已新增至具有範例資料的 `DeviceStateLog` 資料表。

![\[DeviceStateLog 資料表設計具有運算子屬性，可取得特定日期之間的運算子日誌。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-4-Step3.png)


由於 `Operator` 目前不是分割區索引鍵，因此無法根據以 `OperatorID` 為基礎的資料表執行直接鍵值對查詢。我們必須使用 `OperatorID` 上的全域次要索引，建立一個新的[項目集合](WorkingWithItemCollections.md)。存取模式必須根據日期進行查詢，因此日期是[全域次要索引 (GSI)](GSI.md) 的排序索引鍵屬性。這就是 GSI 現在的樣子：

![\[使用 OperatorID 和 Date 做為分割區索引鍵和排序索引鍵的 GSI 設計，以取得特定運算子的日誌。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-5-Step3.png)


針對存取模式 4 (`getLogsForOperatorBetweenTwoDates`)，您可以使用分割區索引鍵 `OperatorID=Liz` 查詢此 GSI，以及 `2020-04-11T05:58:00` 和 `2020-04-24T14:50:00` 之間的排序索引鍵 `Date`。

![\[使用 OperatorID 和 Date 查詢 GSI，以取得兩個日期之間的運算子日誌。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-6-GSI1_1.png)


**步驟 4：位址存取模式 5 (`getEscalatedLogsForSupervisor`)、6 (`getEscalatedLogsWithSpecificStatusForSupervisor`) 和 7 (`getEscalatedLogsWithSpecificStatusForSupervisorForDate`)**

我們可以利用[疏鬆索引](data-modeling-blocks.md#data-modeling-blocks-sparse-index)處理這些存取模式。

全域次要索引依預設是疏鬆的，因此只有基礎資料表中包含主索引鍵屬性的項目，才會實際出現在索引中。針對要建模的存取模式，這是另一種排除無關項目的方式。

您可以匯入 [DeviceStateLog\$16.json](https://github.com/aws-samples/amazon-dynamodb-design-patterns/blob/master/examples/device-state-log/json/DeviceStateLog_6.json)，其中 `EscalatedTo` 屬性已新增至具有範例資料的 `DeviceStateLog` 資料表。如前所述，並非所有日誌都會呈報給主管。

![\[具有 EscalatedTo 屬性的 GSI 設計，以取得主管的所有呈報日誌。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-7-Step4.png)


您現在可以建立分割區索引鍵為 `EscalatedTo`、排序索引鍵為 `State#Date` 的新 GSI。請注意，只有當項目同時具有 `EscalatedTo` 和 `State#Date` 屬性時，才會顯示在索引中。

![\[取得具有 EscalatedTo 和 State#Date 屬性等所有項目的 GSI 設計。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-8-Step4.png)


其餘的存取模式摘要如下：

    針對存取模式 5 (getEscalatedLogsForSupervisor)，您可以使用分割區索引鍵 EscalatedTo="Sara" 在呈報 GSI 上執行查詢。   針對存取模式 6 (getEscalatedLogsWithSpecificStatusForSupervisor)，您可以使用分割區索引鍵 EscalatedTo="Sara"，與排序索引鍵 State\$1Date begins\$1with “WARNING”，在呈報 GSI 上執行查詢。   針對存取模式 7 (getEscalatedLogsWithSpecificStatusForSupervisorForDate)，您可以使用分割區索引鍵 EscalatedTo="Sara"，與排序索引鍵 State\$1Date begins\$1with “WARNING4\$12020-04-27”，在呈報 GSI 上執行查詢。    

下表摘要整理了所有存取模式，以及結構描述設計處理這些模式的方式：


| 存取模式 | 基礎資料表/GSI/LSI | 作業 | 分割區索引鍵值 | 排序索引鍵值 | 其他條件/篩選條件 | 
| --- | --- | --- | --- | --- | --- | 
| createLogEntryForSpecificDevice | 基礎資料表 | PutItem | DeviceID=deviceId | State\$1Date=state\$1date |  | 
| getLogsForSpecificDevice | 基礎資料表 | Query | DeviceID=deviceId | State\$1Date begins\$1with "state1\$1" | ScanIndexForward = False | 
| getWarningLogsForSpecificDevice | 基礎資料表 | Query | DeviceID=deviceId | State\$1Date begins\$1with "WARNING" |  | 
| getLogsForOperatorBetweenTwoDates | GSI-1 | Query | Operator=operatorName | Date between date1 and date2 |  | 
| getEscalatedLogsForSupervisor | GSI-2 | Query | EscalatedTo=supervisorName |  |  | 
| getEscalatedLogsWithSpecificStatusForSupervisor | GSI-2 | Query | EscalatedTo=supervisorName | State\$1Date begins\$1with "state1\$1" |  | 
| getEscalatedLogsWithSpecificStatusForSupervisorForDate | GSI-2 | Query | EscalatedTo=supervisorName | State\$1Date begins\$1with "state1\$1date1" |  | 

## 最終結構描述
<a name="data-modeling-schema-device-status-final-schema"></a>

以下是最終結構描述設計。若要將此結構描述設計下載為 JSON 檔案，請參閱 GitHub 上的 [DynamoDB 範例](https://github.com/aws-samples/aws-dynamodb-examples/tree/master/schema_design/SchemaExamples)。

**基礎資料表**

![\[具有裝置狀態中繼資料的基礎資料表設計，例如 Device ID、State 和 Date。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-9-Table.png)


**GSI-1**

![\[GSI-1 設計。其中會顯示主索引鍵和屬性：DeviceID、State#Date 和 State。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-10-GSI1.png)


**GSI-2**

![\[GSI-2 設計。其中會顯示主索引鍵和屬性：DeviceID、Operator、Date 和 State。\]](http://docs.aws.amazon.com/zh_tw/amazondynamodb/latest/developerguide/images/DataModeling/DeviceStatus-11-GSI2.png)


## 使用 NoSQL Workbench 與此結構描述設計
<a name="data-modeling-schema-device-status-nosql"></a>

您可以將此最終結構描述匯入 [NoSQL Workbench](workbench.md)，這是為 DynamoDB 提供資料建模、資料視覺化，和查詢開發功能的視覺化工具，以進一步探索和編輯新專案。請依照下列步驟以開始使用：

1. 下載 NoSQL Workbench。如需詳細資訊，請參閱[下載 DynamoDB 專用 NoSQL Workbench](workbench.settingup.md)。

1. 下載上面列出的 JSON 結構描述檔案，該檔案已經是 NoSQL Workbench 模型格式。

1. 將 JSON 結構描述檔案匯入到 NoSQL Workbench。如需詳細資訊，請參閱[匯入現有的資料模型](workbench.Modeler.ImportExisting.md)。

1. 一旦您匯入到 NOSQL Workbench 後，便可以編輯資料模型。如需詳細資訊，請參閱[編輯現有的資料模型](workbench.Modeler.Edit.md)。