

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

# 在 DynamoDB 中查詢資料表
<a name="Query"></a>

您可以使用 Amazon DynamoDB 中的 `Query` API 操作，以根據主索引鍵值尋找項目。

您必須提供分割區索引鍵屬性的名稱，以及該屬性的單一值。`Query`​ 會傳回所有具有該分割區索引鍵值的項目。您可以選擇是否提供排序索引鍵屬性，使用比較運算子縮小搜尋結果。

如需如何使用 `Query` (例如請求語法、回應參數和其他範例)，請參閱《*Amazon DynamoDB API 參考*》中的[查詢](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)。

**Topics**
+ [DynamoDB 中查詢操作的索引鍵條件表達式](Query.KeyConditionExpressions.md)
+ [DynamoDB 中查詢操作的篩選條件表達式](Query.FilterExpression.md)
+ [在 DynamoDB 中將資料表查詢結果分頁](Query.Pagination.md)
+ [在 DynamoDB 中使用查詢操作的其他方面](Query.Other.md)

# DynamoDB 中查詢操作的索引鍵條件表達式
<a name="Query.KeyConditionExpressions"></a>

您可以在索引鍵條件表達式中使用任何屬性名稱，只要第一個字元為 `a-z` 或 `A-Z`，且其餘字元 (若有的話，從第二個字元開始) 為 `a-z`、`A-Z`，或 `0-9`。此外，屬性名稱不得為 DynamoDB 的保留字。(如需這些保留字的完整清單，請參閱「[DynamoDB 中的保留字](ReservedWords.md)」)。若屬性名稱不符合這些需求，您必須將表達式屬性名稱定義為預留位置。如需詳細資訊，請參閱[DynamoDB 中的表達式屬性名稱 (別名)](Expressions.ExpressionAttributeNames.md)。

針對具有給定分割區索引鍵值的項目，DynamoDB 會依照排序索引鍵值，將這些項目以排序後的順序存放在緊鄰位置。在 `Query` 操作中，DynamoDB 會以排序後的順序擷取項目，並使用 `KeyConditionExpression` 及任何存在的 `FilterExpression` 處理項目。只有在這個時候，`Query` 的結果才會傳回用戶端。

`Query` 操作永遠都會傳回一個結果集。如果找不到相符項目，表示結果集是空的。

`Query` 結果永遠都會根據排序索引鍵值進行排序。如果排序索引鍵的資料類型是 `Number`，即依數值順序傳回結果。否則，按 UTF-8 位元組順序傳回結果。根據預設，排序順序為遞增排序。若要反轉順序，請將 `ScanIndexForward` 參數設為 `false`。

單一 `Query` 操作最多可擷取 1 MB 的資料。這項限制會在任何 `FilterExpression` 或 `ProjectionExpression` 套用到結果之前套用。若回應中有 `LastEvaluatedKey` 且為非 Null，您即必須為結果集編製分頁 (請參閱[在 DynamoDB 中將資料表查詢結果分頁](Query.Pagination.md))。

## 索引鍵條件表達式範例
<a name="Query.KeyConditionExpressions-example"></a>

若要指定搜尋條件，請使用*索引鍵條件表達式* (判斷要從資料表或索引讀取之項目的字串)。

您必須將分割區索引鍵名稱及數值指定為相等條件。您無法在索引鍵條件表達式中使用非索引鍵屬性。

您可以選擇性為排序索引鍵提供第二個條件 (若有的話)。排序索引鍵條件必須使用下列其中一個比較運算子：
+ `a = b`：如果屬性 *a* 等於數值 *b*，則為 true
+ `a < b`：如果 *a* 小於 *b*，則為 true
+ `a <= b`：如果 *a* 小於或等於 *b*，則為 true
+ `a > b`：如果 *a* 大於 *b*，則為 true
+ `a >= b`：如果 *a* 大於或等於 *b*，則為 true
+ `a BETWEEN b AND c`：如果 *a* 大於或等於 *b* 且小於或等於 *c*，則為 true。

同樣支援下列函數：
+ `begins_with (a, substr)`：如果屬性 `a` 的值開頭為特定子字串，則為 true。

下列 AWS Command Line Interface (AWS CLI) 範例示範如何使用金鑰條件表達式。這些表達式會使用預留位置 (例如 `:name` 和 `:sub`)，而非實際的值。如需更多詳細資訊，請參閱 [DynamoDB 中的表達式屬性名稱 (別名)](Expressions.ExpressionAttributeNames.md) 及 [在 DynamoDB 中使用表達式屬性值](Expressions.ExpressionAttributeValues.md)。

**Example**  
查詢 `Thread` 表是否有特定的 `ForumName` (分割區索引鍵)。查詢會讀取所有具有該 `ForumName` 值的項目，因為 `KeyConditionExpression` 中不包含排序索引鍵 (`Subject`)。  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name" \
    --expression-attribute-values  '{":name":{"S":"Amazon DynamoDB"}}'
```

**Example**  
查詢 `Thread` 表是否有特定的 `ForumName` (分割區索引鍵)，但這次僅傳回具有指定 `Subject` (排序索引鍵) 的項目。  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name and Subject = :sub" \
    --expression-attribute-values  file://values.json
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":name":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"}
}
```

**Example**  
查詢 `Reply` 表是否有特定的 `Id` (分割區索引鍵)，但只傳回以特定字元開頭的 `ReplyDateTime` (排序索引鍵) 項目。  

```
aws dynamodb query \
    --table-name Reply \
    --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
    --expression-attribute-values  file://values.json
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
    ":dt":{"S":"2015-09"}
}
```

# DynamoDB 中查詢操作的篩選條件表達式
<a name="Query.FilterExpression"></a>

若您需要更精確的 `Query` 結果，您可以選擇性的提供篩選條件表達式。*篩選條件表達式*會判斷要傳回 `Query` 結果中的哪些項目。所有其他結果皆會捨棄。

篩選條件表達式會在 `Query` 完成之後，並在傳回結果之前套用。因此，無論是否有篩選條件表達式，`Query` 都會使用相同數量的讀取容量。

`Query` 操作最多可擷取 1 MB 的資料。系統會先套用這項限制，再評估篩選條件表達式。

篩選條件表達式無法包含分割區索引鍵或排序索引鍵屬性。您必須在索引鍵條件表達式中指定這些屬性，而非篩選條件表達式。

篩選條件表達式的語法和索引鍵條件表達式的語法類似。篩選條件表達式可以使用與索引鍵條件表達式相同的比較子、函數和邏輯運算子。此外，篩選條件表達式可以使用不等於運算子 (`<>`)、`OR` 運算子、`CONTAINS` 運算子、`IN` 運算子、`BEGINS_WITH` 運算子、`BETWEEN` 運算子、`EXISTS` 運算子和 `SIZE` 運算子。如需詳細資訊，請參閱[DynamoDB 中查詢操作的索引鍵條件表達式](Query.KeyConditionExpressions.md)及[篩選條件和條件表達式的語法](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Syntax)。

**Example**  
下列 AWS CLI 範例會查詢特定 `ForumName`（分割區索引鍵） 和 `Subject`（排序索引鍵） 的`Thread`資料表。在找到的項目中，只會傳回最受歡迎的討論主題：換句話說，只會傳回具有超過一定 `Views` 數量的主題。  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :fn and Subject begins_with :sub" \
    --filter-expression "#v >= :num" \
    --expression-attribute-names '{"#v": "Views"}' \
    --expression-attribute-values file://values.json
```
`--expression-attribute-values` 的引數會存放在 `values.json` 檔案中。  

```
{
    ":fn":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"},
    ":num":{"N":"3"}
}
```
請注意，`Views` 為 DynamoDB 中的保留字 (請參閱 [DynamoDB 中的保留字](ReservedWords.md))，所以此範例會使用 `#v` 作為預留位置。如需詳細資訊，請參閱[DynamoDB 中的表達式屬性名稱 (別名)](Expressions.ExpressionAttributeNames.md)。

**注意**  
篩選條件表達式會從 `Query` 結果集中移除項目。若可能的話，請避免在預期會擷取大量項目，但又需要捨棄它們大部分的情況下，使用 `Query`。

# 在 DynamoDB 中將資料表查詢結果分頁
<a name="Query.Pagination"></a>

DynamoDB 會對 `Query` 操作的結果進行*分頁*。透過編製分頁，`Query` 結果會分成數個大小為 1 MB (或更小) 的資料「頁」。應用程式可以處理結果的第一頁、第二頁，以此類推。

單一 `Query` 只會傳回符合 1 MB 大小限制的結果集。為判斷是否有更多結果，並且一次擷取一頁結果，應用程式應執行下列作業：

1. 檢查低層級 `Query` 結果：
   + 若結果包含 `LastEvaluatedKey` 元素且為非空值，請接著進行步驟 2。
   + 若結果中「沒有」**`LastEvaluatedKey`，就表示再也沒有要擷取的項目。

1. 使用相同的 `KeyConditionExpression` 建構 `Query`。但這一次採用步驟 1 的 `LastEvaluatedKey` 值，並用它做為新 `Query` 要求的 `ExclusiveStartKey` 參數。

1. 執行新的 `Query` 請求。

1. 前往步驟 1。

換句話說，`LastEvaluatedKey` 回應的 `Query` 應做為下一個 `ExclusiveStartKey` 請求的 `Query` 使用。若 `LastEvaluatedKey` 回應中沒有 `Query` 元素，表示您已擷取到結果的最終頁。如果 `LastEvaluatedKey` 不是空的，則不一定意味著結果集中有更多資料。檢查 `LastEvaluatedKey` 是否為空，是確定您是否已到達結果集末頁的唯一方式。

您可以使用 AWS CLI 來檢視此行為。會重複 AWS CLI 傳送低階`Query`請求至 DynamoDB，直到結果`LastEvaluatedKey`中不再出現 為止。請考慮下列從特定年份擷取電影標題 AWS CLI 的範例。

```
aws dynamodb query --table-name Movies \
    --projection-expression "title" \
    --key-condition-expression "#y = :yyyy" \
    --expression-attribute-names '{"#y":"year"}' \
    --expression-attribute-values '{":yyyy":{"N":"1993"}}' \
    --page-size 5 \
    --debug
```

通常， 會自動 AWS CLI 處理分頁。不過，在此範例中， AWS CLI `--page-size` 參數會限制每頁的項目數量。`--debug` 參數會列印請求及回應的下層資訊。

如果您執行此範例，DynamoDB 的第一個回應會類似以下內容。

```
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":5,"Items":[{"title":{"S":"A Bronx Tale"}},
{"title":{"S":"A Perfect World"}},{"title":{"S":"Addams Family Values"}},
{"title":{"S":"Alive"}},{"title":{"S":"Benny & Joon"}}],
"LastEvaluatedKey":{"year":{"N":"1993"},"title":{"S":"Benny & Joon"}},
"ScannedCount":5}'
```

回應中的 `LastEvaluatedKey` 會指出並未擷取所有項目。 AWS CLI 然後， 向 DynamoDB 發出另一個`Query`請求。此請求和回應模式會持續到最終回應出現為止。

```
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"What\'s Eating Gilbert Grape"}}],"ScannedCount":1}'
```

若沒有 `LastEvaluatedKey`，就表示已不再有要擷取的項目。

**注意**  
 AWS SDKs 會處理低階 DynamoDB 回應 （包括是否存在 `LastEvaluatedKey`)，並提供用於分頁`Query`結果的各種抽象概念。例如，適用於 Java 的開發套件文件介面會提供 `java.util.Iterator` 支援，讓您可一次處理一個結果。  
如需各種程式設計語言的程式碼範例，請參閱《[Amazon DynamoDB 入門指南](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/)》和所需語言的 AWS 軟體開發套件文件。

您還可以透過限制結果集的項目數 (使用 `Query` 操作的 `Limit` 參數) 來減少頁面大小。

如需使用 DynamoDB 進行查詢的詳細資訊，請參閱 [在 DynamoDB 中查詢資料表](Query.md)。

# 在 DynamoDB 中使用查詢操作的其他方面
<a name="Query.Other"></a>

本節涵蓋 DynamoDB 查詢操作的其他層面，包括限制結果大小、計算掃描項目與傳回項目、監控讀取容量耗用量，以及控制讀取一致性。

## 限制結果集的項目數
<a name="Query.Limit"></a>

您可以使用 `Query` 操作來限制其讀取的項目數。若要執行此作業，請將 `Limit` 參數設為您希望的最大項目數。

例如，假設您 `Query` 一份資料表，將 `Limit` 值設為 `6` 且不使用篩選條件表達式。`Query` 結果會包含資料表中符合請求索引鍵條件表達式的前六個項目。

現在假設您在 `Query` 中新增一個篩選條件表達式。在此情況下，DynamoDB 最多可讀取六個項目，然後只傳回符合篩選條件表達式的項目。最後的 `Query` 結果包含六個或更少的項目，即使有更多項目符合篩選條件表達式 (如果 DynamoDB 持續讀取更多項目)。

## 計算結果中的項目
<a name="Query.Count"></a>

除了符合您條件的項目之外，`Query` 回應還包含了下列元素：
+ `ScannedCount`：套用篩選條件表達式 (若有) *前*符合索引鍵條件表達式的項目數。
+ `Count`：套用篩選條件表達式 (若有) *後*剩餘的項目數。

**注意**  
若不使用篩選條件表達式，`ScannedCount` 和 `Count` 就會有相同的值。

若 `Query` 結果集的大小大於 1 MB，則 `ScannedCount` 和 `Count` 僅代表總項目的部分計數。您需要執行多項 `Query` 操作，才能擷取所有的結果 (請參閱[在 DynamoDB 中將資料表查詢結果分頁](Query.Pagination.md))。

每個 `Query` 回應都包含經該特定 `Query` 請求處理過的項目 `ScannedCount` 和 `Count`。若要取得所有 `Query` 請求的總計，您可以為 `ScannedCount` 及 `Count` 記錄流水帳。

## 查詢使用的容量單位
<a name="Query.CapacityUnits"></a>

您可以 `Query` 任何資料表或次要索引，只要您提供分割索引鍵屬性的名稱以及該屬性的單一值即可。`Query` 會傳回具有該分割區索引鍵值的所有項目。您可以選擇是否提供排序索引鍵屬性，並使用比較運算子縮小搜尋結果。`Query`API​ 操作會使用讀取容量單位，如下所示。


****  

| 若您對下列進行 `Query` | DynamoDB 使用的讀取容量單位就會來自... | 
| --- | --- | 
| 資料表 | 該資料表的佈建讀取容量。 | 
| 全域次要索引 | 該索引的佈建讀取容量。 | 
| 本機次要索引 | 該基礎資料表的佈建讀取容量。 | 

根據預設，`Query` 操作不會傳回任何使用之讀取容量的相關資料。但您可以在 `ReturnConsumedCapacity` 請求中指定 `Query` 參數，來取得這項資訊。下列為 `ReturnConsumedCapacity` 的有效設定：
+ `NONE`：不會傳回耗用的容量資料。(此為預設值)。
+ `TOTAL`：回應包括耗用的讀取容量單位總數。
+ `INDEXES`：回應顯示耗用的讀取容量單位總數，以及每個資料表和存取之索引的耗用容量。

DynamoDB 會根據項目的數量以及大小 (而不是根據傳回給應用程式的資料量) 計算耗用的讀取容量單位數。因此，無論您請求所有屬性 (預設行為) 或只請求部分屬性 (使用投影表達式)，使用的容量單位數都相同。無論您是否使用篩選條件表達式，此數量都相同。`Query` 會耗用最小讀取容量單位，每秒執行一個高度一致性讀取；或者針對最大 4 KB 的項目，每秒執行兩個最終一致讀取。如果您需要讀取大於 4KB 的項目，DynamoDB 需要額外的讀取請求單位。空白資料表和具有稀疏分割區索引鍵數量的極龐大資料表，可能會看到超出查詢資料量的額外 RCU 收費。這涵蓋了處理 `Query` 請求的成本，即使沒有資料也一樣。

## 查詢的讀取一致性
<a name="Query.ReadConsistency"></a>

根據預設，`Query` 操作會執行最終一致讀取。這表示 `Query` 的結果可能不會反映最近完成之 `PutItem` 或 `UpdateItem` 操作所造成的變更。如需詳細資訊，請參閱[DynamoDB 讀取一致性](HowItWorks.ReadConsistency.md)。

若您需要高度一致性讀取，請在 `ConsistentRead` 請求中將 `true` 參數設為 `Query`。