Authors: Ransom Richardson (ransom@ransomr.net).
An Erlang interface to Amazon's DynamoDB.
http://aws.amazon.com/archives/Amazon-DynamoDB/8498019230173117
erlcloUd_ddb implements the entire 20111205 API. erlcloud_ddb2 implements a newer version.
Method names match DynamoDB operations converted to
lower_case_with_underscores. The one exception is query, which is
an Erlang reserved word. The q
method implements Query.
Required parameters are passed as function arguments. In addition all methods take an options proplist argument which can be used to pass optional parameters. See function documentation for examples.
Table names, key names, attribute names and any other input strings except attribute values must be binary strings.
Attribute values may be either {Type, Value}
or Value
. If only
Value
is provided then the type is inferred. Lists (iolists are
handled) and binaries are assumed to be strings. The following are
equivalent: {s, <<"value">>}
, <<"value">>
, "value"
. Numbers
are assumed to be numbers. The following are equivalent: {n, 42}
,
42
. To specify the AWS binary or set types an explicit Type
must be provided. For example: {b, <<1,2,3>>}
or {ns,
[4,5,6]}
. Note that binary values will be base64 encoded and
decoded automatically.
Output is in the form of {ok, Value}
or {error, Reason}
. The
format of Value
is controlled by the out
option, which defaults
to simple
. The possible values are:
* simple
- The most interesting part of the output. For example
get_item
will return the item.
* record
- A record containing all the information from the
DynamoDB response. This is useful if you need more detailed
information than what is returned with simple
. For example, with
scan
and query
the record will contain the last evaluated key
which can be used to continue the operation.
* json
- The output from DynamoDB as processed by jsx:decode
but with no further manipulation. This would rarely be useful,
unless the DynamoDB API is updated to include data that is not yet
parsed correctly.
Items will be returned as a list of {Name, Value}
. In most cases
the output will have type information removed. For example:
[{<<"String Attribute">>, <<"value">>}, {<<"Number Attribute">>,
42}, {<<"BinaryAttribute">>, <<1,2,3>>}]
. The exception is for
output fields that are intended to be passed to a subsequent call,
such as unprocessed_keys
and last_evaluated_key
. Those will
contain typed attribute values so that they may be correctly passed
to subsequent calls.
DynamoDB errors are return in the form {error, {ErrorCode,
Message}}
where ErrorCode
and 'Message' are both binary
strings. List of error codes:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html. So
to handle conditional check failures, match {error,
{<<"ConditionalCheckFailedException">>, _}}
.
erlcloud_ddb_util
provides a higher level API that implements common
operations that may require multiple DynamoDB API calls.
erlcloud_ddb1
provides a lower level API that takes JSON terms as
defined by jsx
.
attr_name() = binary()
attr_type() = s | n | b | ss | ns | bs
batch_get_item_request_item() = {table_name(), [key(), ...], get_item_opts()} | {table_name(), [key(), ...]}
batch_get_item_request_items() = maybe_list(batch_get_item_request_item())
batch_get_item_return() = ddb_return(#ddb_batch_get_item{}, [erlcloud_ddb:out_item()])
batch_write_item_delete() = {delete, key()}
batch_write_item_put() = {put, in_item()}
batch_write_item_request() = batch_write_item_put() | batch_write_item_delete()
batch_write_item_request_item() = {table_name(), [batch_write_item_request()]}
batch_write_item_request_items() = maybe_list(batch_write_item_request_item())
batch_write_item_return() = ddb_return(#ddb_batch_write_item{}, #ddb_batch_write_item{})
boolean_opt(Name) = Name | {Name, boolean()}
comparison_op() = eq | ne | le | lt | ge | gt | not_null | null | contains | not_contains | begins_with | in | between
create_table_return() = ddb_return(#ddb_create_table{}, #ddb_table_description{})
ddb_opts() = [out_opt()]
ddb_return(Record, Simple) = {ok, jsx:json_term() | Record | Simple} | {error, term()}
delete_item_opt() = {expected, in_expected()} | {return_values, none | all_old} | out_opt()
delete_item_opts() = [delete_item_opt()]
delete_item_return() = ddb_return(#ddb_delete_item{}, out_item())
delete_table_return() = ddb_return(#ddb_delete_table{}, #ddb_table_description{})
describe_table_return() = ddb_return(#ddb_describe_table{}, #ddb_table{})
get_item_opt() = {attributes_to_get, [binary()]} | boolean_opt(consistent_read) | out_opt()
get_item_opts() = [get_item_opt()]
hash_key() = in_attr_value()
hash_range_key() = {hash_key(), range_key()}
in_attr() = {attr_name(), in_attr_value()}
in_attr_data() = in_attr_data_scalar() | in_attr_data_set()
in_attr_data_scalar() = iolist() | binary() | number()
in_attr_data_set() = [iolist() | binary()] | [number()]
in_attr_typed_value() = {attr_type(), in_attr_data()}
in_attr_value() = in_attr_data() | in_attr_typed_value()
in_expected() = maybe_list(in_expected_item())
in_expected_item() = {attr_name(), false | in_attr_value()}
in_item() = [in_attr()]
in_update() = {attr_name(), in_attr_value(), update_action()} | in_attr() | {attr_name(), delete}
in_updates() = maybe_list(in_update())
item_return() = ok_return(out_item())
key() = hash_key() | hash_range_key()
key_schema() = key_schema_value() | {key_schema_value(), key_schema_value()}
key_schema_value() = {attr_name(), attr_type()}
list_tables_opt() = {limit, pos_integer()} | {exclusive_start_table_name, binary()} | out_opt()
list_tables_opts() = [list_tables_opt()]
list_tables_return() = ddb_return(#ddb_list_tables{}, [table_name()])
maybe_list(T) = T | [T]
ok_return(T) = {ok, T} | {error, term()}
out_attr() = {attr_name(), out_attr_value()}
out_attr_value() = binary() | number() | [binary()] | [number()]
out_item() = [out_attr()]
out_opt() = {out, out_type()}
out_type() = json | record | simple
put_item_opt() = {expected, in_expected()} | {return_values, none | all_old} | out_opt()
put_item_opts() = [put_item_opt()]
put_item_return() = ddb_return(#ddb_put_item{}, out_item())
q_opt() = {attributes_to_get, [binary()]} | {limit, pos_integer()} | boolean_opt(consistent_read) | boolean_opt(count) | {range_key_condition, range_key_condition()} | boolean_opt(scan_index_forward) | {exclusive_start_key, key() | undefined} | out_opt()
q_opts() = [q_opt()]
q_return() = ddb_return(#ddb_q{}, [out_item()])
range_key() = in_attr_value()
range_key_condition() = {in_attr_value(), comparison_op()} | {{in_attr_value(), in_attr_value()}, between}
return_value() = none | all_old | updated_old | all_new | updated_new
scan_filter() = maybe_list(scan_filter_item())
scan_filter_item() = {attr_name(), [in_attr_value()], in} | {attr_name(), {in_attr_value(), in_attr_value()}, between} | {attr_name(), in_attr_value(), comparison_op()}
scan_opt() = {attributes_to_get, [binary()]} | {limit, pos_integer()} | boolean_opt(count) | {scan_filter, scan_filter()} | {exclusive_start_key, key()} | out_opt()
scan_opts() = [scan_opt()]
scan_return() = ddb_return(#ddb_scan{}, [out_item()])
table_name() = binary()
update_action() = put | add | delete
update_item_opt() = {expected, in_expected()} | {return_values, return_value()} | out_opt()
update_item_opts() = [update_item_opt()]
update_item_return() = ddb_return(#ddb_update_item{}, out_item())
update_table_return() = ddb_return(#ddb_update_table{}, #ddb_table_description{})
batch_get_item(RequestItems::batch_get_item_request_items()) -> batch_get_item_return()
batch_get_item(RequestItems::batch_get_item_request_items(), Opts::ddb_opts()) -> batch_get_item_return()
batch_get_item(RequestItems::batch_get_item_request_items(), Opts::ddb_opts(), Config::aws_config()) -> batch_get_item_return()
Get attributes "user" and "friends" from items with keys "Julie" and "Mingus" in table "comp2" and attributes "user" and "status" from three items in table "comp1".
{ok, Items} = erlcloud_ddb:batch_get_item(
[{<<"comp2">>, [<<"Julie">>,
<<"Mingus">>],
[{attributes_to_get, [<<"user">>, <<"friends">>]}]},
{<<"comp1">>, [{<<"Casey">>, 1319509152},
{<<"Dave">>, 1319509155},
{<<"Riley">>, 1319509158}],
[{attributes_to_get, [<<"user">>, <<"status">>]}]}])
batch_write_item(RequestItems::batch_write_item_request_items()) -> batch_write_item_return()
batch_write_item(RequestItems::batch_write_item_request_items(), Opts::ddb_opts()) -> batch_write_item_return()
batch_write_item(RequestItems::batch_write_item_request_items(), Opts::ddb_opts(), Config::aws_config()) -> batch_write_item_return()
Put and delete an item in the "Reply" table and put an item in the "Thread" table.
{ok, _} = erlcloud_ddb:batch_write_item(
[{<<"Reply">>, [{put, [{<<"ReplyDateTime">>, <<"2012-04-03T11:04:47.034Z">>},
{<<"Id">>, <<"Amazon DynamoDB#DynamoDB Thread 5">>}]},
{delete, {<<"Amazon DynamoDB#DynamoDB Thread 4">>,
<<"oops - accidental row">>}}]},
{<<"Thread">>, [{put, [{<<"ForumName">>, <<"Amazon DynamoDB">>},
{<<"Subject">>, <<"DynamoDB Thread 5">>}]}]}])
configure(AccessKeyID::string(), SecretAccessKey::string()) -> ok
configure(AccessKeyID::string(), SecretAccessKey::string(), Host::string()) -> ok
create_table(Table::table_name(), KeySchema::key_schema(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer()) -> create_table_return()
create_table(Table::table_name(), KeySchema::key_schema(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts()) -> create_table_return()
create_table(Table::table_name(), KeySchema::key_schema(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts(), Config::aws_config()) -> create_table_return()
Create "comp-table" with "user" as a string hash key and "time" as a number range key and provisioned throughput of 5 read units and 10 write units.
{ok, _} = erlcloud_ddb:create_table(<<"comp-table">>, {{<<"user">>, s}, {<<"time">>, n}}, 5, 10)
delete_item(Table::table_name(), Key::key()) -> delete_item_return()
delete_item(Table::table_name(), Key::key(), Opts::delete_item_opts()) -> delete_item_return()
delete_item(Table::table_name(), Key::key(), Opts::delete_item_opts(), Config::aws_config()) -> delete_item_return()
Delete item with hash key "Mingus" and range key 200 from "comp-table" if the "status" field is "shopping". Return all old values.
{ok, OldValues} = erlcloud_ddb:delete_item(<<"comp-table">>, {"Mingus", 200},
[{return_values, all_old},
{expected, {<<"status">>, "shopping"}}])
delete_table(Table::table_name()) -> delete_table_return()
delete_table(Table::table_name(), Opts::ddb_opts()) -> delete_table_return()
delete_table(Table::table_name(), Opts::ddb_opts(), Config::aws_config()) -> delete_table_return()
Delete "Table1".
{ok, _} = erlcloud_ddb:delete_table(<<"Table1">>)
describe_table(Table::table_name()) -> describe_table_return()
describe_table(Table::table_name(), Opts::ddb_opts()) -> describe_table_return()
describe_table(Table::table_name(), Opts::ddb_opts(), Config::aws_config()) -> describe_table_return()
Describe "Table1".
{ok, Table} = erlcloud_ddb:describe_table(<<"Table1">>)
get_item(Table::table_name(), Key::key()) -> item_return()
get_item(Table::table_name(), Key::key(), Opts::get_item_opts()) -> item_return()
get_item(Table::table_name(), Key::key(), Opts::get_item_opts(), Config::aws_config()) -> item_return()
Get attributes "status" and "friends" from the item with hash key "Julie" and range key 1307654345 in the table "comptable" using a consistent read.
{ok, Item} = erlcloud_ddb:get_item(<<"comptable">>, {"Julie", 1307654345},
[consistent_read,
{attributes_to_get, [<<"status">>, <<"friends">>]}])
list_tables() -> list_tables_return()
list_tables(Opts::list_tables_opts()) -> list_tables_return()
list_tables(Opts::list_tables_opts(), Config::aws_config()) -> list_tables_return()
Get the next 3 table names after "comp2".
{ok, TableNames} = erlcloud_ddb:list_tables([{limit, 3}, {exclusive_start_table_name, <<"comp2">>}])
new(AccessKeyID::string(), SecretAccessKey::string()) -> aws_config()
new(AccessKeyID::string(), SecretAccessKey::string(), Host::string()) -> aws_config()
put_item(Table::table_name(), Item::in_item()) -> put_item_return()
put_item(Table::table_name(), Item::in_item(), Opts::put_item_opts()) -> put_item_return()
put_item(Table::table_name(), Item::in_item(), Opts::put_item_opts(), Config::aws_config()) -> put_item_return()
Put item with attributes "time" of 300, "feeling" of "not surprised" and "user" of "Riley" into table "comp5", but only if an item with the same key exists and has field "feeling" set to "surprised". Return all the old attributes.
{ok, OldItem} = erlcloud_ddb:put_item(<<"comp5">>,
[{<<"time">>, 300},
{<<"feeling">>, <<"not surprised">>},
{<<"user">>, <<"Riley">>}],
[{return_values, all_old},
{expected, {<<"feeling">>, <<"surprised">>}}])
q(Table::table_name(), HashKey::hash_key()) -> q_return()
q(Table::table_name(), HashKey::hash_key(), Opts::q_opts()) -> q_return()
q(Table::table_name(), HashKey::hash_key(), Opts::q_opts(), Config::aws_config()) -> q_return()
Get up to 2 items with hash key "John" and with range keys coming before "The Matrix" from table "1-hash-rangetable".
{ok, Items} = erlcloud_ddb:q(<<"1-hash-rangetable">>, <<"John">>,
[{exclusive_start_key, {{s, <<"John">>}, {s, <<"The Matrix">>}}},
{scan_index_forward, false},
{limit, 2}])
scan(Table::table_name()) -> scan_return()
scan(Table::table_name(), Opts::scan_opts()) -> scan_return()
scan(Table::table_name(), Opts::scan_opts(), Config::aws_config()) -> scan_return()
Return all items from table "comp5" with "time" greater than 400.
{ok, Items} = erlcloud_ddb:scan(<<"comp5">>, [{scan_filter, [{<<"time">>, 400, gt}]}])
update_item(Table::table_name(), Key::key(), Updates::in_updates()) -> update_item_return()
update_item(Table::table_name(), Key::key(), Updates::in_updates(), Opts::update_item_opts()) -> update_item_return()
update_item(Table::table_name(), Key::key(), Updates::in_updates(), Opts::update_item_opts(), Config::aws_config()) -> update_item_return()
Update item with hash key "Julie" and range key 1307654350 in table "comp5" by changing the status from "offline" to "online" and return the new item.
{ok, NewItem} = erlcloud_ddb:update_item(<<"comp5">>, {"Julie", 1307654350},
[{<<"status">>, <<"online">>, put}],
[{return_values, all_new},
{expected, {<<"status">>, "offline"}}])
update_table(Table::table_name(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer()) -> update_table_return()
update_table(Table::table_name(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts()) -> update_table_return()
update_table(Table::table_name(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts(), Config::aws_config()) -> update_table_return()
Update table "comp1" to have provisioned capacity of 5 read units and 15 write units.
{ok, _} = erlcloud_ddb:update_table(<<"comp1">>, 5, 15)
Generated by EDoc