扱える型
スカラー型
- 数値
- BigDecimal型で返されるため、必要に応じて
to_i
メソッドでInteger型に直す
- 文字列
- バイナリ
- ブール
null
ドキュメント型
セット型
ユニークで順序の保証されないリスト
データ取得
-
scan
- テーブルのすべての項目を取得する
- 全てのカラムを条件に使用可能
-
query
- パーティションキーの指定が必須
- ソートキーを指定しない場合、条件に合致する全てのレコードが返される
-
get_item
filter_expression
- 取得したデータに対し、結果セットを返す前に返すレコードを絞り込む条件を記述する
- 例:
filter_expression: 'Age > :age',
※ :age
は expression_attribute_values
で指定する。
-
scan
, query
で指定可能
- ただしフィルタ式の適用は結果取得後のため、フィルタ式の有無にかかわらずキャパシティーの消費量は同じ
projection_expression
- 取得するカラムをカンマ区切りで指定する
- 例:
projection_expression: 'Name, Age',
-
scan
, query
, get_item
で指定可能
example_table1
example_table2
K1(パーティションキー) |
K2(ソートキー) |
Code |
1 |
1 |
'1_1' |
1 |
2 |
'1_2' |
2 |
1 |
'2_1' |
スキャン
- 主キーやパーティションキー・ソートキー以外を条件に指定可能
-
filter_expression
で条件を指定する。指定しない場合全件を取得する
client.scan({
table_name: 'example_table1',
filter_expression: 'Age >= :age',
expression_attribute_values: {
':age' => 20,
}
})
結果
ページング
- スキャンでは、1回の実行で最大1MBのデータを取得できる
- 1MBを超えるデータを取得する場合、複数回のスキャン実行が必要
- 続きがある場合、実行結果に
last_evaluated_key
というパラメータが含まれている。同じ条件でスキャンを実行する際に、exclusive_start_key
に last_evaluated_key
の値を指定しておくことで、続きの結果を取得できる。
scan_condition = {
table_name: 'table_name',
filter_expression: 'Age = :threshold',
expression_attribute_values: {
':threshold' => 20,
},
}
loop do
result = client.scan(scan_condition)
puts "items: #{result[:items]}"
last_evaluated_key = result[:last_evaluated_key]
puts "last_evaluated_key: #{last_evaluated_key}"
# `last_evaluated_key` がnilの場合は次の結果が無いので終了する
break if last_evaluated_key.nil?
# `exclusive_start_key` に last_evaluated_key の値を指定する
scan_condition[:exclusive_start_key] = last_evaluated_key
end
クエリ
-
query
メソッドは主キーついての条件が必須
- パーティションキーのみの場合は必然的に最大1件になる
- パーティションキー+ソートキーの場合、パーティションキーのみ条件に指定すると複数件の結果が返る
-
filter_expression
にパーティションキー・ソートキーを含めることはできない。key_condition_expression
で指定する。
パーティションキーのみ
client.query({
table_name: 'example_table1',
key_condition_expression: 'Id = :id',
expression_attribute_values: {
':id' => 1
}
})
結果
パーティションキー+ソートキー
client.query({
table_name: 'example_table2',
key_condition_expression: 'K1 = :v1 AND K2 = :v2',
expression_attribute_values: {
':v1' => 1,
':v2' => 1,
}
})
結果
パーティションキー+ソートキー(パーティションキーのみ指定)
client.query({
table_name: 'example_table2',
key_condition_expression: 'K1 = :v1',
expression_attribute_values: {
':v1' => 1,
}
})
結果
K1 |
K2 |
code |
1 |
1 |
'1_1' |
1 |
2 |
'1_2' |
get_item
query
や scan
と異なり、1件のみを取得する
result = client.get_item({
table_name: 'example_table1',
key: {
id: 1,
},
})
puts result[:item]
# => {"Id"=>0.1e1, "Name"=>"Name1", "Age"=>0.21e2, "Email"=>"one@example.com"}
項目の更新
SET
- 値の更新(上書き)を行う
- 存在しないカラムを指定した場合、新たにカラムが追加されそこに値がセットされる
値の更新
client.update_item({
table_name: 'example_table3',
key: {
Id: 3,
},
update_expression: 'SET Val = :new_val',
expression_attribute_values: {
':new_val' => 103,
}
})
結果
データの追加
client.update_item({
table_name: 'example_table3',
key: {
Id: 4, # 存在しない値を指定
},
update_expression: 'SET Val = :val',
expression_attribute_values: {
':val' => 104,
}
})
結果
Id |
Val |
1 |
101 |
2 |
102 |
3 |
103 |
4 |
104 |
カラムの追加
client.update_item({
table_name: 'example_table3',
key: {
Id: 1,
},
update_expression: 'SET Val2 = :val', # 存在しないカラムを指定
expression_attribute_values: {
':val' => 1001,
}
})
結果
Id |
Val |
Val2 |
1 |
101 |
1001 |
2 |
102 |
|
3 |
103 |
|
4 |
104 |
|
複数の更新
例:値の更新とカラム追加を同時に行う
client.update_item({
table_name: 'example_table3',
key: {
Id: 2,
},
update_expression: 'SET Val = :val, Val3 = :val3', # カンマ区切りで式を並べる
expression_attribute_values: {
':val' => 202,
':val3' => 10002,
}
})
結果
Id |
Val |
Val2 |
Val3 |
1 |
101 |
1001 |
|
2 |
202 |
|
10002 |
3 |
103 |
|
|
4 |
104 |
|
|
ADD
- 値の追加を行う
- 数値(Integer)型、リスト型、セット型で挙動が異なる
- SETと同じく、存在しないカラムを指定した場合、カラムを作成し値をセットする
各型のカラムを用意
client.update_item({
table_name: 'example_table4',
key: {
Id: 1,
},
# カンマ区切りで複数カラムに操作
update_expression: 'ADD IntType :int, IntSetType :intset, StrSetType :strset, BinSetType :binset',
expression_attribute_values: {
':int' => 1, # 数値型
':intset' => Set.new([1,2]), # 数値セット型
':strset' => Set.new(['one', 'two']), # 文字列セット型
':binset' => Set.new([StringIO.new('abc123')]), # バイナリセット型
}
})
結果
Id |
IntType |
IntSetType |
StrSetType |
BinSetType |
1 |
1 |
{2, 1} |
{"one", "two"} |
{ YWJjMTIz } |
数値
- 数値型での
ADD
は単に足し算を行う
- マイナスの値を指定すれば引き算される(マイナスを足す)
client.update_item({
table_name: 'example_table4',
key: {
Id: 1,
},
update_expression: 'ADD IntType :int',
expression_attribute_values: {
':int' => 100, # 1 + 100
}
})
結果
Id |
IntType |
IntSetType |
StrSetType |
BinSetType |
1 |
101 |
{2, 1} |
{"one", "two"} |
{ YWJjMTIz } |
セット型
セット型の ADD
は、互いの要素を合わせたものから重複を取り除いたセット型になる
client.update_item({
table_name: 'example_table4',
key: {
Id: 1,
},
update_expression: 'ADD IntSetType :intset, StrSetType :strset, BinSetType :binset',
expression_attribute_values: {
':intset' => Set.new([2,3]), # 2は重複
':strset' => Set.new(['two', 'three']), # 'two'は重複
':binset' => Set.new([StringIO.new('abc123'), StringIO.new('xyz999')]), # StringIO.new('abc123')は重複
}
})
結果
Id |
IntType |
IntSetType |
StrSetType |
BinSetType |
1 |
101 |
{3, 2, 1} |
{'three', 'two', 'one'} |
{ YWJjMTIz, eHl6OTk5 } |
配列で要素の追加をしたい場合、ADDではなくSETを用いる
-
list_append(list1, list2)
Id |
ListType |
1 |
[{"N": "1"}, {"N": "2"}] |
client.update_item({
table_name: 'example_table5',
key: {
Id: 1,
},
update_expression: 'SET AnyList = list_append(AnyList, :l)',
expression_attribute_values: {
':l' => [2, '3'], # 注:配列を渡す
},
})
結果
Id |
ListType |
1 |
[{"N": "1"}, {"N": "2"}, {"N": "2"}, {"S": "3"}] |
ちなみに AnyList
というカラムがまだない場合や、存在しないキー(レコードの作成を期待)を指定するとエラーが発生する
The provided expression refers to an attribute that does not exist in the item (Aws::DynamoDB::Errors::ValidationException)
カラムが存在しない場合の代わりの値を渡すことで解決することができる
-
if_not_exists(Column, default)
- 第一引数に指定したカラムが存在する場合、第一引数の値を返す
- 第一引数に指定したカラムが存在しない場合、第二引数の値を返す
client.update_item({
table_name: 'example_table5',
key: {
Id: 1,
},
update_expression: 'SET AnyList2 = list_append(if_not_exists(AnyList2, :empty), :l)',
expression_attribute_values: {
':l' => [1, '2', 3],
':empty' => [], # もちろん空でない配列でもOK
}
})
REMOVE
すべての型
- あるレコードの指定したカラムの値を空にする
- DynamoDBの性質上、この操作によりすべてのレコードがそのカラムに値を持たなくなった場合、カラム自体も削除される
- 存在しないカラムを指定してもエラーにはならない
Id |
Column1 |
Column2 |
Column3 |
Column4 |
1 |
col1 |
col2 |
col3 |
|
2 |
col1 |
col2 |
|
col4 |
client.update_item({
table_name: 'example_table6',
key: {
Id: 1,
},
update_expression: 'REMOVE Column2, Column3, Column4, Column5', # カンマ区切りで複数指定可能
}
結果
Id |
Column1 |
Column2 |
Column4 |
1 |
col1 |
|
|
2 |
col1 |
col2 |
col4 |
リスト型
-
REMOVE AnyList[0]
のように、REMOVE
+ インデックスで要素指定を行うことで、リストの任意の位置の要素を削除できる
Id |
AnyList |
1 |
[{"N": "1"}, {"N": "2"}, {"S": "3"}] |
client.update_item({
table_name: 'example_table5',
key: {
Id: 1,
},
update_expression: 'REMOVE AnyList[1]',
}
結果
Id |
AnyList |
1 |
[{"N": "1"}, {"S": "3"}] |
DELETE
Id |
IntSet1 |
IntSet2 |
1 |
{1,2,3} |
{4,5} |
client.update_item({
table_name: 'example_table6',
key: {
Id: 1,
},
update_expression: 'DELETE IntSet1 :s1, IntSet2 :s2',
expression_attribute_values: {
':s1' => Set.new([1,4]),
':s2' => Set.new([4,5]),
},
})
結果
条件
- 更新する際に条件を設けることも可能
- 条件を満たさない場合更新は行われずエラーが返る
client.update_item({
table_name: 'example_table7',
key: {
id: 1,
},
update_expression: 'SET Val = Val + :v',
condition_expression: 'Val > :threshold',
expression_attribute_values: {
':threshold' => 100,
':v' => 100,
}
})
# => The conditional request failed (Aws::DynamoDB::Errors::ConditionalCheckFailedException)
client.update_item({
table_name: 'example_table7',
key: {
id: 1,
},
update_expression: 'SET Val = Val + :v',
condition_expression: 'Val > :threshold',
expression_attribute_values: {
':threshold' => 99,
':v' => 100,
}
})
結果
項目の削除
client.delete_item({
table_name: 'example_table8',
key: {
Id: 2,
},
})
結果
更新と同様条件を設定することも可能
client.delete_item({
table_name: 'example_table8',
key: {
id: 1,
},
condition_expression: 'Val > :twenty',
expression_attribute_values: {
':twenty' => 20
}
})
条件(condition_expression
)により削除できなかった場合はエラーが返るので注意
The conditional request failed (Aws::DynamoDB::Errors::ConditionalCheckFailedException)
戻り値
- 更新や削除を実行する際、戻り値を指定することができる
-
return-values
に文字列で指定する
キー |
説明 |
ALL_OLD |
更新前のすべての項目(カラム) |
ALL_NEW |
更新後のすべての項目 |
UPDATED_OLD |
更新された項目のみ、以前の値 |
UPDATED_NEW |
更新された項目のみ、更新後の値 |
ALL_OLD
以外は update_item
でのみ指定可能
Id |
Val1 |
Val2 |
Val3 |
1 |
11 |
21 |
31 |
2 |
12 |
22 |
32 |
3 |
13 |
23 |
33 |
return_values = client.update_item({
table_name: 'example_table9',
key: {
id: 1,
},
update_expression: 'SET Val1 = :zero',
expression_attribute_values: {
':zero' => 0,
},
return_values: 'ALL_OLD'
})
puts return_values[:attributes]
# => {"Id"=>1, "Val1"=>0.11e2, "Val2"=>0.21e2, "Val3"=>0.31e2}
return_values = client.update_item({
table_name: 'example_table9',
key: {
id: 2,
},
update_expression: 'SET Val1 = :zero, Val2 = :zero',
expression_attribute_values: {
':zero' => 0,
},
return_values: 'UPDATED_NEW'
})
puts return_values[:attributes]
# => {"Val1"=>0.0, "Val2"=>0.0}
expression_attribute_names
-
update_expression
等にカラム名を記述する際、プレースホルダーを使用しなければならない場合がある。
- 数字始まり
- スペースを含む
- 特殊文字を含む
- 予約語である
- プレースホルダーは
#
で始める必要がある
Id |
Col umn |
Value |
1 |
"スペースを含むカラム名" |
"予約語のカラム名" |
client.update_item({
table_name: 'example_table3',
key: {
Id: 1,
},
update_expression: 'SET #Col1 = :v1, #Col2 = :v2',
expression_attribute_names: {
'#Col1' => 'Col umn',
'#Col2' => 'Value',
},
expression_attribute_values: {
':v1' => 'aaa',
':v2' => 'bbb',
}
})