Module erlcloud_ddb

An Erlang interface to Amazon's DynamoDB.

Authors: Ransom Richardson (ransom@ransomr.net).

Description

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.

See the unit tests for additional usage examples beyond what are provided for each function.

Data Types

attr_name()

attr_name() = binary()

attr_type()

attr_type() = s | n | b | ss | ns | bs

batch_get_item_request_item()

batch_get_item_request_item() = {table_name(), [key(), ...], get_item_opts()} | {table_name(), [key(), ...]}

batch_get_item_request_items()

batch_get_item_request_items() = maybe_list(batch_get_item_request_item())

batch_get_item_return()

batch_get_item_return() = ddb_return(#ddb_batch_get_item{}, [erlcloud_ddb:out_item()])

batch_write_item_delete()

batch_write_item_delete() = {delete, key()}

batch_write_item_put()

batch_write_item_put() = {put, in_item()}

batch_write_item_request()

batch_write_item_request() = batch_write_item_put() | batch_write_item_delete()

batch_write_item_request_item()

batch_write_item_request_item() = {table_name(), [batch_write_item_request()]}

batch_write_item_request_items()

batch_write_item_request_items() = maybe_list(batch_write_item_request_item())

batch_write_item_return()

batch_write_item_return() = ddb_return(#ddb_batch_write_item{}, #ddb_batch_write_item{})

boolean_opt()

boolean_opt(Name) = Name | {Name, boolean()}

comparison_op()

comparison_op() = eq | ne | le | lt | ge | gt | not_null | null | contains | not_contains | begins_with | in | between

create_table_return()

create_table_return() = ddb_return(#ddb_create_table{}, #ddb_table_description{})

ddb_opts()

ddb_opts() = [out_opt()]

ddb_return()

ddb_return(Record, Simple) = {ok, jsx:json_term() | Record | Simple} | {error, term()}

delete_item_opt()

delete_item_opt() = {expected, in_expected()} | {return_values, none | all_old} | out_opt()

delete_item_opts()

delete_item_opts() = [delete_item_opt()]

delete_item_return()

delete_item_return() = ddb_return(#ddb_delete_item{}, out_item())

delete_table_return()

delete_table_return() = ddb_return(#ddb_delete_table{}, #ddb_table_description{})

describe_table_return()

describe_table_return() = ddb_return(#ddb_describe_table{}, #ddb_table{})

get_item_opt()

get_item_opt() = {attributes_to_get, [binary()]} | boolean_opt(consistent_read) | out_opt()

get_item_opts()

get_item_opts() = [get_item_opt()]

hash_key()

hash_key() = in_attr_value()

hash_range_key()

hash_range_key() = {hash_key(), range_key()}

in_attr()

in_attr() = {attr_name(), in_attr_value()}

in_attr_data()

in_attr_data() = in_attr_data_scalar() | in_attr_data_set()

in_attr_data_scalar()

in_attr_data_scalar() = iolist() | binary() | number()

in_attr_data_set()

in_attr_data_set() = [iolist() | binary()] | [number()]

in_attr_typed_value()

in_attr_typed_value() = {attr_type(), in_attr_data()}

in_attr_value()

in_attr_value() = in_attr_data() | in_attr_typed_value()

in_expected()

in_expected() = maybe_list(in_expected_item())

in_expected_item()

in_expected_item() = {attr_name(), false | in_attr_value()}

in_item()

in_item() = [in_attr()]

in_update()

in_update() = {attr_name(), in_attr_value(), update_action()} | in_attr() | {attr_name(), delete}

in_updates()

in_updates() = maybe_list(in_update())

item_return()

item_return() = ok_return(out_item())

key()

key() = hash_key() | hash_range_key()

key_schema()

key_schema() = key_schema_value() | {key_schema_value(), key_schema_value()}

key_schema_value()

key_schema_value() = {attr_name(), attr_type()}

list_tables_opt()

list_tables_opt() = {limit, pos_integer()} | {exclusive_start_table_name, binary()} | out_opt()

list_tables_opts()

list_tables_opts() = [list_tables_opt()]

list_tables_return()

list_tables_return() = ddb_return(#ddb_list_tables{}, [table_name()])

maybe_list()

maybe_list(T) = T | [T]

ok_return()

ok_return(T) = {ok, T} | {error, term()}

out_attr()

out_attr() = {attr_name(), out_attr_value()}

out_attr_value()

out_attr_value() = binary() | number() | [binary()] | [number()]

out_item()

out_item() = [out_attr()]

out_opt()

out_opt() = {out, out_type()}

out_type()

out_type() = json | record | simple

put_item_opt()

put_item_opt() = {expected, in_expected()} | {return_values, none | all_old} | out_opt()

put_item_opts()

put_item_opts() = [put_item_opt()]

put_item_return()

put_item_return() = ddb_return(#ddb_put_item{}, out_item())

q_opt()

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_opts() = [q_opt()]

q_return()

q_return() = ddb_return(#ddb_q{}, [out_item()])

range_key()

range_key() = in_attr_value()

range_key_condition()

range_key_condition() = {in_attr_value(), comparison_op()} | {{in_attr_value(), in_attr_value()}, between}

return_value()

return_value() = none | all_old | updated_old | all_new | updated_new

scan_filter()

scan_filter() = maybe_list(scan_filter_item())

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()

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_opts() = [scan_opt()]

scan_return()

scan_return() = ddb_return(#ddb_scan{}, [out_item()])

table_name()

table_name() = binary()

update_action()

update_action() = put | add | delete

update_item_opt()

update_item_opt() = {expected, in_expected()} | {return_values, return_value()} | out_opt()

update_item_opts()

update_item_opts() = [update_item_opt()]

update_item_return()

update_item_return() = ddb_return(#ddb_update_item{}, out_item())

update_table_return()

update_table_return() = ddb_return(#ddb_update_table{}, #ddb_table_description{})

Function Index

batch_get_item/1
batch_get_item/2
batch_get_item/3

Example

.
batch_write_item/1
batch_write_item/2
batch_write_item/3

Example

.
configure/2
configure/3
create_table/4
create_table/5
create_table/6

Example

.
delete_item/2
delete_item/3
delete_item/4

Example

.
delete_table/1
delete_table/2
delete_table/3

Example

.
describe_table/1
describe_table/2
describe_table/3

Example

.
get_item/2
get_item/3
get_item/4

Example

.
list_tables/0
list_tables/1
list_tables/2

Example

.
new/2
new/3
put_item/2
put_item/3
put_item/4

Example

.
q/2
q/3
q/4

Example

.
scan/1
scan/2
scan/3

Example

.
update_item/3
update_item/4
update_item/5

Example

.
update_table/3
update_table/4
update_table/5

Example

.

Function Details

batch_get_item/1

batch_get_item(RequestItems::batch_get_item_request_items()) -> batch_get_item_return()

batch_get_item/2

batch_get_item(RequestItems::batch_get_item_request_items(), Opts::ddb_opts()) -> batch_get_item_return()

batch_get_item/3

batch_get_item(RequestItems::batch_get_item_request_items(), Opts::ddb_opts(), Config::aws_config()) -> batch_get_item_return()

Example

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/1

batch_write_item(RequestItems::batch_write_item_request_items()) -> batch_write_item_return()

batch_write_item/2

batch_write_item(RequestItems::batch_write_item_request_items(), Opts::ddb_opts()) -> batch_write_item_return()

batch_write_item/3

batch_write_item(RequestItems::batch_write_item_request_items(), Opts::ddb_opts(), Config::aws_config()) -> batch_write_item_return()

Example

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/2

configure(AccessKeyID::string(), SecretAccessKey::string()) -> ok

configure/3

configure(AccessKeyID::string(), SecretAccessKey::string(), Host::string()) -> ok

create_table/4

create_table(Table::table_name(), KeySchema::key_schema(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer()) -> create_table_return()

create_table/5

create_table(Table::table_name(), KeySchema::key_schema(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts()) -> create_table_return()

create_table/6

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()

Example

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/2

delete_item(Table::table_name(), Key::key()) -> delete_item_return()

delete_item/3

delete_item(Table::table_name(), Key::key(), Opts::delete_item_opts()) -> delete_item_return()

delete_item/4

delete_item(Table::table_name(), Key::key(), Opts::delete_item_opts(), Config::aws_config()) -> delete_item_return()

Example

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/1

delete_table(Table::table_name()) -> delete_table_return()

delete_table/2

delete_table(Table::table_name(), Opts::ddb_opts()) -> delete_table_return()

delete_table/3

delete_table(Table::table_name(), Opts::ddb_opts(), Config::aws_config()) -> delete_table_return()

Example

Delete "Table1".

{ok, _} = erlcloud_ddb:delete_table(<<"Table1">>)

describe_table/1

describe_table(Table::table_name()) -> describe_table_return()

describe_table/2

describe_table(Table::table_name(), Opts::ddb_opts()) -> describe_table_return()

describe_table/3

describe_table(Table::table_name(), Opts::ddb_opts(), Config::aws_config()) -> describe_table_return()

Example

Describe "Table1".

{ok, Table} = erlcloud_ddb:describe_table(<<"Table1">>)

get_item/2

get_item(Table::table_name(), Key::key()) -> item_return()

get_item/3

get_item(Table::table_name(), Key::key(), Opts::get_item_opts()) -> item_return()

get_item/4

get_item(Table::table_name(), Key::key(), Opts::get_item_opts(), Config::aws_config()) -> item_return()

Example

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/0

list_tables() -> list_tables_return()

list_tables/1

list_tables(Opts::list_tables_opts()) -> list_tables_return()

list_tables/2

list_tables(Opts::list_tables_opts(), Config::aws_config()) -> list_tables_return()

Example

Get the next 3 table names after "comp2".

{ok, TableNames} = erlcloud_ddb:list_tables([{limit, 3}, {exclusive_start_table_name, <<"comp2">>}])

new/2

new(AccessKeyID::string(), SecretAccessKey::string()) -> aws_config()

new/3

new(AccessKeyID::string(), SecretAccessKey::string(), Host::string()) -> aws_config()

put_item/2

put_item(Table::table_name(), Item::in_item()) -> put_item_return()

put_item/3

put_item(Table::table_name(), Item::in_item(), Opts::put_item_opts()) -> put_item_return()

put_item/4

put_item(Table::table_name(), Item::in_item(), Opts::put_item_opts(), Config::aws_config()) -> put_item_return()

Example

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/2

q(Table::table_name(), HashKey::hash_key()) -> q_return()

q/3

q(Table::table_name(), HashKey::hash_key(), Opts::q_opts()) -> q_return()

q/4

q(Table::table_name(), HashKey::hash_key(), Opts::q_opts(), Config::aws_config()) -> q_return()

Example

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/1

scan(Table::table_name()) -> scan_return()

scan/2

scan(Table::table_name(), Opts::scan_opts()) -> scan_return()

scan/3

scan(Table::table_name(), Opts::scan_opts(), Config::aws_config()) -> scan_return()

Example

Return all items from table "comp5" with "time" greater than 400.

{ok, Items} = erlcloud_ddb:scan(<<"comp5">>, [{scan_filter, [{<<"time">>, 400, gt}]}])

update_item/3

update_item(Table::table_name(), Key::key(), Updates::in_updates()) -> update_item_return()

update_item/4

update_item(Table::table_name(), Key::key(), Updates::in_updates(), Opts::update_item_opts()) -> update_item_return()

update_item/5

update_item(Table::table_name(), Key::key(), Updates::in_updates(), Opts::update_item_opts(), Config::aws_config()) -> update_item_return()

Example

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/3

update_table(Table::table_name(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer()) -> update_table_return()

update_table/4

update_table(Table::table_name(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts()) -> update_table_return()

update_table/5

update_table(Table::table_name(), ReadUnits::non_neg_integer(), WriteUnits::non_neg_integer(), Opts::ddb_opts(), Config::aws_config()) -> update_table_return()

Example

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