Queryで使用するdynamodb/api.goに書かれたQueryInputは以下の通りです。
以下に、スペースを全て詰めた表を提供します。
フィールド名 | タイプ | 説明 | デフォルト値 | SQLでの類似概念 |
---|---|---|---|---|
*ConsistentRead | *bool |
読み取りの整合性モデルを決定。true の場合、強い整合性の読み取りを使用。グローバルセカンダリインデックスではサポートされていない。 |
false |
SELECT with FOR UPDATE
|
ExclusiveStartKey | map[string]*AttributeValue |
評価を開始する最初のアイテムのプライマリキー。 | nil |
OFFSET |
*ExpressionAttributeNames | map[string]*string |
式内の属性名の代用トークン。 | nil |
AS (エイリアス) |
*ExpressionAttributeValues | map[string]*AttributeValue |
式内の属性値の代用トークン。 | nil |
プレースホルダー (? ) |
*FilterExpression | *string |
Query 操作後に適用される条件。 |
nil |
WHERE (追加フィルター) |
IndexName | *string |
クエリを実行するインデックスの名前。 | nil |
INDEX (インデックス指定) |
*KeyConditionExpression | *string |
アイテムを取得するためのキー条件を指定する式。 | nil |
WHERE (主キー条件) |
*Limit | *int64 |
評価する最大アイテム数。 | nil |
LIMIT |
*ProjectionExpression | *string |
取得する属性を指定する式。 | nil |
SELECT |
ReturnConsumedCapacity | *string |
レスポンスに含まれるスループット消費情報のレベルを決定。 | NONE |
なし |
ScanIndexForward | *bool |
インデックスの走査順序を決定。true の場合、昇順。 |
true |
ORDER BY |
*Select | *string |
結果に含まれる属性を決定。 | ALL_ATTRIBUTES |
SELECT |
*TableName | *string |
アイテムを含むテーブルの名前。必須フィールド。 | nil |
FROM |
定義にAttributesToGet・ConditionalOperator・QueryFilter・KeyConditionsが含まれていたが、これらはレガシーパラメータのため使用されない模様。
表記方法
TableName
これはそのままの意味でテーブルの名前を指定します。
input := &dynamodb.QueryInput{
TableName: aws.String("TableName"),
}
KeyConditionExpression&ExpressionAttributeValues
アイテムを取得するためのキー条件を指定する式で、SQLのWHERE句みたいなものです。
ExpressionAttributevalues
で具体的な値を指定します。
KeyCondtionExpressionValuesで使用できる条件は以下の通りです。
条件 | 説明 |
---|---|
a = b | true if the attribute a is equal to the value b |
a < b | true if a is less than b |
a <= b | true if a is less than or equal to b |
a > b | true if a is greater than b |
a >= b | true if a is greater than or equal to b |
a BETWEEN b AND c | true if a is greater than or equal to b, and less than or equal to c |
begins_with (a, substr) | true if the value of attribute a begins with a particular substring |
これらの条件をKeyConditionExpression
で指定し:hoge
で書かれた値をExpressionAttributeValues
でセットします。
例えば以下のようなデータがあるとします。
PrimaryKey (OrderID) | SortKey (OrderDate) | CustomerName | Amount |
---|---|---|---|
1001 | 2023-01-01 | Alice | 50 |
1001 | 2023-01-02 | Bob | 30 |
1002 | 2023-01-01 | Carol | 70 |
1002 | 2023-01-03 | Dave | 40 |
1003 | 2023-01-02 | Eve | 20 |
このデータに対して以下のQueryを投げると、
input := &dynamodb.QueryInput{
TableName: aws.String("Orders"),
KeyConditionExpression: aws.String("OrderID = :pk AND OrderDate BETWEEN :start AND :end"),
ExpressionAttributeValues: map[string]types.AttributeValue{
":pk": &types.AttributeValueMemberS{Value: aws.String("1002")},
":start": &types.AttributeValueMemberS{Value: aws.String("2023-01-01")},
":end": &types.AttributeValueMemberS{Value: aws.String("2023-01-03")},
},
}
以下のようなデータを取得することができます。
これはOrders
テーブルからPKが1002
で、2023-01-01
から2023-01-03
のデータを取得するという意味だからです。
OrderID | OrderDate | CustomerName | Amount |
---|---|---|---|
1002 | 2023-01-01 | Carol | 70 |
1002 | 2023-01-03 | Dave | 40 |
Limit
評価する最大アイテム数。
input := &dynamodb.QueryInput{
TableName: aws.String("YourTableName"),
Limit: aws.Int64(10),
}
指定した件数取得する設定です。
ただ、この設定はDynamoDBでは思った挙動にならないこともあるようで、使い方が意外と難しい模様です。
input := &dynamodb.QueryInput{
TableName: aws.String("TableName"),
Limit: aws.Int64(10),
}
例えば、以下の記事にあるように後述するFilterExpression
を使用すると、これはQuery操作後に適用される条件のため10件取得と設定しても、10件取得したデータに対してFilterをかけてしまい思った挙動にならないようです。
https://www.denzow.me/entry/2018/02/04/130419
FilterExpression
Limitの説明でも出てきましたが、Query操作後に適用される条件です。
ExpressionAttributevalues
で具体的な値を指定します。
上述した通り、データ取得後にFilterExpressionが実行されるため、その点には注意が必要です。
input := &dynamodb.ScanInput{
TableName: aws.String("Orders"),
FilterExpression: aws.String("Amount <= :amount"),
ExpressionAttributeValues: map[string]types.AttributeValue{
":amount": &types.AttributeValueMemberN{Value: "40"},
},
}
ProjectionExpression
取得したい特定の属性を指定するために使用します。
例えば、以下のようなテーブルがあるとしましょう。
PrimaryKey (OrderID) | SortKey (OrderDate) | CustomerName | Amount |
---|---|---|---|
1001 | 2023-01-01 | Alice | 50 |
1001 | 2023-01-02 | Bob | 30 |
1002 | 2023-01-01 | Carol | 70 |
1002 | 2023-01-03 | Dave | 40 |
1003 | 2023-01-02 | Eve | 20 |
ここで以下のqueryで設定すると、
input := &dynamodb.ScanInput{
TableName: aws.String("Orders"),
ProjectionExpression: aws.String("OrderID, Amount"),
}
以下のように指定した属性のみ取得することが可能となります。
OrderID | Amount |
---|---|
1001 | 50 |
1001 | 30 |
1002 | 70 |
1002 | 40 |
1003 | 20 |
SELECT
これは取得する属性を指定するという点でProjectionExpression
と非常に似ています。
そのため、SELECT
とProjectionExpression
を同時に使用することはできません。ただし、SelectがSPECIFIC_ATTRIBUTESの場合は例外です。(ただ、一緒に使う意味がないので実際に同時に使うことはなさそう。)
というよりおそらくProjectionExpression
はSELECT
のオプションの1つのよう(間違ってるかも。)
表でまとめると以下の通りとなります。
ただ、デフォルトで全ての属性を取得するのでALL_ATTRIBUTES
は使わないだろうし、SPECIFIC_ATTRIBUTES
もProjection Expression
だけ指定すればいいから特に指定する必要はなさそうだし、あまり使う機会がなさそう。
唯一使えそうなのはCOUNT
くらいかな?
オプション | 説明 | 利用ケース |
---|---|---|
ALL_ATTRIBUTES | 指定されたテーブルまたはインデックスの全てのアイテム属性を返す。 | 全ての属性を取得したい場合に使用。 |
ALL_PROJECTED_ATTRIBUTES | インデックスをクエリする場合にのみ使用可能。インデックスにプロジェクトされた全ての属性を取得。 | インデックスが全ての属性をプロジェクトするように設定されている場合に使用。 |
COUNT | 一致するアイテムの数を返す。実際のアイテムそのものではない。 | クエリの結果のアイテム数を知りたい場合に使用。 |
SPECIFIC_ATTRIBUTES | 特定の属性のみを返す。ProjectionExpression と組み合わせて使用。 |
特定の属性のみを取得したい場合に使用。 |
ProjectionExpression | 特定の属性を指定して取得する。 | 特定の属性のみを取得したい場合に使用。 |
例えば、以下のように設定すれば検索結果のデータではなく、検索件数を取得できる。
input := &dynamodb.QueryInput{
TableName: aws.String("Orders"),
KeyConditionExpression: aws.String("OrderID = :id"),
ExpressionAttributeValues: map[string]types.AttributeValue{
":id": &types.AttributeValueMemberS{Value: aws.String("1001")},
},
Select: types.SelectCount,
}
んー、でも結局これもQueryOutputのScannedCount
とCount
フィールドがあるからそれを使えばいいから結局SELECT
の使い道っていまいち分からない。。。😅
以下はQueryOutput
のメモです。
フィールド名 | 説明 |
---|---|
Items | クエリによって返されるアイテムのリスト。 |
Count | クエリによって返されたアイテムの数。 |
ScannedCount | フィルタリング前にスキャンされたアイテムの数。 |
LastEvaluatedKey | ページングが必要な場合に、次のページの開始キーを示す。 |
ExpressionAttributeNames
ExpressionAttributeNamesは、予約語や特殊文字を含む属性名のエイリアスを指定するために使用されます。SQLだとAS
と同じようなものです。同じようなものです。
例えば以下のテーブル属性のCustomerName
が予約語だったとしましょう。
PrimaryKey (OrderID) | SortKey (OrderDate) | CustomerName | Amount |
---|---|---|---|
1001 | 2023-01-01 | Alice | 50 |
1001 | 2023-01-02 | Bob | 30 |
1002 | 2023-01-01 | Carol | 70 |
1002 | 2023-01-03 | Dave | 40 |
1003 | 2023-01-02 | Eve | 20 |
その場合、以下のように#hoge
と書くことでCustomerName
を使用することができます。
input := &dynamodb.ScanInput{
TableName: aws.String("Orders"),
ProjectionExpression: aws.String("OrderID, #n, Amount"),
ExpressionAttributeNames: map[string]string{
"#n": "CustomerName",
},
}
ConsistentRead
読み取りの整合性モデルを決定します。trueの場合、強い整合性の読み取りを使用。グローバルセカンダリインデックスではサポートされていません。
input := &dynamodb.QueryInput{
TableName: aws.String("YourTableName"),
ConsistentRead: aws.Bool(true),
}
まとめ
Queryで使用するオプションを今回は調べてまとめてみました。
頭が整理できてよかったです🙌