Dynamodb DG
Dynamodb DG
Developer Guide
API Version 2012-08-10
Amazon DynamoDB Developer Guide
Amazon's trademarks and trade dress may not be used in connection with any product or service that is not
Amazon's, in any manner that is likely to cause confusion among customers, or in any manner that disparages or
discredits Amazon. All other trademarks not owned by Amazon are the property of their respective owners, who may
or may not be affiliated with, connected to, or sponsored by Amazon.
Amazon DynamoDB Developer Guide
Table of Contents
What Is Amazon DynamoDB? ............................................................................................................... 1
High Availability and Durability .................................................................................................... 1
Getting Started with DynamoDB .................................................................................................. 1
How It Works ............................................................................................................................ 2
Core Components .............................................................................................................. 2
DynamoDB API ................................................................................................................ 10
Naming Rules and Data Types ........................................................................................... 12
Read Consistency ............................................................................................................. 16
Read/write Capacity Mode ................................................................................................. 17
Partitions and Data Distribution ......................................................................................... 21
From SQL to NoSQL ................................................................................................................. 23
Relational or NoSQL? ........................................................................................................ 24
Characteristics of Databases .............................................................................................. 25
Creating a Table ............................................................................................................... 27
Getting Information About a Table ..................................................................................... 29
Writing Data to a Table ..................................................................................................... 30
Reading Data from a Table ................................................................................................ 32
Managing Indexes ............................................................................................................. 37
Modifying Data in a Table ................................................................................................. 40
Deleting Data from a Table ............................................................................................... 42
Removing a Table ............................................................................................................. 43
Additional Amazon DynamoDB Resources .................................................................................... 44
Blog Posts, Repositories, and Guides ................................................................................... 44
Data Modeling and Design Patterns .................................................................................... 44
Advanced Design Patterns with Rick Houlihan ...................................................................... 44
Training Courses ............................................................................................................... 44
Tools for Coding and Visualization ..................................................................................... 45
Setting Up DynamoDB ...................................................................................................................... 46
Setting Up DynamoDB Local (Downloadable Version) .................................................................... 46
Deploying DynamoDB on Your Computer ............................................................................ 46
Deploying as an Apache Maven Repository .......................................................................... 48
Install the Official Docker Image ........................................................................................ 48
Usage Notes .................................................................................................................... 49
Setting Up DynamoDB (Web Service) .......................................................................................... 51
Signing Up for AWS .......................................................................................................... 51
Getting an AWS Access Key ............................................................................................... 52
Configuring Your Credentials ............................................................................................. 53
Accessing DynamoDB ........................................................................................................................ 54
Using the Console .................................................................................................................... 54
Working with User Preferences .......................................................................................... 55
Using the AWS CLI ................................................................................................................... 56
Downloading and Configuring the AWS CLI ......................................................................... 56
Using the AWS CLI with DynamoDB .................................................................................... 56
Using the AWS CLI with Downloadable DynamoDB ............................................................... 57
Using the API .......................................................................................................................... 58
Using the NoSQL Workbench ..................................................................................................... 58
IP Address Ranges .................................................................................................................... 58
Getting Started with DynamoDB ........................................................................................................ 59
Basic Concepts ......................................................................................................................... 59
Prerequisites ............................................................................................................................ 59
Step 1: Create a Table .............................................................................................................. 59
Step 2: Write Data .................................................................................................................... 62
Step 3: Read Data .................................................................................................................... 64
Step 4: Update Data ................................................................................................................. 65
Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable
performance with seamless scalability. DynamoDB lets you offload the administrative burdens
of operating and scaling a distributed database so that you don't have to worry about hardware
provisioning, setup and configuration, replication, software patching, or cluster scaling. DynamoDB also
offers encryption at rest, which eliminates the operational burden and complexity involved in protecting
sensitive data. For more information, see DynamoDB Encryption at Rest (p. 813).
With DynamoDB, you can create database tables that can store and retrieve any amount of data and
serve any level of request traffic. You can scale up or scale down your tables' throughput capacity
without downtime or performance degradation. You can use the AWS Management Console to monitor
resource utilization and performance metrics.
DynamoDB provides on-demand backup capability. It allows you to create full backups of your tables
for long-term retention and archival for regulatory compliance needs. For more information, see On-
Demand Backup and Restore for DynamoDB (p. 604).
You can create on-demand backups and enable point-in-time recovery for your Amazon DynamoDB
tables. Point-in-time recovery helps protect your tables from accidental write or delete operations. With
point-in-time recovery, you can restore that table to any point in time during the last 35 days. For more
information, see Point-in-Time Recovery: How It Works (p. 620).
DynamoDB allows you to delete expired items from tables automatically to help you reduce storage
usage and the cost of storing data that is no longer relevant. For more information, see Expiring Items
Using Time to Live (TTL) (p. 409).
• Amazon DynamoDB: How It Works (p. 2)—To learn essential DynamoDB concepts.
• Setting Up DynamoDB (p. 46)—To learn how to set up DynamoDB (the downloadable version or
the web service).
• Accessing DynamoDB (p. 54)—To learn how to access DynamoDB using the console, AWS CLI, or
API.
To get started quickly with DynamoDB, see Getting Started with DynamoDB and AWS SDKs (p. 76).
To quickly find recommendations for maximizing performance and minimizing throughput costs, see
Best Practices for Designing and Architecting with DynamoDB (p. 896). To learn how to tag DynamoDB
resources, see Adding Tags and Labels to Resources (p. 360).
For best practices, how-to guides, and tools, see Amazon DynamoDB resources.
You can use AWS Database Migration Service (AWS DMS) to migrate data from a relational database or
MongoDB to a DynamoDB table. For more information, see the AWS Database Migration Service User
Guide.
To learn how to use MongoDB as a migration source, see Using MongoDB as a Source for AWS Database
Migration Service. To learn how to use DynamoDB as a migration target, see Using an Amazon
DynamoDB Database as a Target for AWS Database Migration Service.
After you read this introduction, try working through the Creating Tables and Loading Data for Code
Examples in DynamoDB (p. 326) section, which walks you through the process of creating sample
tables, uploading data, and performing some basic database operations.
For language-specific tutorials with sample code, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Topics
• Core Components of Amazon DynamoDB (p. 2)
• DynamoDB API (p. 10)
• Naming Rules and Data Types (p. 12)
• Read Consistency (p. 16)
• Read/Write Capacity Mode (p. 17)
• Partitions and Data Distribution (p. 21)
There are limits in DynamoDB. For more information, see Service, Account, and Table Limits in Amazon
DynamoDB (p. 959).
Topics
• Tables, Items, and Attributes (p. 3)
• Primary Key (p. 6)
• Secondary Indexes (p. 7)
• DynamoDB Streams (p. 9)
• Tables – Similar to other database systems, DynamoDB stores data in tables. A table is a collection of
data. For example, see the example table called People that you could use to store personal contact
information about friends, family, or anyone else of interest. You could also have a Cars table to store
information about vehicles that people drive.
• Items – Each table contains zero or more items. An item is a group of attributes that is uniquely
identifiable among all of the other items. In a People table, each item represents a person. For a Cars
table, each item represents one vehicle. Items in DynamoDB are similar in many ways to rows, records,
or tuples in other database systems. In DynamoDB, there is no limit to the number of items you can
store in a table.
• Attributes – Each item is composed of one or more attributes. An attribute is a fundamental data
element, something that does not need to be broken down any further. For example, an item in a
People table contains attributes called PersonID, LastName, FirstName, and so on. For a Department
table, an item might have attributes such as DepartmentID, Name, Manager, and so on. Attributes in
DynamoDB are similar in many ways to fields or columns in other database systems.
The following diagram shows a table named People with some example items and attributes.
• Each item in the table has a unique identifier, or primary key, that distinguishes the item from all of
the others in the table. In the People table, the primary key consists of one attribute (PersonID).
• Other than the primary key, the People table is schemaless, which means that neither the attributes
nor their data types need to be defined beforehand. Each item can have its own distinct attributes.
• Most of the attributes are scalar, which means that they can have only one value. Strings and numbers
are common examples of scalars.
• Some of the items have a nested attribute (Address). DynamoDB supports nested attributes up to 32
levels deep.
The following is another example table named Music that you could use to keep track of your music
collection.
• The primary key for Music consists of two attributes (Artist and SongTitle). Each item in the table must
have these two attributes. The combination of Artist and SongTitle distinguishes each item in the table
from all of the others.
• Other than the primary key, the Music table is schemaless, which means that neither the attributes nor
their data types need to be defined beforehand. Each item can have its own distinct attributes.
• One of the items has a nested attribute (PromotionInfo), which contains other nested attributes.
DynamoDB supports nested attributes up to 32 levels deep.
For more information, see Working with Tables and Data in DynamoDB (p. 336).
Primary Key
When you create a table, in addition to the table name, you must specify the primary key of the table.
The primary key uniquely identifies each item in the table, so that no two items can have the same key.
• Partition key – A simple primary key, composed of one attribute known as the partition key.
DynamoDB uses the partition key's value as input to an internal hash function. The output from the
hash function determines the partition (physical storage internal to DynamoDB) in which the item will
be stored.
In a table that has only a partition key, no two items can have the same partition key value.
The People table described in Tables, Items, and Attributes (p. 3) is an example of a table with a
simple primary key (PersonID). You can access any item in the People table directly by providing the
PersonId value for that item.
• Partition key and sort key – Referred to as a composite primary key, this type of key is composed of
two attributes. The first attribute is the partition key, and the second attribute is the sort key.
DynamoDB uses the partition key value as input to an internal hash function. The output from the
hash function determines the partition (physical storage internal to DynamoDB) in which the item will
be stored. All items with the same partition key value are stored together, in sorted order by sort key
value.
In a table that has a partition key and a sort key, it's possible for two items to have the same partition
key value. However, those two items must have different sort key values.
The Music table described in Tables, Items, and Attributes (p. 3) is an example of a table with a
composite primary key (Artist and SongTitle). You can access any item in the Music table directly, if you
provide the Artist and SongTitle values for that item.
A composite primary key gives you additional flexibility when querying data. For example, if you
provide only the value for Artist, DynamoDB retrieves all of the songs by that artist. To retrieve only a
subset of songs by a particular artist, you can provide a value for Artist along with a range of values for
SongTitle.
Note
The partition key of an item is also known as its hash attribute. The term hash attribute derives
from the use of an internal hash function in DynamoDB that evenly distributes data items across
partitions, based on their partition key values.
The sort key of an item is also known as its range attribute. The term range attribute derives
from the way DynamoDB stores items with the same partition key physically close together, in
sorted order by the sort key value.
Each primary key attribute must be a scalar (meaning that it can hold only a single value). The only data
types allowed for primary key attributes are string, number, or binary. There are no such restrictions for
other, non-key attributes.
API Version 2012-08-10
6
Amazon DynamoDB Developer Guide
Core Components
Secondary Indexes
You can create one or more secondary indexes on a table. A secondary index lets you query the data
in the table using an alternate key, in addition to queries against the primary key. DynamoDB doesn't
require that you use indexes, but they give your applications more flexibility when querying your data.
After you create a secondary index on a table, you can read data from the index in much the same way as
you do from the table.
• Global secondary index – An index with a partition key and sort key that can be different from those
on the table.
• Local secondary index – An index that has the same partition key as the table, but a different sort key.
Each table in DynamoDB has a limit of 20 global secondary indexes (default limit) and 5 local secondary
indexes per table.
In the example Music table shown previously, you can query data items by Artist (partition key) or by
Artist and SongTitle (partition key and sort key). What if you also wanted to query the data by Genre and
AlbumTitle? To do this, you could create an index on Genre and AlbumTitle, and then query the index in
much the same way as you'd query the Music table.
The following diagram shows the example Music table, with a new index called GenreAlbumTitle. In the
index, Genre is the partition key and AlbumTitle is the sort key.
• Every index belongs to a table, which is called the base table for the index. In the preceding example,
Music is the base table for the GenreAlbumTitle index.
• DynamoDB maintains indexes automatically. When you add, update, or delete an item in the base
table, DynamoDB adds, updates, or deletes the corresponding item in any indexes that belong to that
table.
• When you create an index, you specify which attributes will be copied, or projected, from the base
table to the index. At a minimum, DynamoDB projects the key attributes from the base table into the
index. This is the case with GenreAlbumTitle, where only the key attributes from the Music table
are projected into the index.
You can query the GenreAlbumTitle index to find all albums of a particular genre (for example, all Rock
albums). You can also query the index to find all albums within a particular genre that have certain
album titles (for example, all Country albums with titles that start with the letter H).
For more information, see Improving Data Access with Secondary Indexes (p. 497).
DynamoDB Streams
DynamoDB Streams is an optional feature that captures data modification events in DynamoDB tables.
The data about these events appear in the stream in near-real time, and in the order that the events
occurred.
Each event is represented by a stream record. If you enable a stream on a table, DynamoDB Streams
writes a stream record whenever one of the following events occurs:
• A new item is added to the table: The stream captures an image of the entire item, including all of its
attributes.
• An item is updated: The stream captures the "before" and "after" image of any attributes that were
modified in the item.
• An item is deleted from the table: The stream captures an image of the entire item before it was
deleted.
Each stream record also contains the name of the table, the event timestamp, and other metadata.
Stream records have a lifetime of 24 hours; after that, they are automatically removed from the stream.
You can use DynamoDB Streams together with AWS Lambda to create a trigger—code that executes
automatically whenever an event of interest appears in a stream. For example, consider a Customers
table that contains customer information for a company. Suppose that you want to send a "welcome"
email to each new customer. You could enable a stream on that table, and then associate the stream
with a Lambda function. The Lambda function would execute whenever a new stream record appears,
but only process new items added to the Customers table. For any item that has an EmailAddress
attribute, the Lambda function would invoke Amazon Simple Email Service (Amazon SES) to send an
email to that address.
Note
In this example, the last customer, Craig Roe, will not receive an email because he doesn't have
an EmailAddress.
In addition to triggers, DynamoDB Streams enables powerful solutions such as data replication within
and across AWS Regions, materialized views of data in DynamoDB tables, data analysis using Kinesis
materialized views, and much more.
For more information, see Capturing Table Activity with DynamoDB Streams (p. 574).
DynamoDB API
To work with Amazon DynamoDB, your application must use a few simple API operations. The following
is a summary of these operations, organized by category.
Topics
• Control Plane (p. 10)
• Data Plane (p. 11)
• DynamoDB Streams (p. 12)
• Transactions (p. 12)
Control Plane
Control plane operations let you create and manage DynamoDB tables. They also let you work with
indexes, streams, and other objects that are dependent on tables.
• CreateTable – Creates a new table. Optionally, you can create one or more secondary indexes, and
enable DynamoDB Streams for the table.
• DescribeTable– Returns information about a table, such as its primary key schema, throughput
settings, and index information.
• ListTables – Returns the names of all of your tables in a list.
• UpdateTable – Modifies the settings of a table or its indexes, creates or removes new indexes on a
table, or modifies DynamoDB Streams settings for a table.
• DeleteTable – Removes a table and all of its dependent objects from DynamoDB.
Data Plane
Data plane operations let you perform create, read, update, and delete (also called CRUD) actions on
data in a table. Some of the data plane operations also let you read data from a secondary index.
Creating Data
• PutItem – Writes a single item to a table. You must specify the primary key attributes, but you don't
have to specify other attributes.
• BatchWriteItem – Writes up to 25 items to a table. This is more efficient than calling PutItem
multiple times because your application only needs a single network round trip to write the items. You
can also use BatchWriteItem for deleting multiple items from one or more tables.
Reading Data
• GetItem – Retrieves a single item from a table. You must specify the primary key for the item that you
want. You can retrieve the entire item, or just a subset of its attributes.
• BatchGetItem – Retrieves up to 100 items from one or more tables. This is more efficient than calling
GetItem multiple times because your application only needs a single network round trip to read the
items.
• Query – Retrieves all items that have a specific partition key. You must specify the partition key value.
You can retrieve entire items, or just a subset of their attributes. Optionally, you can apply a condition
to the sort key values so that you only retrieve a subset of the data that has the same partition key.
You can use this operation on a table, provided that the table has both a partition key and a sort key.
You can also use this operation on an index, provided that the index has both a partition key and a sort
key.
• Scan – Retrieves all items in the specified table or index. You can retrieve entire items, or just a subset
of their attributes. Optionally, you can apply a filtering condition to return only the values that you are
interested in and discard the rest.
Updating Data
• UpdateItem – Modifies one or more attributes in an item. You must specify the primary key for the
item that you want to modify. You can add new attributes and modify or remove existing attributes.
You can also perform conditional updates, so that the update is only successful when a user-defined
condition is met. Optionally, you can implement an atomic counter, which increments or decrements a
numeric attribute without interfering with other write requests.
Deleting Data
• DeleteItem – Deletes a single item from a table. You must specify the primary key for the item that
you want to delete.
• BatchWriteItem – Deletes up to 25 items from one or more tables. This is more efficient than calling
DeleteItem multiple times because your application only needs a single network round trip to delete
the items. You can also use BatchWriteItem for adding multiple items to one or more tables.
DynamoDB Streams
DynamoDB Streams operations let you enable or disable a stream on a table, and allow access to the
data modification records contained in a stream.
• ListStreams – Returns a list of all your streams, or just the stream for a specific table.
• DescribeStream – Returns information about a stream, such as its Amazon Resource Name (ARN)
and where your application can begin reading the first few stream records.
• GetShardIterator – Returns a shard iterator, which is a data structure that your application uses to
retrieve the records from the stream.
• GetRecords – Retrieves one or more stream records, using a given shard iterator.
Transactions
Transactions provide atomicity, consistency, isolation, and durability (ACID) enabling you to maintain
data correctness in your applications more easily.
• TransactWriteItems – A batch operation that allows Put, Update, and Delete operations to
multiple items both within and across tables with a guaranteed all-or-nothing result.
• TransactGetItems – A batch operation that allows Get operations to retrieves multiple items from
one or more tables.
Topics
• Naming Rules (p. 12)
• Data Types (p. 13)
Naming Rules
Tables, attributes, and other objects in DynamoDB must have names. Names should be meaningful and
concise—for example, names such as Products, Books, and Authors are self-explanatory.
Although DynamoDB allows you to use these reserved words and special characters for names, we
recommend that you avoid doing so because you have to define placeholder variables whenever
you use these names in an expression. For more information, see Expression Attribute Names in
DynamoDB (p. 390).
Data Types
DynamoDB supports many different data types for attributes within a table. They can be categorized as
follows:
• Scalar Types – A scalar type can represent exactly one value. The scalar types are number, string,
binary, Boolean, and null.
• Document Types – A document type can represent a complex structure with nested attributes, such as
you would find in a JSON document. The document types are list and map.
• Set Types – A set type can represent multiple scalar values. The set types are string set, number set,
and binary set.
When you create a table or a secondary index, you must specify the names and data types of each
primary key attribute (partition key and sort key). Furthermore, each primary key attribute must be
defined as type string, number, or binary.
DynamoDB is a NoSQL database and is schemaless. This means that, other than the primary key
attributes, you don't have to define any attributes or data types when you create tables. By comparison,
relational databases require you to define the names and data types of each column when you create a
table.
The following are descriptions of each data type, along with examples in JSON format.
Scalar Types
The scalar types are number, string, binary, Boolean, and null.
Number
Numbers can be positive, negative, or zero. Numbers can have up to 38 digits of precision. Exceeding this
results in an exception.
In DynamoDB, numbers are represented as variable length. Leading and trailing zeroes are trimmed.
All numbers are sent across the network to DynamoDB as strings, to maximize compatibility across
languages and libraries. However, DynamoDB treats them as number type attributes for mathematical
operations.
Note
If number precision is important, you should pass numbers to DynamoDB using strings that you
convert from the number type.
You can use the number data type to represent a date or a timestamp. One way to do this is by using
epoch time—the number of seconds since 00:00:00 UTC on 1 January 1970. For example, the epoch time
1437136300 represents 12:31:40 PM UTC on 17 July 2015.
String
Strings are Unicode with UTF-8 binary encoding. The length of a string must be greater than zero and is
constrained by the maximum DynamoDB item size limit of 400 KB.
The following additional constraints apply to primary key attributes that are defined as type string:
• For a simple primary key, the maximum length of the first attribute value (the partition key) is 2048
bytes.
• For a composite primary key, the maximum length of the second attribute value (the sort key) is 1024
bytes.
DynamoDB collates and compares strings using the bytes of the underlying UTF-8 string encoding. For
example, "a" (0x61) is greater than "A" (0x41), and "¿" (0xC2BF) is greater than "z" (0x7A).
You can use the string data type to represent a date or a timestamp. One way to do this is by using ISO
8601 strings, as shown in these examples:
• 2016-02-15
• 2015-12-21T17:42:34Z
• 20150311T122706Z
Binary
Binary type attributes can store any binary data, such as compressed text, encrypted data, or images.
Whenever DynamoDB compares binary values, it treats each byte of the binary data as unsigned.
The length of a binary attribute must be greater than zero, and is constrained by the maximum
DynamoDB item size limit of 400 KB.
If you define a primary key attribute as a binary type attribute, the following additional constraints
apply:
• For a simple primary key, the maximum length of the first attribute value (the partition key) is 2048
bytes.
• For a composite primary key, the maximum length of the second attribute value (the sort key) is 1024
bytes.
Your applications must encode binary values in base64-encoded format before sending them to
DynamoDB. Upon receipt of these values, DynamoDB decodes the data into an unsigned byte array and
uses that as the length of the binary attribute.
dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk
Boolean
A Boolean type attribute can store either true or false.
Null
Null represents an attribute with an unknown or undefined state.
Document Types
The document types are list and map. These data types can be nested within each other, to represent
complex data structures up to 32 levels deep.
There is no limit on the number of values in a list or a map, as long as the item containing the values fits
within the DynamoDB item size limit (400 KB).
An attribute value cannot be an empty string or empty set (string set, number set, or binary set).
However, empty lists and maps are allowed. For more information, see Attributes (p. 964).
List
A list type attribute can store an ordered collection of values. Lists are enclosed in square brackets:
[ ... ]
A list is similar to a JSON array. There are no restrictions on the data types that can be stored in a list
element, and the elements in a list element do not have to be of the same type.
The following example shows a list that contains two strings and a number.
Note
DynamoDB lets you work with individual elements within lists, even if those elements are deeply
nested. For more information, see Using Expressions in DynamoDB (p. 386).
Map
A map type attribute can store an unordered collection of name-value pairs. Maps are enclosed in curly
braces: { ... }
A map is similar to a JSON object. There are no restrictions on the data types that can be stored in a map
element, and the elements in a map do not have to be of the same type.
Maps are ideal for storing JSON documents in DynamoDB. The following example shows a map that
contains a string, a number, and a nested list that contains another map.
{
Day: "Monday",
UnreadEmails: 42,
ItemsOnMyDesk: [
"Coffee Cup",
"Telephone",
{
Pens: { Quantity : 3},
Pencils: { Quantity : 2},
Erasers: { Quantity : 1}
}
]
}
Note
DynamoDB lets you work with individual elements within maps, even if those elements are
deeply nested. For more information, see Using Expressions in DynamoDB (p. 386).
Sets
DynamoDB supports types that represent sets of number, string, or binary values. All the elements
within a set must be of the same type. For example, an attribute of type Number Set can only contain
numbers; String Set can only contain strings; and so on.
There is no limit on the number of values in a set, as long as the item containing the values fits within
the DynamoDB item size limit (400 KB).
Each value within a set must be unique. The order of the values within a set is not preserved. Therefore,
your applications must not rely on any particular order of elements within the set. Finally, DynamoDB
does not support empty sets.
The following example shows a string set, a number set, and a binary set:
Read Consistency
Amazon DynamoDB is available in multiple AWS Regions around the world. Each Region is independent
and isolated from other AWS Regions. For example, if you have a table called People in the us-east-2
Region and another table named People in the us-west-2 Region, these are considered two entirely
separate tables. For a list of all the AWS Regions in which DynamoDB is available, see AWS Regions and
Endpoints in the Amazon Web Services General Reference.
Every AWS Region consists of multiple distinct locations called Availability Zones. Each Availability
Zone is isolated from failures in other Availability Zones, and provides inexpensive, low-latency network
connectivity to other Availability Zones in the same Region. This allows rapid replication of your data
among multiple Availability Zones in a Region.
When your application writes data to a DynamoDB table and receives an HTTP 200 response (OK), the
write has occurred and is durable. The data is eventually consistent across all storage locations, usually
within one second or less.
When you read data from a DynamoDB table, the response might not reflect the results of a recently
completed write operation. The response might include some stale data. If you repeat your read request
after a short time, the response should return the latest data.
When you request a strongly consistent read, DynamoDB returns a response with the most up-to-
date data, reflecting the updates from all prior write operations that were successful. However, this
consistency comes with some disadvantages:
• A strongly consistent read might not be available if there is a network delay or outage. In this case,
DynamoDB may return a server error (HTTP 500).
• Strongly consistent reads may have higher latency than eventually consistent reads.
• Strongly consistent reads are not supported on global secondary indexes.
• Strongly consistent reads use more throughput capacity than eventually consistent reads. For details,
see Read/Write Capacity Mode (p. 17)
Note
DynamoDB uses eventually consistent reads, unless you specify otherwise. Read operations
(such as GetItem, Query, and Scan) provide a ConsistentRead parameter. If you set this
parameter to true, DynamoDB uses strongly consistent reads during the operation.
• On-demand
• Provisioned (default, free-tier eligible)
The read/write capacity mode controls how you are charged for read and write throughput and how you
manage capacity. You can set the read/write capacity mode when creating a table or you can change it
later.
Global secondary indexes inherit the read/write capacity mode from the base table. For more
information, see Considerations When Changing Read/Write Capacity Mode (p. 341).
Topics
• On-Demand Mode (p. 17)
• Provisioned Mode (p. 19)
On-Demand Mode
Amazon DynamoDB on-demand is a flexible billing option capable of serving thousands of requests per
second without capacity planning. DynamoDB on-demand offers pay-per-request pricing for read and
write requests so that you pay only for what you use.
When you choose on-demand mode, DynamoDB instantly accommodates your workloads as they
ramp up or down to any previously reached traffic level. If a workload’s traffic level hits a new peak,
DynamoDB adapts rapidly to accommodate the workload. Tables that use on-demand mode deliver
the same single-digit millisecond latency, service-level agreement (SLA) commitment, and security that
DynamoDB already offers. You can choose on-demand for both new and existing tables and you can
continue using the existing DynamoDB APIs without changing code.
The request rate is only limited by the DynamoDB throughput default table limits, but it can be raised
upon request. For more information, see Throughput Default Limits (p. 960).
To get started with on-demand, you can create or update a table to use on-demand mode. For more
information, see Basic Operations on DynamoDB Tables (p. 336).
You can switch between read/write capacity modes once every 24 hours. For issues you should consider
when switching read/write capacity modes, see Considerations When Changing Read/Write Capacity
Mode (p. 341).
Note
On-demand is currently not supported by the DynamoDB import/export tool.
Topics
• Read Request Units and Write Request Units (p. 18)
• Peak Traffic and Scaling Properties (p. 18)
• Initial Throughput for On-Demand Capacity Mode (p. 19)
• Table Behavior while Switching Read/Write Capacity Mode (p. 19)
• One read request unit represents one strongly consistent read request, or two eventually consistent
read requests, for an item up to 4 KB in size. Transactional read requests require 2 read request units to
perform one read for items up to 4 KB. If you need to read an item that is larger than 4 KB, DynamoDB
needs additional read request units. The total number of read request units required depends on the
item size, and whether you want an eventually consistent or strongly consistent read. For example, if
your item size is 8 KB, you require 2 read request units to sustain one strongly consistent read, 1 read
request unit if you choose eventually consistent reads, or 4 read request units for a transactional read
request.
Note
To learn more about DynamoDB read consistency models, see Read Consistency (p. 16).
• One write request unit represents one write for an item up to 1 KB in size. If you need to write an item
that is larger than 1 KB, DynamoDB needs to consume additional write request units. Transactional
write requests require 2 write request units to perform one write for items up to 1 KB. The total
number of write request units required depends on the item size. For example, if your item size is
2 KB, you require 2 write request units to sustain one write request or 4 write request units for a
transactional write request.
For a list of AWS Regions where DynamoDB on-demand is available, see Amazon DynamoDB Pricing.
If you need more than double your previous peak on table, DynamoDB automatically allocates more
capacity as your traffic volume increases to help ensure that your workload does not experience
throttling. However, throttling can occur if you exceed double your previous peak within 30 minutes.
For example, if your application’s traffic pattern varies between 25,000 and 50,000 strongly consistent
reads per second where 50,000 reads per second is the previously reached traffic peak, DynamoDB
recommends spacing your traffic growth over at least 30 minutes before driving more than 100,000
reads per second.
• Newly created table with on-demand capacity mode: The previous peak is 2,000 write request units
or 6,000 read request units. You can drive up to double the previous peak immediately, which enables
newly created on-demand tables to serve up to 4,000 write request units or 12,000 read request units,
or any linear combination of the two.
• Existing table switched to on-demand capacity mode: The previous peak is half the maximum write
capacity units and read capacity units provisioned since the table was created, or the settings for a
newly created table with on-demand capacity mode, whichever is higher. In other words, your table
will deliver at least as much throughput as it did prior to switching to on-demand capacity mode.
Provisioned Mode
If you choose provisioned mode, you specify the number of reads and writes per second that you require
for your application. You can use auto scaling to adjust your table’s provisioned capacity automatically
in response to traffic changes. This helps you govern your DynamoDB use to stay at or below a defined
request rate in order to obtain cost predictability.
• One read capacity unit represents one strongly consistent read per second, or two eventually
consistent reads per second, for an item up to 4 KB in size. Transactional read requests require two
read capacity units to perform one read per second for items up to 4 KB. If you need to read an item
that is larger than 4 KB, DynamoDB must consume additional read capacity units. The total number of
read capacity units required depends on the item size, and whether you want an eventually consistent
or strongly consistent read. For example, if your item size is 8 KB, you require 2 read capacity units
to sustain one strongly consistent read per second, 1 read capacity unit if you choose eventually
consistent reads, or 4 read capacity units for a transactional read request. For more information, see
Capacity Unit Consumption for Reads (p. 343).
Note
To learn more about DynamoDB read consistency models, see Read Consistency (p. 16).
• One write capacity unit represents one write per second for an item up to 1 KB in size. If you need
to write an item that is larger than 1 KB, DynamoDB must consume additional write capacity units.
Transactional write requests require 2 write capacity units to perform one write per second for items
up to 1 KB. The total number of write capacity units required depends on the item size. For example,
if your item size is 2 KB, you require 2 write capacity units to sustain one write request per second
or 4 write capacity units for a transactional write request. For more information, see Capacity Unit
Consumption for Writes (p. 343).
Important
When calling DescribeTable on an on-demand table, read capacity units and write capacity
units are set to 0.
If your application reads or writes larger items (up to the DynamoDB maximum item size of 400 KB), it
will consume more capacity units.
For example, suppose that you create a provisioned table with 6 read capacity units and 6 write capacity
units. With these settings, your application could do the following:
For more information, see Managing Settings on DynamoDB Provisioned Capacity Tables (p. 342).
Provisioned throughput is the maximum amount of capacity that an application can consume from a
table or index. If your application exceeds your provisioned throughput capacity on a table or index, it is
subject to request throttling.
Throttling prevents your application from consuming too many capacity units.
When a request is throttled, it fails with an HTTP 400 code (Bad Request) and a
ProvisionedThroughputExceededException. The AWS SDKs have built-in support for retrying
throttled requests (see Error Retries and Exponential Backoff (p. 228)), so you do not need to write this
logic yourself.
You can use the AWS Management Console to monitor your provisioned and actual throughput, and to
modify your throughput settings if necessary.
With DynamoDB auto scaling, a table or a global secondary index can increase its provisioned read and
write capacity to handle sudden increases in traffic, without request throttling. When the workload
decreases, DynamoDB auto scaling can decrease the throughput so that you don't pay for unused
provisioned capacity.
Note
If you use the AWS Management Console to create a table or a global secondary index,
DynamoDB auto scaling is enabled by default.
You can manage auto scaling settings at any time by using the console, the AWS CLI, or one of
the AWS SDKs.
For more information, see Managing Throughput Capacity Automatically with DynamoDB Auto
Scaling (p. 346).
Reserved Capacity
As a DynamoDB customer, you can purchase reserved capacity in advance, as described at Amazon
DynamoDB Pricing. With reserved capacity, you pay a one-time upfront fee and commit to a minimum
usage level over a period of time. By reserving your read and write capacity units ahead of time, you
realize significant cost savings compared to on-demand provisioned throughput settings.
Note
Reserved capacity is not available in on-demand mode.
To manage reserved capacity, go to the DynamoDB console and choose Reserved Capacity.
Note
You can prevent users from viewing or purchasing reserved capacity, while still allowing them
to access the rest of the console. For more information, see "Grant Permissions to Prevent
Purchasing of Reserved Capacity Offerings" in Identity and Access Management in Amazon
DynamoDB (p. 823).
When you create a table, the initial status of the table is CREATING. During this phase, DynamoDB
allocates sufficient partitions to the table so that it can handle your provisioned throughput
requirements. You can begin writing and reading table data after the table status changes to ACTIVE.
• If you increase the table's provisioned throughput settings beyond what the existing partitions can
support.
• If an existing partition fills to capacity and more storage space is required.
Partition management occurs automatically in the background and is transparent to your applications.
Your table remains available throughout and fully supports your provisioned throughput requirements.
Global secondary indexes in DynamoDB are also composed of partitions. The data in a global secondary
index is stored separately from the data in its base table, but index partitions behave in much the same
way as table partitions.
To write an item to the table, DynamoDB uses the value of the partition key as input to an internal hash
function. The output value from the hash function determines the partition in which the item will be
stored.
To read an item from the table, you must specify the partition key value for the item. DynamoDB uses
this value as input to its hash function, yielding the partition in which the item can be found.
The following diagram shows a table named Pets, which spans multiple partitions. The table's primary
key is AnimalType (only this key attribute is shown). DynamoDB uses its hash function to determine
where to store a new item, in this case based on the hash value of the string Dog. Note that the items are
not stored in sorted order. Each item's location is determined by the hash value of its partition key.
Note
DynamoDB is optimized for uniform distribution of items across a table's partitions, no matter
how many partitions there may be. We recommend that you choose a partition key that can
have a large number of distinct values relative to the number of items in the table.
To write an item to the table, DynamoDB calculates the hash value of the partition key to determine
which partition should contain the item. In that partition, several items could have the same partition
key value. So DynamoDB stores the item among the others with the same partition key, in ascending
order by sort key.
To read an item from the table, you must specify its partition key value and sort key value. DynamoDB
calculates the partition key's hash value, yielding the partition in which the item can be found.
You can read multiple items from the table in a single operation (Query) if the items you want have the
same partition key value. DynamoDB returns all of the items with that partition key value. Optionally,
you can apply a condition to the sort key so that it returns only the items within a certain range of
values.
Suppose that the Pets table has a composite primary key consisting of AnimalType (partition key) and
Name (sort key). The following diagram shows DynamoDB writing an item with a partition key value of
Dog and a sort key value of Fido.
To read that same item from the Pets table, DynamoDB calculates the hash value of Dog, yielding the
partition in which these items are stored. DynamoDB then scans the sort key attribute values until it
finds Fido.
To read all of the items with an AnimalType of Dog, you can issue a Query operation without specifying
a sort key condition. By default, the items are returned in the order that they are stored (that is, in
ascending order by sort key). Optionally, you can request descending order instead.
To query only some of the Dog items, you can apply a condition to the sort key (for example, only the
Dog items where Name begins with a letter that is within the range A through K).
Note
In a DynamoDB table, there is no upper limit on the number of distinct sort key values per
partition key value. If you needed to store many billions of Dog items in the Pets table,
DynamoDB would allocate enough storage to handle this requirement automatically.
NoSQL is a term used to describe nonrelational database systems that are highly available, scalable, and
optimized for high performance. Instead of the relational model, NoSQL databases (like DynamoDB)
use alternate models for data management, such as key-value pairs or document storage. For more
information, see http://aws.amazon.com/nosql.
Note
The SQL examples in this section are compatible with the MySQL RDBMS.
The DynamoDB examples in this section show the name of the DynamoDB operation, along with
the parameters for that operation in JSON format. For code examples that use these operations,
see Getting Started with DynamoDB and AWS SDKs (p. 76).
Topics
• Relational (SQL) or NoSQL? (p. 24)
• Characteristics of Databases (p. 25)
• Creating a Table (p. 27)
• Getting Information About a Table (p. 29)
• Writing Data to a Table (p. 30)
• Key Differences When Reading Data from a Table (p. 32)
• Managing Indexes (p. 37)
• Modifying Data in a Table (p. 40)
• Deleting Data from a Table (p. 42)
• Removing a Table (p. 43)
Amazon DynamoDB is well-suited for these kinds of workloads. As a developer, you can start small
and gradually increase your utilization as your application becomes more popular. DynamoDB scales
seamlessly to handle very large amounts of data and very large numbers of users.
The following table shows some high-level differences between an RDBMS and DynamoDB.
Data Access SQL is the standard for storing You can use the AWS
and retrieving data. Relational Management Console or
databases offer a rich set the AWS CLI to work with
of tools for simplifying the DynamoDB and perform ad hoc
development of database-driven tasks. Applications can use the
applications, but all of these AWS software development kits
tools use SQL. (SDKs) to work with DynamoDB
using object-based, document-
centric, or low-level interfaces.
Characteristics of Databases
Before your application can access a database, it must be authenticated to ensure that the application is
allowed to use the database. It must be authorized so that the application can perform only the actions
for which it has permissions.
The following diagram shows a client's interaction with a relational database and with Amazon
DynamoDB.
The following table has more details about client interaction tasks.
Tools for Accessing the Most relational databases In most cases, you write
Database provide a command line application code. You can also
interface (CLI) so that you can use the AWS Management
enter ad hoc SQL statements Console or the AWS Command
and see the results immediately. Line Interface (AWS CLI) to send
ad hoc requests to DynamoDB
and view the results.
Sending a Request The application issues a SQL The application sends HTTP(S)
statement for every database requests to DynamoDB. The
operation that it wants to requests contain the name of
perform. Upon receipt of the the DynamoDB operation to
SQL statement, the RDBMS perform, along with parameters.
checks its syntax, creates a plan DynamoDB executes the request
for performing the operation, immediately.
and then executes the plan.
Receiving a Response The RDBMS returns the results DynamoDB returns an HTTP(S)
from the SQL statement. If there response containing the results
is an error, the RDBMS returns of the operation. If there is an
an error status and message. error, DynamoDB returns an
HTTP error status and messages.
Creating a Table
Tables are the fundamental data structures in relational databases and in Amazon DynamoDB. A
relational database management system (RDBMS) requires you to define the table's schema when you
create it. In contrast, DynamoDB tables are schemaless—other than the primary key, you do not need to
define any extra attributes or data types when you create a table.
Topics
• SQL (p. 27)
• DynamoDB (p. 28)
SQL
Use the CREATE TABLE statement to create a table, as shown in the following example.
Year INT,
Price FLOAT,
Genre VARCHAR(10),
Tags TEXT,
PRIMARY KEY(Artist, SongTitle)
);
The primary key for this table consists of Artist and SongTitle.
You must define all of the table's columns and data types, and the table's primary key. (You can use the
ALTER TABLE statement to change these definitions later, if necessary.)
Many SQL implementations let you define storage specifications for your table, as part of the CREATE
TABLE statement. Unless you indicate otherwise, the table is created with default storage settings. In a
production environment, a database administrator can help determine the optimal storage parameters.
DynamoDB
Use the CreateTable action to create a provisioned mode table, specifying parameters as shown
following:
{
TableName : "Music",
KeySchema: [
{
AttributeName: "Artist",
KeyType: "HASH", //Partition key
},
{
AttributeName: "SongTitle",
KeyType: "RANGE" //Sort key
}
],
AttributeDefinitions: [
{
AttributeName: "Artist",
AttributeType: "S"
},
{
AttributeName: "SongTitle",
AttributeType: "S"
}
],
ProvisionedThroughput: { // Only specified if using provisioned mode
ReadCapacityUnits: 1,
WriteCapacityUnits: 1
}
}
The primary key for this table consists of Artist (partition key) and SongTitle (sort key).
if necessary. You do not need to specify a table's storage requirements because storage allocation is
managed entirely by DynamoDB.
Note
For code examples that use CreateTable, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Topics
• SQL (p. 29)
• DynamoDB (p. 29)
SQL
Most relational database management systems (RDBMS) allow you to describe a table's structure—
columns, data types, primary key definition, and so on. There is no standard way to do this in SQL.
However, many database systems provide a DESCRIBE command. The following is an example from
MySQL.
DESCRIBE Music;
This returns the structure of your table, with all of the column names, data types, and sizes.
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| Artist | varchar(20) | NO | PRI | NULL | |
| SongTitle | varchar(30) | NO | PRI | NULL | |
| AlbumTitle | varchar(25) | YES | | NULL | |
| Year | int(11) | YES | | NULL | |
| Price | float | YES | | NULL | |
| Genre | varchar(10) | YES | | NULL | |
| Tags | text | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
The primary key for this table consists of Artist and SongTitle.
DynamoDB
DynamoDB has a DescribeTable action, which is similar. The only parameter is the table name.
{
TableName : "Music"
}
{
"Table": {
"AttributeDefinitions": [
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"TableName": "Music",
"KeySchema": [
{
"AttributeName": "Artist",
"KeyType": "HASH" //Partition key
},
{
"AttributeName": "SongTitle",
"KeyType": "RANGE" //Sort key
}
],
...
DescribeTable also returns information about indexes on the table, provisioned throughput settings,
an approximate item count, and other metadata.
This section describes how to write one row (or item) to a table.
Topics
• SQL (p. 30)
• DynamoDB (p. 31)
SQL
A table in a relational database is a two-dimensional data structure composed of rows and columns.
Some database management systems also provide support for semistructured data, usually with native
JSON or XML data types. However, the implementation details vary among vendors.
The primary key for this table consists of Artist and SongTitle. You must specify values for these columns.
Note
This example uses the Tags column to store semistructured data about the songs in the Music
table. The Tags column is defined as type TEXT, which can store up to 65,535 characters in
MySQL.
DynamoDB
In Amazon DynamoDB, you use the PutItem action to add an item to a table.
{
TableName: "Music",
Item: {
"Artist":"No One You Know",
"SongTitle":"Call Me Today",
"AlbumTitle":"Somewhat Famous",
"Year": 2015,
"Price": 2.14,
"Genre": "Country",
"Tags": {
"Composers": [
"Smith",
"Jones",
"Davis"
],
"LengthInSeconds": 214
}
}
}
The primary key for this table consists of Artist and SongTitle. You must specify values for these
attributes.
Here are some key things to know about this PutItem example:
• DynamoDB provides native support for documents, using JSON. This makes DynamoDB ideal for
storing semistructured data, such as Tags. You can also retrieve and manipulate data from within JSON
documents.
• The Music table does not have any predefined attributes, other than the primary key (Artist and
SongTitle).
• Most SQL databases are transaction oriented. When you issue an INSERT statement, the data
modifications are not permanent until you issue a COMMIT statement. With Amazon DynamoDB, the
effects of a PutItem action are permanent when DynamoDB replies with an HTTP 200 status code
(OK).
Note
For code examples using PutItem, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
{
TableName: "Music",
Item: {
"Artist": "No One You Know",
"SongTitle": "My Dog Spot",
"AlbumTitle":"Hey Now",
"Price": 1.98,
"Genre": "Country",
"CriticRating": 8.4
}
}
{
TableName: "Music",
Item: {
"Artist": "No One You Know",
"SongTitle": "Somewhere Down The Road",
"AlbumTitle":"Somewhat Famous",
"Genre": "Country",
"CriticRating": 8.4,
"Year": 1984
}
}
{
TableName: "Music",
Item: {
"Artist": "The Acme Band",
"SongTitle": "Still In Love",
"AlbumTitle":"The Buck Starts Here",
"Price": 2.47,
"Genre": "Rock",
"PromotionInfo": {
"RadioStationsPlaying":[
"KHCR", "KBQX", "WTNR", "WJJH"
],
"TourDates": {
"Seattle": "20150625",
"Cleveland": "20150630"
},
"Rotation": "Heavy"
}
}
}
{
TableName: "Music",
Item: {
"Artist": "The Acme Band",
"SongTitle": "Look Out, World",
"AlbumTitle":"The Buck Starts Here",
"Price": 0.99,
"Genre": "Rock"
}
}
Note
In addition to PutItem, DynamoDB supports a BatchWriteItem action for writing multiple
items at the same time.
• GetItem – Retrieves a single item from a table. This is the most efficient way to read a single item
because it provides direct access to the physical location of the item. (DynamoDB also provides the
BatchGetItem operation, allowing you to perform up to 100 GetItem calls in a single operation.)
• Query – Retrieves all of the items that have a specific partition key. Within those items, you can apply
a condition to the sort key and retrieve only a subset of the data. Query provides quick, efficient
access to the partitions where the data is stored. (For more information, see Partitions and Data
Distribution (p. 21).)
• Scan – Retrieves all of the items in the specified table. (This operation should not be used with large
tables because it can consume large amounts of system resources.)
Note
With a relational database, you can use the SELECT statement to join data from multiple
tables and return the results. Joins are fundamental to the relational model. To ensure that
joins execute efficiently, the database and its applications should be performance-tuned on an
ongoing basis. DynamoDB is a non-relational NoSQL database that does not support table joins.
Instead, applications read data from one table at a time.
The following sections describe different use cases for reading data, and how to perform these tasks with
a relational database and with DynamoDB.
Topics
• Reading an Item Using Its Primary Key (p. 33)
• Querying a Table (p. 34)
• Scanning a Table (p. 36)
Topics
• SQL (p. 33)
• DynamoDB (p. 33)
SQL
In SQL, you use the SELECT statement to retrieve data from a table. You can request one or more
columns in the result (or all of them, if you use the * operator). The WHERE clause determines which rows
to return.
The following is a SELECT statement to retrieve a single row from the Music table. The WHERE clause
specifies the primary key values.
SELECT *
FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'
You can modify this query to retrieve only a subset of the columns.
Note that the primary key for this table consists of Artist and SongTitle.
DynamoDB
DynamoDB provides the GetItem action for retrieving an item by its primary key. GetItem is highly
efficient because it provides direct access to the physical location of the item. (For more information, see
Partitions and Data Distribution (p. 21).)
By default, GetItem returns the entire item with all of its attributes.
{
TableName: "Music",
Key: {
"Artist": "No One You Know",
"SongTitle": "Call Me Today"
}
}
You can add a ProjectionExpression parameter to return only some of the attributes.
{
TableName: "Music",
Key: {
"Artist": "No One You Know",
"SongTitle": "Call Me Today"
},
"ProjectionExpression": "AlbumTitle, Year, Price"
}
Note that the primary key for this table consists of Artist and SongTitle.
The DynamoDB GetItem action is very efficient: It uses the primary key values to determine the exact
storage location of the item in question, and retrieves it directly from there. The SQL SELECT statement
is similarly efficient, in the case of retrieving items by primary key values.
The SQL SELECT statement supports many kinds of queries and table scans. DynamoDB provides similar
functionality with its Query and Scan actions, which are described in Querying a Table (p. 34) and
Scanning a Table (p. 36).
The SQL SELECT statement can perform table joins, allowing you to retrieve data from multiple
tables at the same time. Joins are most effective where the database tables are normalized and the
relationships among the tables are clear. However, if you join too many tables in one SELECT statement
application performance can be affected. You can work around such issues by using database replication,
materialized views, or query rewrites.
DynamoDB is a nonrelational database and doesn't support table joins. If you are migrating an existing
application from a relational database to DynamoDB, you need to denormalize your data model to
eliminate the need for joins.
Note
For code examples that use GetItem, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Querying a Table
Another common access pattern is reading multiple items from a table, based on your query criteria.
Topics
• SQL (p. 34)
• DynamoDB (p. 35)
SQL
The SQL SELECT statement lets you query on key columns, non-key columns, or any combination. The
WHERE clause determines which rows are returned, as shown in the following examples.
/* Return all of the songs by an artist, with a particular word in the title...
...but only if the price is less than 1.00 */
Note that the primary key for this table consists of Artist and SongTitle.
DynamoDB
The Amazon DynamoDB Query action lets you retrieve data in a similar fashion. The Query action
provides quick, efficient access to the physical locations where the data is stored. For more information,
see Partitions and Data Distribution (p. 21).
You can use Query with any table that has a composite primary key (partition key and sort key).
You must specify an equality condition for the partition key, and you can optionally provide another
condition for the sort key.
The KeyConditionExpression parameter specifies the key values that you want to query. You can use
an optional FilterExpression to remove certain items from the results before they are returned to
you.
Note that the primary key for this table consists of Artist and SongTitle.
{
TableName: "Music",
KeyConditionExpression: "Artist = :a and SongTitle = :t",
ExpressionAttributeValues: {
":a": "No One You Know",
":t": "Call Me Today"
}
}
{
TableName: "Music",
KeyConditionExpression: "Artist = :a",
ExpressionAttributeValues: {
":a": "No One You Know"
}
}
{
TableName: "Music",
KeyConditionExpression: "Artist = :a and begins_with(SongTitle, :t)",
ExpressionAttributeValues: {
":a": "No One You Know",
":t": "Call"
}
}
Note
For code examples that use Query, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Scanning a Table
In SQL, a SELECT statement without a WHERE clause will return every row in a table. In Amazon
DynamoDB, the Scan operation does the same thing. In both cases, you can retrieve all of the items or
just some of them.
Whether you are using a SQL or a NoSQL database, scans should be used sparingly because they can
consume large amounts of system resources. Sometimes a scan is appropriate (such as scanning a small
table) or unavoidable (such as performing a bulk export of data). However, as a general rule, you should
design your applications to avoid performing scans.
Topics
• SQL (p. 36)
• DynamoDB (p. 36)
SQL
In SQL, you can scan a table and retrieve all of its data by using a SELECT statement without specifying
a WHERE clause. You can request one or more columns in the result. Or you can request all of them if you
use the wildcard character (*).
DynamoDB
DynamoDB provides a Scan action that works in a similar way. The following are some examples.
The Scan action also provides a FilterExpression parameter, which you can use to discard items
that you do not want to appear in the results. A FilterExpression is applied after the entire table is
scanned, but before the results are returned to you. (This is not recommended with large tables. You are
still charged for the entire Scan, even if only a few matching items are returned.)
Note
For code examples that use Scan, see Getting Started with DynamoDB and AWS SDKs (p. 76).
Managing Indexes
Indexes give you access to alternate query patterns, and can speed up queries. This section compares and
contrasts index creation and usage in SQL and Amazon DynamoDB.
Whether you are using a relational database or DynamoDB, you should be judicious with index creation.
Whenever a write occurs on a table, all of the table's indexes must be updated. In a write-heavy
environment with large tables, this can consume large amounts of system resources. In a read-only or
read-mostly environment, this is not as much of a concern. However, you should ensure that the indexes
are actually being used by your application, and not simply taking up space.
Topics
• Creating an Index (p. 37)
• Querying and Scanning an Index (p. 39)
Creating an Index
Compare the CREATE INDEX statement in SQL with the UpdateTable operation in Amazon
DynamoDB.
Topics
• SQL (p. 37)
• DynamoDB (p. 38)
SQL
In a relational database, an index is a data structure that lets you perform fast queries on different
columns in a table. You can use the CREATE INDEX SQL statement to add an index to an existing table,
specifying the columns to be indexed. After the index has been created, you can query the data in the
table as usual, but now the database can use the index to quickly find the specified rows in the table
instead of scanning the entire table.
After you create an index, the database maintains it for you. Whenever you modify data in the table, the
index is automatically modified to reflect changes in the table.
DynamoDB
In DynamoDB, you can create and use a secondary index for similar purposes.
Indexes in DynamoDB are different from their relational counterparts. When you create a secondary
index, you must specify its key attributes—a partition key and a sort key. After you create the secondary
index, you can Query it or Scan it just as you would with a table. DynamoDB does not have a query
optimizer, so a secondary index is only used when you Query it or Scan it.
• Global secondary indexes – The primary key of the index can be any two attributes from its table.
• Local secondary indexes – The partition key of the index must be the same as the partition key of its
table. However, the sort key can be any other attribute.
DynamoDB ensures that the data in a secondary index is eventually consistent with its table. You can
request strongly consistent Query or Scan actions on a table or a local secondary index. However, global
secondary indexes support only eventual consistency.
You can add a global secondary index to an existing table, using the UpdateTable action and specifying
GlobalSecondaryIndexUpdates.
{
TableName: "Music",
AttributeDefinitions:[
{AttributeName: "Genre", AttributeType: "S"},
{AttributeName: "Price", AttributeType: "N"}
],
GlobalSecondaryIndexUpdates: [
{
Create: {
IndexName: "GenreAndPriceIndex",
KeySchema: [
{AttributeName: "Genre", KeyType: "HASH"}, //Partition key
{AttributeName: "Price", KeyType: "RANGE"}, //Sort key
],
Projection: {
"ProjectionType": "ALL"
},
ProvisionedThroughput: { // Only specified
if using provisioned mode
"ReadCapacityUnits": 1,"WriteCapacityUnits": 1
}
}
}
]
}
• Projection – Attributes from the table that are copied to the index. In this case, ALL means that
all of the attributes are copied.
• ProvisionedThroughput (for provisioned tables) – The number of reads and writes per
second that you need for this index. (This is separate from the provisioned throughput settings of
the table.)
Part of this operation involves backfilling data from the table into the new index. During backfilling, the
table remains available. However, the index is not ready until its Backfilling attribute changes from
true to false. You can use the DescribeTable action to view this attribute.
Note
For code examples that use UpdateTable, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Topics
• SQL (p. 39)
• DynamoDB (p. 39)
SQL
In a relational database, you do not work directly with indexes. Instead, you query tables by issuing
SELECT statements, and the query optimizer can make use of any indexes.
A query optimizer is a relational database management system (RDBMS) component that evaluates the
available indexes and determines whether they can be used to speed up a query. If the indexes can be
used to speed up a query, the RDBMS accesses the index first and then uses it to locate the data in the
table.
Here are some SQL statements that can use GenreAndPriceIndex to improve performance. We assume
that the Music table has enough data in it that the query optimizer decides to use this index, rather than
simply scanning the entire table.
DynamoDB
In DynamoDB, you perform Query operations directly on the index, in the same way that you would on a
table. You must specify both TableName and IndexName.
The following are some queries on GenreAndPriceIndex in DynamoDB. (The key schema for this index
consists of Genre and Price.)
{
TableName: "Music",
IndexName: "GenreAndPriceIndex",
KeyConditionExpression: "Genre = :genre",
ExpressionAttributeValues: {
":genre": "Rock"
},
};
{
TableName: "Music",
IndexName: "GenreAndPriceIndex",
KeyConditionExpression: "Genre = :genre and Price < :price",
ExpressionAttributeValues: {
":genre": "Country",
":price": 0.50
},
ProjectionExpression: "Artist, SongTitle, Price"
};
This example uses a ProjectionExpression to indicate that you only want some of the attributes,
rather than all of them, to appear in the results.
You can also perform Scan operations on a secondary index, in the same way that you would on a table.
The following is a scan on GenreAndPriceIndex.
{
TableName: "Music",
IndexName: "GenreAndPriceIndex"
}
Topics
• SQL (p. 40)
• DynamoDB (p. 41)
SQL
In SQL, you use the UPDATE statement to modify one or more rows. The SET clause specifies new values
for one or more columns, and the WHERE clause determines which rows are modified. The following is an
example.
UPDATE Music
SET RecordLabel = 'Global Records'
WHERE Artist = 'No One You Know' AND SongTitle = 'Call Me Today';
If no rows match the WHERE clause, the UPDATE statement has no effect.
DynamoDB
In DynamoDB, you use the UpdateItem action to modify a single item. (If you want to modify multiple
items, you must use multiple UpdateItem operations.)
{
TableName: "Music",
Key: {
"Artist":"No One You Know",
"SongTitle":"Call Me Today"
},
UpdateExpression: "SET RecordLabel = :label",
ExpressionAttributeValues: {
":label": "Global Records"
}
}
You must specify the Key attributes of the item to be modified and an UpdateExpression to specify
attribute values. UpdateItem behaves like an "upsert" operation: The item is updated if it exists in the
table, but if not, a new item is added (inserted).
UpdateItem supports conditional writes, where the operation succeeds only if a specific
ConditionExpression evaluates to true. For example, the following UpdateItem action does not
perform the update unless the price of the song is greater than or equal to 2.00.
{
TableName: "Music",
Key: {
"Artist":"No One You Know",
"SongTitle":"Call Me Today"
},
UpdateExpression: "SET RecordLabel = :label",
ConditionExpression: "Price >= :p",
ExpressionAttributeValues: {
":label": "Global Records",
":p": 2.00
}
}
UpdateItem also supports atomic counters, or attributes of type Number that can be incremented or
decremented. Atomic counters are similar in many ways to sequence generators, identity columns, or
autoincrement fields in SQL databases.
The following is an example of an UpdateItem action to initialize a new attribute (Plays) to keep track
of the number of times a song has been played.
{
TableName: "Music",
Key: {
"Artist":"No One You Know",
"SongTitle":"Call Me Today"
},
UpdateExpression: "SET Plays = :val",
ExpressionAttributeValues: {
":val": 0
},
ReturnValues: "UPDATED_NEW"
}
The ReturnValues parameter is set to UPDATED_NEW, which returns the new values of any attributes
that were updated. In this case, it returns 0 (zero).
Whenever someone plays this song, we can use the following UpdateItem action to increment Plays by
one.
{
TableName: "Music",
Key: {
"Artist":"No One You Know",
"SongTitle":"Call Me Today"
},
UpdateExpression: "SET Plays = Plays + :incr",
ExpressionAttributeValues: {
":incr": 1
},
ReturnValues: "UPDATED_NEW"
}
Note
For code examples that use UpdateItem, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Topics
• SQL (p. 42)
• DynamoDB (p. 42)
SQL
In SQL, you use the DELETE statement to delete one or more rows. The WHERE clause determines the
rows that you want to modify. The following is an example.
You can modify the WHERE clause to delete multiple rows. For example, you could delete all of the songs
by a particular artist, as shown in the following example.
Note
If you omit the WHERE clause, the database attempts to delete all of the rows from the table.
DynamoDB
In DynamoDB, you use the DeleteItem action to delete data from a table, one item at a time. You must
specify the item's primary key values.
{
TableName: "Music",
Key: {
Artist: "The Acme Band",
SongTitle: "Look Out, World"
}
}
Note
In addition to DeleteItem, Amazon DynamoDB supports a BatchWriteItem action for
deleting multiple items at the same time.
DeleteItem supports conditional writes, where the operation succeeds only if a specific
ConditionExpression evaluates to true. For example, the following DeleteItem action deletes the
item only if it has a RecordLabel attribute.
{
TableName: "Music",
Key: {
Artist: "The Acme Band",
SongTitle: "Look Out, World"
},
ConditionExpression: "attribute_exists(RecordLabel)"
}
Note
For code examples that use DeleteItem, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Removing a Table
In SQL, you use the DROP TABLE statement to remove a table. In Amazon DynamoDB, you use the
DeleteTable operation.
Topics
• SQL (p. 43)
• DynamoDB (p. 43)
SQL
When you no longer need a table and want to discard it permanently, you use the DROP TABLE
statement in SQL.
After a table is dropped, it cannot be recovered. (Some relational databases do allow you to undo a DROP
TABLE operation, but this is vendor-specific functionality and it is not widely implemented.)
DynamoDB
DynamoDB has a similar action: DeleteTable. In the following example, the table is permanently
deleted.
{
TableName: "Music"
Note
For code examples that use DeleteTable, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
Note
Each session covers different use cases and examples.
Training Courses
• DynamoDB Deep-Dive Course — A course from Linux Academy with help from the Amazon DynamoDB
team.
• Amazon DynamoDB: Building NoSQL Database-Driven Applications — A course from the AWS Training
and Certification team hosted on edX.
Setting Up DynamoDB
In addition to the Amazon DynamoDB web service, AWS provides a downloadable version of DynamoDB
that you can run on your computer and is perfect for development and testing of your code. The
downloadable version lets you write and test applications locally without accessing the DynamoDB web
service.
The topics in this section describe how to set up DynamoDB (downloadable version) and the DynamoDB
web service.
Topics
• Setting Up DynamoDB Local (Downloadable Version) (p. 46)
• Setting Up DynamoDB (Web Service) (p. 51)
Having this local version helps you save on throughput, data storage, and data transfer fees. In addition,
you don't need an internet connection while you develop your application.
If you prefer to use the Amazon DynamoDB web service instead, see Setting Up DynamoDB (Web
Service) (p. 51).
Topics
• Deploying DynamoDB Locally on Your Computer (p. 46)
• Deploying DynamoDB by adding an Apache Maven Repository (p. 48)
• Install the DynamoDB Docker Image (p. 48)
• DynamoDB Usage Notes (p. 49)
Downloadable DynamoDB is available on Apache Maven. For more information, see Deploying
DynamoDB by adding an Apache Maven Repository (p. 48). DynamoDB is also available as part of
the AWS Toolkit for Eclipse. For more information, see AWS Toolkit For Eclipse.
Important
To run DynamoDB on your computer, you must have the Java Runtime Environment (JRE)
version 6.x or newer. The application doesn't run on earlier JRE versions.
2. After you download the archive, extract the contents and copy the extracted directory to a location
of your choice.
3. To start DynamoDB on your computer, open a command prompt window, navigate to the directory
where you extracted DynamoDBLocal.jar, and enter the following command.
Note
If you're using Windows PowerShell, be sure to enclose the parameter name or the entire
name and value like this:
java -D"java.library.path=./DynamoDBLocal_lib" -jar DynamoDBLocal.jar
DynamoDB processes incoming requests until you stop it. To stop DynamoDB, press Ctrl+C
at the command prompt.
DynamoDB uses port 8000 by default. If port 8000 is unavailable, this command throws an
exception. For a complete list of DynamoDB runtime options, including -port, enter this
command.
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -
help
4. Before you can access DynamoDB programmatically or through the AWS Command Line Interface
(AWS CLI), you must configure your credentials to enable authorization for your applications.
Downloadable DynamoDB requires any credentials to work, as shown in the following example.
You can use the aws configure command of the AWS CLI to set up credentials. For more
information, see Using the AWS CLI (p. 56).
5. Start writing applications. To access DynamoDB running locally with the AWS CLI, use the --
endpoint-url parameter. For example, use the following command to list DynamoDB tables.
1. Download and install Apache Maven. For more information, see Downloading Apache Maven and
Installing Apache Maven.
2. Add the DynamoDB Maven repository to your application's Project Object Model (POM) file.
<!--Dependency:-->
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>DynamoDBLocal</artifactId>
<version>[1.12,2.0)</version>
</dependency>
</dependencies>
<!--Custom repository:-->
<repositories>
<repository>
<id>dynamodb-local-oregon</id>
<name>DynamoDB Local Release Repository</name>
<url>https://s3-us-west-2.amazonaws.com/dynamodb-local/release</url>
</repository>
</repositories>
Note
You can also use one of the following repository URLs, depending on your AWS Region.
id Repository URL
dynamodb-local-mumbai https://s3.ap-south-1.amazonaws.com/
dynamodb-local-mumbai/release
dynamodb-local-singapore https://s3.ap-
southeast-1.amazonaws.com/dynamodb-
local-singapore/release
dynamodb-local-tokyo https://s3.ap-northeast-1.amazonaws.com/
dynamodb-local-tokyo/release
dynamodb-local-frankfurt https://s3.eu-central-1.amazonaws.com/
dynamodb-local-frankfurt/release
dynamodb-local-sao-paulo https://s3.sa-east-1.amazonaws.com/
dynamodb-local-sao-paulo/release
The aws-dynamodb-examples repository in GitHub contains examples for starting and stopping
DynamoDB local inside a Java program and using DynamoDB local in JUnit tests.
For an example of using DynamoDB local as part of a REST application built on the AWS Serverless
Application Model (AWS SAM), see SAM DynamoDB application for managing orders. This sample
application demonstrates how to use DynamoDB local for testing.
• If you use the -sharedDb option, DynamoDB creates a single database file named shared-local-
instance.db. Every program that connects to DynamoDB accesses this file. If you delete the file, you
lose any data that you have stored in it.
• If you omit -sharedDb, the database file is named myaccesskeyid_region.db, with the AWS access key
ID and AWS Region as they appear in your application configuration. If you delete the file, you lose any
data that you have stored in it.
• If you use the -inMemory option, DynamoDB doesn't write any database files at all. Instead, all data is
written to memory, and the data is not saved when you terminate DynamoDB.
• If you use the -optimizeDbBeforeStartup option, you must also specify the -dbPath parameter
so that DynamoDB can find its database file.
• The AWS SDKs for DynamoDB require that your application configuration specify an access key value
and an AWS Region value. Unless you're using the -sharedDb or the -inMemory option, DynamoDB
uses these values to name the local database file. These values don't have to be valid AWS values to
run locally. However, you might find it convenient to use valid values so that you can run your code in
the cloud later by changing the endpoint you're using.
Topics
• Command Line Options (p. 49)
• Setting the Local Endpoint (p. 50)
• Differences Between Downloadable DynamoDB and the DynamoDB Web Service (p. 50)
• -cors value — Enables support for cross-origin resource sharing (CORS) for JavaScript. You must
provide a comma-separated "allow" list of specific domains. The default setting for -cors is an
asterisk (*), which allows public access.
• -dbPath value — The directory where DynamoDB writes its database file. If you don't specify this
option, the file is written to the current directory. You can't specify both -dbPath and -inMemory at
once.
• -delayTransientStatuses — Causes DynamoDB to introduce delays for certain operations.
DynamoDB (downloadable version) can perform some tasks almost instantaneously, such as create/
update/delete operations on tables and indexes. However, the DynamoDB service requires more time
for these tasks. Setting this parameter helps DynamoDB running on your computer simulate the
behavior of the DynamoDB web service more closely. (Currently, this parameter introduces delays only
for global secondary indexes that are in either CREATING or DELETING status.)
• -help — Prints a usage summary and options.
• -inMemory — DynamoDB runs in memory instead of using a database file. When you stop
DynamoDB, none of the data is saved. You can't specify both -dbPath and -inMemory at once.
• -optimizeDbBeforeStartup — Optimizes the underlying database tables before starting
DynamoDB on your computer. You also must specify -dbPath when you use this parameter.
• -port value — The port number that DynamoDB uses to communicate with your application. If you
don't specify this option, the default port is 8000.
Note
DynamoDB uses port 8000 by default. If port 8000 is unavailable, this command throws an
exception. You can use the -port option to specify a different port number. For a complete
list of DynamoDB runtime options, including -port , type this command:
java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -
help
• -sharedDb — If you specify -sharedDb, DynamoDB uses a single database file instead of separate
files for each credential and Region.
http://localhost:8000
To access DynamoDB running locally, use the --endpoint-url parameter. The following is an example
of using the AWS CLI to list the tables in DynamoDB on your computer.
Note
The AWS CLI can't use the downloadable version of DynamoDB as a default endpoint. Therefore,
you must specify --endpoint-url with each AWS CLI command.
AWS SDKs
The way you specify an endpoint depends on the programming language and AWS SDK you're using. The
following sections describe how to do this:
Note
For examples in other programming languages, see Getting Started with DynamoDB and AWS
SDKs (p. 76).
The downloadable version of DynamoDB differs from the web service in the following ways:
• AWS Regions and distinct AWS accounts are not supported at the client level.
• Provisioned throughput settings are ignored in downloadable DynamoDB, even though the
CreateTable operation requires them. For CreateTable, you can specify any numbers you want
for provisioned read and write throughput, even though these numbers are not used. You can call
UpdateTable as many times as you want per day. However, any changes to provisioned throughput
values are ignored.
• Scan operations are performed sequentially. Parallel scans are not supported. The Segment and
TotalSegments parameters of the Scan operation are ignored.
• The speed of read and write operations on table data is limited only by the speed of your computer.
CreateTable, UpdateTable, and DeleteTable operations occur immediately, and table state is
always ACTIVE. UpdateTable operations that change only the provisioned throughput settings on
tables or global secondary indexes occur immediately. If an UpdateTable operation creates or deletes
any global secondary indexes, then those indexes transition through normal states (such as CREATING
and DELETING, respectively) before they become an ACTIVE state. The table remains ACTIVE during
this time.
• Read operations are eventually consistent. However, due to the speed of DynamoDB running on your
computer, most reads appear to be strongly consistent.
• Item collection metrics and item collection sizes are not tracked. In operation responses, nulls are
returned instead of item collection metrics.
• In DynamoDB, there is a 1 MB limit on data returned per result set. Both the DynamoDB web service
and the downloadable version enforce this limit. However, when querying an index, the DynamoDB
service calculates only the size of the projected key and attributes. By contrast, the downloadable
version of DynamoDB calculates the size of the entire item.
• If you're using DynamoDB Streams, the rate at which shards are created might differ. In the DynamoDB
web service, shard-creation behavior is partially influenced by table partition activity. When you
run DynamoDB locally, there is no table partitioning. In either case, shards are ephemeral, so your
application should not be dependent on shard behavior.
• TransactionConflictExceptions are not thrown by downloadable DynamoDB for
transactional APIs. We recommend that you use a Java mocking framework to simulate
TransactionConflictExceptions in the DynamoDB handler to test how your application
responds to conflicting transactions.
• In the DynamoDB web service, table names are case sensitive. A table named Authors and one
named authors can both exist as separate tables. In the downloadable version, table names are case
insensitive, and attempting to create these two tables would result in an error.
1. Open https://portal.aws.amazon.com/billing/signup.
2. Follow the online instructions.
Part of the sign-up procedure involves receiving a phone call and entering a verification code on the
phone keypad.
Access keys consist of an access key ID and secret access key, which are used to sign programmatic
requests that you make to AWS. If you don't have access keys, you can create them from the AWS
Management Console. As a best practice, do not use the AWS account root user access keys for any task
where it's not required. Instead, create a new administrator IAM user with access keys for yourself.
The only time that you can view or download the secret access key is when you create the keys. You
cannot recover them later. However, you can create new access keys at any time. You must also have
permissions to perform the required IAM actions. For more information, see Permissions Required to
Access IAM Resources in the IAM User Guide.
1. Sign in to the AWS Management Console and open the IAM console at https://
console.aws.amazon.com/iam/.
2. In the navigation pane, choose Users.
3. Choose the name of the user whose access keys you want to create, and then choose the Security
credentials tab.
4. In the Access keys section, choose Create access key.
5. To view the new access key pair, choose Show. You will not have access to the secret access key again
after this dialog box closes. Your credentials will look something like this:
Keep the keys confidential in order to protect your AWS account and never email them. Do not share
them outside your organization, even if an inquiry appears to come from AWS or Amazon.com. No
one who legitimately represents Amazon will ever ask you for your secret key.
7. After you download the .csv file, choose Close. When you create an access key, the key pair is active
by default, and you can use the pair right away.
Related topics
There are several ways to do this. For example, you can manually create the credentials file to store your
access key ID and secret access key. You also can use the aws configure command of the AWS CLI to
automatically create the file. Alternatively, you can use environment variables. For more information
about configuring your credentials, see the programming-specific AWS SDK developer guide.
To install and configure the AWS CLI, see Using the AWS CLI (p. 56).
Accessing DynamoDB
You can access Amazon DynamoDB using the AWS Management Console, the AWS Command Line
Interface (AWS CLI), or the DynamoDB API.
Topics
• Using the Console (p. 54)
• Using the AWS CLI (p. 56)
• Using the API (p. 58)
• Using the NoSQL Workbench for DynamoDB (p. 58)
• IP Address Ranges (p. 58)
• Monitor recent alerts, total capacity, service health, and the latest DynamoDB news on the DynamoDB
dashboard.
• Create, update, and delete tables. The capacity calculator provides estimates of how many capacity
units to request based on the usage information you provide.
• Manage streams.
• View, add, update, and delete items that are stored in tables. Manage Time to Live (TTL) to define
when items in a table expire so that they can be automatically deleted from the database.
• Query and scan a table.
• Set up and view alarms to monitor your table's capacity usage. View your table's top monitoring
metrics on real-time graphs from CloudWatch.
• Modify a table's provisioned capacity.
• Create and delete global secondary indexes.
• Create triggers to connect DynamoDB streams to AWS Lambda functions.
• Apply tags to your resources to help organize and identify them.
• Purchase reserved capacity.
The console displays an introductory screen that prompts you to create your first table. To view your
tables, in the navigation pane on the left side of the console, choose Tables.
Here's a high-level overview of the actions available per table within each navigation tab:
• Overview – View stream and table details, and manage streams and Time to Live (TTL).
• Items – Manage items and perform queries and scans.
• Metrics – Monitor Amazon CloudWatch metrics.
• Alarms – Manage CloudWatch alarms.
• Capacity – Modify a table's provisioned capacity.
• Indexes – Manage global secondary indexes.
• Triggers – Manage triggers to connect DynamoDB streams to Lambda functions.
• Access control – Set up fine-grained access control with web identity federation.
• Tags – Apply tags to your resources to help organize and identify them.
You can still change individual settings on console pages without having saved any user preferences.
Those choices persist until you close the console window. When you return to the console, any saved user
preferences are applied.
Note
User preferences are available only for IAM users. You can't set preferences if you use federated
access, temporary access, or an AWS account root user to access the console.
• Table detail view mode: View all the table-specific information vertically, horizontally, or covering the
full screen (if enabled, the navigation bar still appears).
• Show navigation bar: Enable this option to show the navigation bar on the left side (expanded).
Disable it to automatically collapse the navigation bar (you can expand it using the right chevron).
• Default entry page (Dashboard or Tables): Choose the page that loads when you access DynamoDB.
This option automatically loads the Dashboard or the Tables page, respectively.
• Items editor mode (Tree or Text): Choose the default editor mode to use when you create or edit an
item.
• Items default query type (Scan or Query): Choose the default query type to use when you access
the Items tab. Choose Scan if you want to either enable or disable the automatic scan operation that
occurs when accessing the Items tab.
• Automatic scan operation when accessing the items tab: If Scan is the default query type for items
and you enable this setting, an automatic scan operation occurs when you access the Items tab. If you
disable this setting, you can perform a scan by choosing Start search on the Items tab.
To view and save preferences on the DynamoDB console for your IAM user
Sign in as an IAM user. You can't configure user preferences for other user types.
2. In the title bar navigation, choose Preferences.
3. In Preferences, configure your preferences.
• To view the DynamoDB console default settings, choose Restore. These defaults are applied if you
choose Save.
Before you can use the AWS CLI with DynamoDB, you must get an access key ID and secret access key. For
more information, see Getting an AWS Access Key (p. 52).
For a complete listing of all the commands available for DynamoDB in the AWS CLI, see the AWS CLI
Command Reference.
Topics
• Downloading and Configuring the AWS CLI (p. 56)
• Using the AWS CLI with DynamoDB (p. 56)
• Using the AWS CLI with Downloadable DynamoDB (p. 57)
For example, the following command creates a table named Music. The partition key is Artist, and the
sort key is SongTitle. (For easier readability, long commands in this section are broken into separate
lines.)
AttributeName=Artist,AttributeType=S \
AttributeName=SongTitle,AttributeType=S \
--key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE \
--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
The following commands add new items to the table. These examples use a combination of shorthand
syntax and JSON.
On the command line, it can be difficult to compose valid JSON. However, the AWS CLI can read JSON
files. For example, consider the following JSON code snippet, which is stored in a file named key-
conditions.json.
{
"Artist": {
"AttributeValueList": [
{
"S": "No One You Know"
}
],
"ComparisonOperator": "EQ"
},
"SongTitle": {
"AttributeValueList": [
{
"S": "Call Me Today"
}
],
"ComparisonOperator": "EQ"
}
}
You can now issue a Query request using the AWS CLI. In this example, the contents of the key-
conditions.json file are used for the --key-conditions parameter.
--endpoint-url http://localhost:8000
The following example uses the AWS CLI to list the tables in a local database.
If DynamoDB is using a port number other than the default (8000), modify the --endpoint-url value
accordingly.
Note
The AWS CLI can't use the downloadable version of DynamoDB as a default endpoint. Therefore,
you must specify --endpoint-url with each command.
The AWS SDKs provide broad support for DynamoDB in Java, JavaScript in the browser, .NET, Node.js,
PHP, Python, Ruby, C++, Go, Android, and iOS. To get started quickly with these languages, see Getting
Started with DynamoDB and AWS SDKs (p. 76).
Before you can use the AWS SDKs with DynamoDB, you must get an AWS access key ID and secret access
key. For more information, see Setting Up DynamoDB (Web Service) (p. 51).
For a high-level overview of DynamoDB application programming with the AWS SDKs, see Programming
with DynamoDB and the AWS SDKs (p. 214).
IP Address Ranges
Amazon Web Services (AWS) publishes its current IP address ranges in JSON format. To view the current
ranges, download ip-ranges.json. For more information, see AWS IP Address Ranges in the AWS General
Reference.
To find the IP address ranges that you can use to access to DynamoDB tables and indexes, search the ip-
ranges.json file for the following string: "service": "DYNAMODB".
Note
The IP address ranges do not apply to DynamoDB Streams or DynamoDB Accelerator (DAX).
Topics
• Basic Concepts in DynamoDB (p. 59)
• Prerequisites - Getting Started Tutorial (p. 59)
• Step 1: Create a Table (p. 59)
• Step 2: Write Data to a Table Using the Console or AWS CLI (p. 62)
• Step 3: Read Data from a Table (p. 64)
• Step 4: Update Data in a Table (p. 65)
• Step 5: Query Data in a Table (p. 67)
• Step 6: Create a Global Secondary Index (p. 69)
• Step 7: Query the Global Secondary Index (p. 72)
• Step 8: (Optional) Clean Up Resources (p. 74)
• Getting Started with DynamoDB: Next Steps (p. 74)
• If you plan to interact with DynamoDB only through the AWS Management Console, you don't
need an AWS access key. Complete the steps in Signing Up for AWS, and then continue on to
Step 1: Create a Table (p. 59).
• If you don't want to sign up for a free tier account, you can set up DynamoDB Local
(Downloadable Version). Then continue on to Step 1: Create a Table (p. 59).
For more information about table operations, see Working with Tables and Data in DynamoDB (p. 336).
Note
Before you begin, make sure that you followed the steps in Prerequisites - Getting Started
Tutorial (p. 59).
1. Sign in to the AWS Management Console and open the DynamoDB console at https://
console.aws.amazon.com/dynamodb/.
2. In the navigation pane on the left side of the console, choose Dashboard.
3. On the right side of the console, choose Create Table.
AWS CLI
The following AWS CLI example creates a new Music table using create-table.
{
"TableDescription": {
"TableArn": "arn:aws:dynamodb:us-west-2:522194210714:table/Music",
"AttributeDefinitions": [
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"WriteCapacityUnits": 5,
"ReadCapacityUnits": 10
},
"TableSizeBytes": 0,
"TableName": "Music",
"TableStatus": "CREATING",
"TableId": "d04c7240-0e46-435d-b231-d54091fe1017",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "Artist"
},
{
"KeyType": "RANGE",
"AttributeName": "SongTitle"
}
],
"ItemCount": 0,
"CreationDateTime": 1558028402.69
}
}
To verify that DynamoDB has finished creating the Music table, use the describe-table command.
This command returns the following result. When DynamoDB finishes creating the table, the value of the
TableStatus field is set to ACTIVE.
"TableStatus": "ACTIVE",
After creating the new table, proceed to Step 2: Write Data to a Table Using the Console or AWS
CLI (p. 62).
For more information about write operations, see Writing an Item (p. 376).
11. Repeat this process and create another item with the following values:
AWS CLI
The following AWS CLI example creates two new items in the Music table using put-item.
For more information about supported data types in DynamoDB, see Data Types.
For more information about how to represent DynamoDB data types in JSON, see Attribute Values.
After writing data to your table, proceed to Step 3: Read Data from a Table (p. 64).
For more information about read operations in DynamoDB, see Reading an Item (p. 376).
The first item in the list is the one with the Artist Acme Band and the SongTitle Happy Day.
AWS CLI
The following AWS CLI example reads an item from the Music table using get-item.
Note
The default behavior for DynamoDB is eventually consistent reads. The consistent-read
parameter is used below to demonstrate strongly consistent reads.
{
"Item": {
"AlbumTitle": {
"S": "Songs About Life"
},
"Awards": {
"N": "10"
},
"SongTitle": {
"S": "Happy Day"
},
"Artist": {
"S": "Acme Band"
}
}
}
To update the data in your table, proceed to Step 4: Update Data in a Table (p. 65).
For more information about write operations, see Writing an Item (p. 376).
AWS CLI
The following AWS CLI example updates an item in the Music table using update-item.
"Attributes": {
"AlbumTitle": {
"S": "Updated Album Title"
},
"Awards": {
"N": "10"
},
"SongTitle": {
"S": "Happy Day"
},
"Artist": {
"S": "Acme Band"
}
}
}
To query the data in the Music table, proceed to Step 5: Query Data in a Table (p. 67).
For more information about query operations, see Working with Queries in DynamoDB (p. 458).
6. For Partition key, enter Acme Band, and then choose Start search.
AWS CLI
The following AWS CLI example queries an item in the Music table using query.
{
"Count": 1,
"Items": [
{
"AlbumTitle": {
"S": "Updated Album Title"
},
"Awards": {
"N": "10"
},
"SongTitle": {
"S": "Happy Day"
},
"Artist": {
"S": "Acme Band"
}
}
],
"ScannedCount": 1,
"ConsumedCapacity": null
}
To create a global secondary index for your table, proceed to Step 6: Create a Global Secondary
Index (p. 69).
For more information about global secondary indexes, see Using Global Secondary Indexes in
DynamoDB (p. 500).
6. For the Partition key, enter AlbumTitle, and then choose Create index.
AWS CLI
The following AWS CLI example creates a global secondary index AlbumTitle-index for the Music
table using update-table.
{
"TableDescription": {
"TableArn": "arn:aws:dynamodb:us-west-2:522194210714:table/Music",
"AttributeDefinitions": [
{
"AttributeName": "AlbumTitle",
"AttributeType": "S"
},
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"GlobalSecondaryIndexes": [
{
"IndexSizeBytes": 0,
"IndexName": "AlbumTitle-index",
"Projection": {
"ProjectionType": "ALL"
},
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"WriteCapacityUnits": 5,
"ReadCapacityUnits": 10
},
"IndexStatus": "CREATING",
"Backfilling": false,
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "AlbumTitle"
}
],
"IndexArn": "arn:aws:dynamodb:us-west-2:522194210714:table/Music/index/
AlbumTitle-index",
"ItemCount": 0
}
],
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"WriteCapacityUnits": 5,
"ReadCapacityUnits": 10
},
"TableSizeBytes": 0,
"TableName": "Music",
"TableStatus": "UPDATING",
"TableId": "d04c7240-0e46-435d-b231-d54091fe1017",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "Artist"
},
{
"KeyType": "RANGE",
"AttributeName": "SongTitle"
}
],
"ItemCount": 0,
"CreationDateTime": 1558028402.69
}
}
To verify that DynamoDB has finished creating the AlbumTitle-index global secondary index, use the
describe-table command.
This command returns the following result. The index is ready for use when the value of the
IndexStatus field returned is set to ACTIVE.
"IndexStatus": "ACTIVE",
Next, you can query the global secondary index. For details, see Step 7: Query the Global Secondary
Index (p. 72).
For more information about global secondary indexes, see Using Global Secondary Indexes in
DynamoDB (p. 500).
For AlbumTitle, enter Somewhat Famous, and then choose Start search.
AWS CLI
The following AWS CLI example queries a global secondary index AlbumTitle-index on the Music
table.
{
"Count": 1,
"Items": [
{
"AlbumTitle": {
"S": "Somewhat Famous"
},
"Awards": {
"N": "1"
},
"SongTitle": {
"S": "Call Me Today"
},
"Artist": {
"S": "No One You Know"
}
}
],
"ScannedCount": 1,
"ConsumedCapacity": null
}
For more information about table operations in DynamoDB, see Working with Tables and Data in
DynamoDB (p. 336).
AWS CLI
The following AWS CLI example deletes the Music table using delete-table.
Topics
• Getting Started with Java and DynamoDB (p. 76)
• Getting Started with JavaScript and DynamoDB (p. 95)
• Getting Started with Node.js and DynamoDB (p. 118)
• Getting Started with .NET and DynamoDB (p. 135)
• PHP and DynamoDB (p. 157)
• Getting Started Developing with Python and DynamoDB (p. 178)
• Ruby and DynamoDB (p. 195)
• Create a table called Movies and load sample data in JSON format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
The SDK for Java offers several programming models for different use cases. In this exercise, the Java
code uses the document model that provides a level of abstraction that makes it easier for you to work
with JSON documents.
As you work through this tutorial, you can refer to the AWS SDK for Java Documentation.
Tutorial Prerequisites
• Download and run DynamoDB on your computer. For more information, see Setting Up DynamoDB
Local (Downloadable Version) (p. 46).
DynamoDB (downloadable version) is also available as part of the AWS Toolkit for Eclipse. For more
information, see AWS Toolkit For Eclipse.
Note
You use the downloadable version of DynamoDB in this tutorial. For information about how to
run the same code against the DynamoDB web service, see the Summary (p. 95).
• Set up an AWS access key to use the AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Set up the AWS SDK for Java:
• Install a Java development environment. If you are using the Eclipse IDE, install the AWS Toolkit for
Eclipse.
• Install the AWS SDK for Java.
• Set up your AWS security credentials for use with the SDK for Java.
For instructions, see Getting Started in the AWS SDK for Java Developer Guide.
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import java.util.Arrays;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
try {
System.out.println("Attempting to create table; please wait...");
Table table = dynamoDB.createTable(tableName,
Arrays.asList(new KeySchemaElement("year", KeyType.HASH), // Partition
// key
new KeySchemaElement("title", KeyType.RANGE)), // Sort key
Arrays.asList(new AttributeDefinition("year", ScalarAttributeType.N),
new AttributeDefinition("title", ScalarAttributeType.S)),
new ProvisionedThroughput(10L, 10L));
table.waitForActive();
System.out.println("Success. Table status: " +
table.getDescription().getTableStatus());
}
catch (Exception e) {
System.err.println("Unable to create table: ");
System.err.println(e.getMessage());
}
}
}
Note
• You set the endpoint to indicate that you are creating the table in DynamoDB on your
computer.
• In the createTable call, you specify table name, primary key attributes, and its data
types.
• The ProvisionedThroughput parameter is required, but the downloadable version of
DynamoDB ignores it. (Provisioned throughput is beyond the scope of this exercise.)
2. Compile and run the program.
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Topics
• Step 2.1: Download the Sample Data File (p. 79)
• Step 2.2: Load the Sample Data into the Movies Table (p. 79)
This scenario uses a sample data file that contains information about a few thousand movies from the
Internet Movie Database (IMDb). The movie data is in JSON format, as shown in the following example.
For each movie, there is a year, a title, and a JSON map named info.
[
{
"year" : ... ,
"title" : ... ,
"info" : { ... }
},
{
"year" : ...,
"title" : ...,
"info" : { ... }
},
...
• You use the year and title as the primary key attribute values for the Movies table.
• You store the rest of the info values in a single attribute called info. This program illustrates how
you can store JSON in an Amazon DynamoDB attribute.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
Step 2.2: Load the Sample Data into the Movies Table
After you download the sample data, you can run the following program to populate the Movies table.
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import java.io.File;
import java.util.Iterator;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
ObjectNode currentNode;
while (iter.hasNext()) {
currentNode = (ObjectNode) iter.next();
try {
table.putItem(new Item().withPrimaryKey("year", year, "title",
title).withJSON("info",
currentNode.path("info").toString()));
System.out.println("PutItem succeeded: " + year + " " + title);
}
catch (Exception e) {
System.err.println("Unable to add movie: " + year + " " + title);
System.err.println(e.getMessage());
break;
}
}
parser.close();
}
}
This program uses the open source Jackson library to process JSON. Jackson is included in the AWS
SDK for Java. You don't have to install it separately.
2. Compile and run the program.
To learn more about reading and writing data, see Working with Items and Attributes (p. 375).
Topics
• Step 3.1: Create a New Item (p. 81)
• Step 3.2: Read an Item (p. 82)
• Step 3.3: Update an Item (p. 84)
• Step 3.4: Increment an Atomic Counter (p. 85)
• Step 3.5: Update an Item (Conditionally) (p. 87)
• Step 3.6: Delete an Item (p. 88)
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import java.util.HashMap;
import java.util.Map;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.PutItemOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
try {
System.out.println("Adding a new item...");
PutItemOutcome outcome = table
.putItem(new Item().withPrimaryKey("year", year, "title",
title).withMap("info", infoMap));
}
catch (Exception e) {
System.err.println("Unable to add item: " + year + " " + title);
System.err.println(e.getMessage());
}
}
}
Note
The primary key is required. This code adds an item that has primary key (year, title)
and info attributes. The info attribute stores JSON example code that provides more
information about the movie.
2. Compile and run the program.
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
You can use the getItem method to read the item from the Movies table. You must specify the primary
key values so that you can read any item from Movies if you know its year and title.
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.GetItemSpec;
try {
System.out.println("Attempting to read the item...");
Item outcome = table.getItem(spec);
System.out.println("GetItem succeeded: " + outcome);
}
catch (Exception e) {
System.err.println("Unable to read item: " + year + " " + title);
System.err.println(e.getMessage());
}
}
}
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
To this:
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]
}
}
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import java.util.Arrays;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;
try {
System.out.println("Updating the item...");
UpdateItemOutcome outcome = table.updateItem(updateItemSpec);
System.out.println("UpdateItem succeeded:\n" +
outcome.getItem().toJSONPretty());
}
catch (Exception e) {
System.err.println("Unable to update item: " + year + " " + title);
System.err.println(e.getMessage());
}
}
}
Note
This program uses an UpdateExpression to describe all updates you want to perform on
the specified item.
The ReturnValues parameter instructs Amazon DynamoDB to return only the updated
attributes (UPDATED_NEW).
2. Compile and run the program.
The following program shows how to increment the rating for a movie. Each time you run it, the
program increments this attribute by one.
1. Copy the following program and paste it into your Java development environment.
/**
package com.amazonaws.codesamples.gsg;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;
try {
System.out.println("Incrementing an atomic counter...");
UpdateItemOutcome outcome = table.updateItem(updateItemSpec);
System.out.println("UpdateItem succeeded:\n" +
outcome.getItem().toJSONPretty());
}
catch (Exception e) {
System.err.println("Unable to update item: " + year + " " + title);
System.err.println(e.getMessage());
}
}
}
In this case, the movie item is updated only if there are more than three actors.
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.PrimaryKey;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;
}
catch (Exception e) {
System.err.println("Unable to update item: " + year + " " + title);
System.err.println(e.getMessage());
}
}
}
This is because the movie has three actors in it, but the condition is checking for greater than three
actors.
3. Modify the program so that the ConditionExpression looks like the following.
In the following example, you try to delete a specific movie item if its rating is 5 or less.
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.PrimaryKey;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
try {
System.out.println("Attempting a conditional delete...");
table.deleteItem(deleteItemSpec);
System.out.println("DeleteItem succeeded");
}
catch (Exception e) {
System.err.println("Unable to delete item: " + year + " " + title);
System.err.println(e.getMessage());
}
}
}
This is because the rating for this particular move is greater than 5.
3. Modify the program to remove the condition in DeleteItemSpec.
4. Compile and run the program. Now, the delete succeeds because you removed the condition.
The primary key for the Movies table is composed of the following:
To find all movies released during a year, you need to specify only the year. You can also provide the
title to retrieve a subset of movies based on some condition (on the sort key). For example, you can
find movies released in 2014 that have a title starting with the letter "A".
In addition to the query method, there is also a scan method that can retrieve all of the table data.
To learn more about querying and scanning data, see Working with Queries in DynamoDB (p. 458) and
Working with Scans in DynamoDB (p. 476), respectively.
Topics
• Step 4.1: Query (p. 90)
• Step 4.2: Scan (p. 92)
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import java.util.HashMap;
import java.util.Iterator;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
try {
System.out.println("Movies from 1985");
items = table.query(querySpec);
iterator = items.iterator();
while (iterator.hasNext()) {
item = iterator.next();
System.out.println(item.getNumber("year") + ": " +
item.getString("title"));
}
}
catch (Exception e) {
System.err.println("Unable to query movies from 1985");
System.err.println(e.getMessage());
}
valueMap.put(":yyyy", 1992);
valueMap.put(":letter1", "A");
valueMap.put(":letter2", "L");
try {
System.out.println("Movies from 1992 - titles A-L, with genres and lead
actor");
items = table.query(querySpec);
iterator = items.iterator();
while (iterator.hasNext()) {
item = iterator.next();
System.out.println(item.getNumber("year") + ": " +
item.getString("title") + " " + item.getMap("info"));
}
}
catch (Exception e) {
System.err.println("Unable to query movies from 1992:");
System.err.println(e.getMessage());
}
}
}
Note
First, you create the querySpec object, which describes the query parameters, and then you pass
the object to the query method.
2. Compile and run the program.
Note
The preceding program shows how to query a table by its primary key attributes. In DynamoDB,
you can optionally create one or more secondary indexes on a table, and query those indexes
in the same way that you query a table. Secondary indexes give your applications additional
flexibility by allowing queries on non-key attributes. For more information, see Improving Data
Access with Secondary Indexes (p. 497).
The following program scans the entire Movies table, which contains approximately 5,000 items. The
scan specifies the optional filter to retrieve only the movies from the 1950s (approximately 100 items)
and discard all the others.
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import java.util.Iterator;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.ScanSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
try {
ItemCollection<ScanOutcome> items = table.scan(scanSpec);
}
catch (Exception e) {
System.err.println("Unable to scan the table:");
System.err.println(e.getMessage());
}
}
}
Note
You can also use the Scan operation with any secondary indexes that you created on the table.
For more information, see Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into your Java development environment.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.gsg;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Table;
try {
System.out.println("Attempting to delete table; please wait...");
table.delete();
table.waitForDelete();
System.out.print("Success.");
}
catch (Exception e) {
System.err.println("Unable to delete table: ");
System.err.println(e.getMessage());
}
}
}
Summary
In this tutorial, you created the Movies table in Amazon DynamoDB on your computer and performed
basic operations. The downloadable version of DynamoDB is useful during application development
and testing. However, when you're ready to run your application in a production environment, you must
modify your code so that it uses the DynamoDB web service.
import com.amazonaws.client.builder.AwsClientBuilder;
AmazonDynamoDB client =
AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
new AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();
3. Now modify the client so that it accesses an AWS Region instead of a specific endpoint.
For example, if you want to access the us-west-2 region, you would do the following.
Instead of using DynamoDB on your computer, the program now uses the DynamoDB web service
endpoint in the US West (Oregon) Region.
DynamoDB is available in AWS Regions worldwide. For the complete list, see Regions and Endpoints in
the AWS General Reference. For more information about setting Regions and endpoints in your code, see
AWS Region Selection in the AWS SDK for Java Developer Guide.
• Create a table called Movies and load sample data in JSON format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
As you work through this tutorial, you can refer to the AWS SDK for JavaScript API Reference.
Tutorial Prerequisites
• Download and run DynamoDB on your computer. For more information, see Setting Up DynamoDB
Local (Downloadable Version) (p. 46).
Note
You use the downloadable version of DynamoDB in this tutorial. For information about how
to run the same code against the DynamoDB web service, see the Summary and Review of
JavaScript and DynamoDB Tutorial (p. 117).
• Set up an AWS access key to use AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Set up the AWS SDK for JavaScript. To do this, add or modify the following script tag to your HTML
pages:
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.7.16.min.js"></script>
Note
The version of AWS SDK for JavaScript might have been updated. For the latest version, see
the AWS SDK for JavaScript API Reference.
• Enable cross-origin resource sharing (CORS) so that your computer's browser can communicate with
the downloadable version of DynamoDB.
To enable CORS
1. Download the free ModHeader Chrome browser extension (or any other browser extension that
allows you to modify HTTP response headers).
2. Run the ModHeader Chrome browser extension, and add an HTTP response header with the name
set to "Access-Control-Allow-Origin" and a value of "null" or "*".
Important
This configuration is required only while running this tutorial program for JavaScript
on your computer. After you finish the tutorial, you should disable or remove this
configuration.
3. You can now run the JavaScript tutorial program files.
If you prefer to run a complete version of the JavaScript tutorial program instead of performing step-by-
step instructions, do the following:
1. Copy the following program and paste it into a file named MoviesCreateTable.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function createMovies() {
var params = {
TableName : "Movies",
KeySchema: [
{ AttributeName: "year", KeyType: "HASH"},
{ AttributeName: "title", KeyType: "RANGE" }
],
AttributeDefinitions: [
{ AttributeName: "year", AttributeType: "N" },
{ AttributeName: "title", AttributeType: "S" }
],
ProvisionedThroughput: {
ReadCapacityUnits: 5,
WriteCapacityUnits: 5
}
};
</script>
</head>
<body>
<input id="createTableButton" type="button" value="Create Table"
onclick="createMovies();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
Note
• You set the endpoint to indicate that you are creating the table in Amazon DynamoDB on
your computer.
• In the createMovies function, you specify the table name, primary key attributes, and
its data types.
• The ProvisionedThroughput parameter is required, but the downloadable version of
DynamoDB ignores it. (Provisioned throughput is beyond the scope of this tutorial.)
2. Open the MoviesCreateTable.html file in your browser.
3. Choose Create Table.
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Topics
• Step 2.1: Download the Sample Data File (p. 99)
• Step 2.2: Load the Sample Data into the Movies Table (p. 99)
This scenario uses a sample data file that contains information about a few thousand movies from the
Internet Movie Database (IMDb). The movie data is in JSON format, as shown in the following example.
For each movie, there is a year, a title, and a JSON map named info.
[
{
"year" : ... ,
"title" : ... ,
"info" : { ... }
},
{
"year" : ...,
"title" : ...,
"info" : { ... }
},
...
• The year and title are used as the primary key attribute values for the Movies table.
• The rest of the info values are stored in a single attribute called info. This program illustrates how
you can store JSON in an Amazon DynamoDB attribute.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
Step 2.2: Load the Sample Data into the Movies Table
After you download the sample data, you can run the following program to populate the Movies table.
1. Copy the following program and paste it into a file named MoviesLoadData.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<head>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.7.16.min.js"></script>
<script type="text/javascript">
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function processFile(evt) {
document.getElementById('textarea').innerHTML = "";
document.getElementById('textarea').innerHTML += "Importing movies into DynamoDB.
Please wait..." + "\n";
var file = evt.target.files[0];
if (file) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
var allMovies = JSON.parse(contents);
allMovies.forEach(function (movie) {
document.getElementById('textarea').innerHTML += "Processing: " +
movie.title + "\n";
var params = {
TableName: "Movies",
Item: {
"year": movie.year,
"title": movie.title,
"info": movie.info
}
};
docClient.put(params, function (err, data) {
if (err) {
document.getElementById('textarea').innerHTML += "Unable to add
movie: " + count + movie.title + "\n";
document.getElementById('textarea').innerHTML += "Error JSON: "
+ JSON.stringify(err) + "\n";
} else {
document.getElementById('textarea').innerHTML += "PutItem
succeeded: " + movie.title + "\n";
textarea.scrollTop = textarea.scrollHeight;
}
});
});
};
r.readAsText(file);
} else {
alert("Could not read movie data file");
}
}
</script>
</head>
<body>
<script>
document.getElementById('fileinput').addEventListener('change', processFile,
false);
</script>
</body>
</html>
To learn more about reading and writing data, see Working with Items and Attributes (p. 375).
Topics
• Step 3.1: Create a New Item (p. 101)
• Step 3.2: Read an Item (p. 102)
• Step 3.3: Update an Item (p. 104)
• Step 3.4: Increment an Atomic Counter (p. 106)
• Step 3.5: Update an Item (Conditionally) (p. 107)
• Step 3.6: Delete an Item (p. 109)
1. Copy the following program and paste it into a file named MoviesItemOps01.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function createItem() {
var params = {
TableName :"Movies",
Item:{
"year": 2015,
"title": "The Big New Movie",
"info":{
"plot": "Nothing happens at all.",
"rating": 0
}
}
};
docClient.put(params, function(err, data) {
if (err) {
document.getElementById('textarea').innerHTML = "Unable to add item: " +
"\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "PutItem succeeded: " +
"\n" + JSON.stringify(data, undefined, 2);
}
});
}
</script>
</head>
<body>
<input id="createItem" type="button" value="Create Item" onclick="createItem();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
Note
The primary key is required. This code adds an item that has a primary key (year,
title) and info attributes. The info attribute stores sample JSON that provides more
information about the movie.
2. Open the MoviesItemOps01.html file in your browser.
3. Choose Create Item.
{
year: 2015,
title: "The Big New Movie",
info: {
You can use the get method to read the item from the Movies table. You must specify the primary key
values, so you can read any item from Movies if you know its year and title.
1. Copy the following program and paste it into a file named MoviesItemOps02.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function readItem() {
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";
var params = {
TableName: table,
Key:{
"year": year,
"title": title
}
};
docClient.get(params, function(err, data) {
if (err) {
document.getElementById('textarea').innerHTML = "Unable to read item: " +
"\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "GetItem succeeded: " +
"\n" + JSON.stringify(data, undefined, 2);
}
});
}
</script>
</head>
<body>
<input id="readItem" type="button" value="Read Item" onclick="readItem();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
To this:
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]
}
}
1. Copy the following program and paste it into a file named MoviesItemOps03.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function updateItem() {
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";
var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "set info.rating = :r, info.plot=:p, info.actors=:a",
ExpressionAttributeValues:{
":r":5.5,
":p":"Everything happens all at once.",
":a":["Larry", "Moe", "Curly"]
},
ReturnValues:"UPDATED_NEW"
};
</script>
</head>
<body>
<input id="updateItem" type="button" value="Update Item" onclick="updateItem();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
Note
This program uses UpdateExpression to describe all updates you want to perform on the
specified item.
The ReturnValues parameter instructs Amazon DynamoDB to return only the updated
attributes ("UPDATED_NEW").
2. Open the MoviesItemOps03.html file in your browser.
3. Choose Update Item.
The following program shows how to increment the rating for a movie. Each time you run it, the
program increments this attribute by one.
1. Copy the following program and paste it into a file named MoviesItemOps04.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function increaseRating() {
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";
var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "set info.rating = info.rating + :val",
ExpressionAttributeValues:{
":val":1
},
ReturnValues:"UPDATED_NEW"
};
</script>
</head>
<body>
<input id="increaseRating" type="button" value="Increase Rating"
onclick="increaseRating();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
In this case, the item is updated only if there are more than three actors in the movie.
1. Copy the following program and paste it into a file named MoviesItemOps05.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<head>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.7.16.min.js"></script>
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function conditionalUpdate() {
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";
</script>
</head>
<body>
<input id="conditionalUpdate" type="button" value="Conditional Update"
onclick="conditionalUpdate();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
This is because the movie has three actors in it, but the condition is checking for greater than three
actors.
4. Modify the program so that the ConditionExpression looks like the following.
In the following example, you try to delete a specific movie item if its rating is 5 or less.
1. Copy the following program and paste it into a file named MoviesItemOps06.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function conditionalDelete() {
var table = "Movies";
var year = 2015;
var params = {
TableName:table,
Key:{
"year":year,
"title":title
},
ConditionExpression:"info.rating <= :val",
ExpressionAttributeValues: {
":val": 5.0
}
};
</script>
</head>
<body>
<input id="conditionalDelete" type="button" value="Conditional Delete"
onclick="conditionalDelete();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
This is because the rating for this particular movie is greater than 5.
4. Modify the program to remove the condition from params.
var params = {
TableName:table,
Key:{
"title":title,
"year":year
}
};
5. Run the program again. The delete succeeds because you removed the condition.
The primary key for the Movies table is composed of the following:
To find all movies released during a year, you need to specify only the year. You can also provide the
title to retrieve a subset of movies based on some condition (on the sort key); for example, to find
movies released in 2014 that have a title starting with the letter "A".
In addition to the query method, you can use the scan method to retrieve all the table data.
To learn more about querying and scanning data, see Working with Queries in DynamoDB (p. 458) and
Working with Scans in DynamoDB (p. 476), respectively.
Topics
• Step 4.1: Query - All Movies Released in a Year (p. 111)
• Step 4.2: Query - All Movies Released in a Year with Certain Titles (p. 113)
• Step 4.3: Scan (p. 114)
1. Copy the following program and paste it into a file named MoviesQuery01.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
function queryData() {
document.getElementById('textarea').innerHTML += "Querying for movies from 1985.";
var params = {
TableName : "Movies",
KeyConditionExpression: "#yr = :yyyy",
ExpressionAttributeNames:{
"#yr": "year"
},
ExpressionAttributeValues: {
":yyyy":1985
}
};
</script>
</head>
<body>
<input id="queryData" type="button" value="Query" onclick="queryData();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
Note
ExpressionAttributeNames provides name substitution. This is used because year is a
reserved word in Amazon DynamoDB. You can't use it directly in any expression, including
KeyConditionExpression. For this reason, you use the expression attribute name #yr.
ExpressionAttributeValues provides value substitution. This is used because you can't
use literals in any expression, including KeyConditionExpression. For this reason, you
use the expression attribute value :yyyy.
2. Open the MoviesQuery01.html file in your browser.
3. Choose Query.
Note
The preceding program shows how to query a table by its primary key attributes. In DynamoDB,
you can optionally create one or more secondary indexes on a table, and query those indexes
in the same way that you query a table. Secondary indexes give your applications additional
flexibility by allowing queries on non-key attributes. For more information, see Improving Data
Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesQuery02.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function queryData() {
document.getElementById('textarea').innerHTML += "Querying for movies from 1985.";
var params = {
TableName : "Movies",
ProjectionExpression:"#yr, title, info.genres, info.actors[0]",
KeyConditionExpression: "#yr = :yyyy and title between :letter1 and :letter2",
ExpressionAttributeNames:{
"#yr": "year"
},
ExpressionAttributeValues: {
":yyyy":1992,
":letter1": "A",
":letter2": "L"
}
};
} else {
document.getElementById('textarea').innerHTML += "Querying for movies
from 1992 - titles A-L, with genres and lead actor: " + "\n" + JSON.stringify(data,
undefined, 2);
}
});
}
</script>
</head>
<body>
<input id="queryData" type="button" value="Query" onclick="queryData();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
The following program scans the entire Movies table, which contains approximately 5,000 items. The
scan specifies the optional filter to retrieve only the movies from the 1950s (approximately 100 items),
and discard all the others.
1. Copy the following program and paste it into a file named MoviesScan.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function scanData() {
document.getElementById('textarea').innerHTML += "Scanning Movies table." + "\n";
var params = {
TableName: "Movies",
ProjectionExpression: "#yr, title, info.rating",
FilterExpression: "#yr between :start_yr and :end_yr",
ExpressionAttributeNames: {
"#yr": "year",
},
ExpressionAttributeValues: {
":start_yr": 1950,
":end_yr": 1959
}
};
docClient.scan(params, onScan);
</script>
</head>
<body>
<input id="scanData" type="button" value="Scan" onclick="scanData();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
3. Choose Scan.
Note
You also can use the Scan operation with any secondary indexes that you create on the table.
For more information, see Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesDeleteTable.html.
<!--
Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
This file is licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License. A copy of
the License is located at
http://aws.amazon.com/apache2.0/
<script>
AWS.config.update({
region: "us-west-2",
endpoint: 'http://localhost:8000',
// accessKeyId default can be used while using the downloadable version of DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
accessKeyId: "fakeMyKeyId",
// secretAccessKey default can be used while using the downloadable version of
DynamoDB.
// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});
function deleteMovies() {
var params = {
TableName : "Movies"
};
</script>
</head>
<body>
<input id="deleteTableButton" type="button" value="Delete Table"
onclick="deleteMovies();" />
<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>
</body>
</html>
AWS.config.update({region: "aws-region"});
For example, if you want to use the us-west-2 Region, set the following Region.
AWS.config.update({region: "us-west-2"});
The program now uses the Amazon DynamoDB web service in the US West (Oregon) Region.
DynamoDB is available in AWS Regions worldwide. For the complete list, see Regions and Endpoints in
the AWS General Reference. For more information about setting Regions and endpoints in your code, see
Setting the Region in the AWS SDK for JavaScript Getting Started Guide.
For more information, see Configuring AWS Credentials in Your Files Using Amazon Cognito (p. 929).
• Create a table named Movies and load sample data in JSON format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
As you work through this tutorial, you can refer to the AWS SDK for JavaScript API Reference.
Tutorial Prerequisites
• Download and run DynamoDB on your computer. For more information, see Setting Up DynamoDB
Local (Downloadable Version) (p. 46).
Note
You use the downloadable version of DynamoDB in this tutorial. For information about how to
run the same code against the DynamoDB web service, see the Summary (p. 135).
• Set up an AWS access key to use the AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Set up the AWS SDK for JavaScript:
• Install Node.js.
• Install the AWS SDK for JavaScript.
For more information, see the AWS SDK for JavaScript Getting Started Guide.
1. Copy the following program and paste it into a file named MoviesCreateTable.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName : "Movies",
KeySchema: [
{ AttributeName: "year", KeyType: "HASH"}, //Partition key
{ AttributeName: "title", KeyType: "RANGE" } //Sort key
],
AttributeDefinitions: [
{ AttributeName: "year", AttributeType: "N" },
{ AttributeName: "title", AttributeType: "S" }
],
ProvisionedThroughput: {
ReadCapacityUnits: 10,
WriteCapacityUnits: 10
}
};
Note
• You set the endpoint to indicate that you are creating the table in Amazon DynamoDB on
your computer.
• In the createTable call, you specify table name, primary key attributes, and its data
types.
• The ProvisionedThroughput parameter is required, but the downloadable version of
DynamoDB ignores it. (Provisioned throughput is beyond the scope of this tutorial.)
2. To run the program, enter the following command.
node MoviesCreateTable.js
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Topics
• Step 2.1: Download the Sample Data File (p. 120)
• Step 2.2: Load the Sample Data into the Movies Table (p. 121)
You use a sample data file that contains information about a few thousand movies from the Internet
Movie Database (IMDb). The movie data is in JSON format, as shown in the following example. For each
movie, there is a year, a title, and a JSON map named info.
[
{
"year" : ... ,
"title" : ... ,
"info" : { ... }
},
{
"year" : ...,
"title" : ...,
"info" : { ... }
},
...
• The year and title are used as the primary key attribute values for the Movies table.
• The rest of the info values are stored in a single attribute called info. This program illustrates how
you can store JSON in an Amazon DynamoDB attribute.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
3. Copy and paste the moviedata.json file into your current directory.
Step 2.2: Load the Sample Data into the Movies Table
After you download the sample data, you can run the following program to populate the Movies table.
1. Copy the following program and paste it into a file named MoviesLoadData.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
var fs = require('fs');
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
node MoviesLoadData.js
To learn more about reading and writing data, see Working with Items and Attributes (p. 375).
Topics
• Step 3.1: Create a New Item (p. 122)
• Step 3.2: Read an Item (p. 123)
• Step 3.3: Update an Item (p. 124)
• Step 3.4: Increment an Atomic Counter (p. 126)
• Step 3.5: Update an Item (Conditionally) (p. 127)
• Step 3.6: Delete an Item (p. 128)
1. Copy the following program and paste it into a file named MoviesItemOps01.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName:table,
Item:{
"year": year,
"title": title,
"info":{
"plot": "Nothing happens at all.",
"rating": 0
}
}
};
Note
The primary key is required. This code adds an item that has a primary key (year,
title) and info attributes. The info attribute stores sample JSON that provides more
information about the movie.
2. To run the program, enter the following command.
node MoviesItemOps01.js
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
You can use the get method to read the item from the Movies table. You must specify the primary key
values so that you can read any item from Movies if you know its year and title.
1. Copy the following program and paste it into a file named MoviesItemOps02.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName: table,
Key:{
"year": year,
"title": title
}
};
node MoviesItemOps02.js
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]
}
}
1. Copy the following program and paste it into a file named MoviesItemOps03.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "set info.rating = :r, info.plot=:p, info.actors=:a",
ExpressionAttributeValues:{
":r":5.5,
":p":"Everything happens all at once.",
":a":["Larry", "Moe", "Curly"]
},
ReturnValues:"UPDATED_NEW"
};
Note
This program uses UpdateExpression to describe all updates you want to perform on the
specified item.
The ReturnValues parameter instructs DynamoDB to return only the updated attributes
("UPDATED_NEW").
2. To run the program, enter the following command.
node MoviesItemOps03.js
The following program shows how to increment the rating for a movie. Each time you run the program,
it increments this attribute by one.
1. Copy the following program and paste it into a file named MoviesItemOps04.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "set info.rating = info.rating + :val",
ExpressionAttributeValues:{
":val": 1
},
ReturnValues:"UPDATED_NEW"
};
node MoviesItemOps04.js
In this case, the item is updated only if there are more than three actors in the movie.
1. Copy the following program and paste it into a file named MoviesItemOps05.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "remove info.actors[0]",
ConditionExpression: "size(info.actors) > :num",
ExpressionAttributeValues:{
":num": 3
},
ReturnValues:"UPDATED_NEW"
};
node MoviesItemOps05.js
This is because the movie has three actors in it, but the condition is checking for greater than three
actors.
3. Modify the program so that the ConditionExpression looks like the following.
In the following example, you try to delete a specific movie item if its rating is 5 or less.
1. Copy the following program and paste it into a file named MoviesItemOps06.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
ConditionExpression:"info.rating <= :val",
ExpressionAttributeValues: {
":val": 5.0
}
};
node MoviesItemOps06.js
This is because the rating for this particular movie is greater than 5.
3. Modify the program to remove the condition from params.
var params = {
TableName:table,
Key:{
"title":title,
"year":year
}
};
4. Run the program again. Now, the delete succeeds because you removed the condition.
The primary key for the Movies table is composed of the following:
To find all movies released during a year, you need to specify only the year. You can also provide the
title to retrieve a subset of movies based on some condition (on the sort key). For example, you can
find movies released in 2014 that have a title starting with the letter "A".
In addition to the query method, you also can use the scan method, which can retrieve all the table
data.
To learn more about querying and scanning data, see Working with Queries in DynamoDB (p. 458) and
Working with Scans in DynamoDB (p. 476), respectively.
Topics
• Step 4.1: Query - All Movies Released in a Year (p. 130)
• Step 4.2: Query - All Movies Released in a Year with Certain Titles (p. 131)
• Step 4.3: Scan (p. 132)
1. Copy the following program and paste it into a file named MoviesQuery01.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName : "Movies",
KeyConditionExpression: "#yr = :yyyy",
ExpressionAttributeNames:{
"#yr": "year"
},
ExpressionAttributeValues: {
":yyyy": 1985
}
};
Note
ExpressionAttributeNames provides name substitution. You use this because year is a
reserved word in Amazon DynamoDB. You can't use it directly in any expression, including
KeyConditionExpression. You use the expression attribute name #yr to address this.
ExpressionAttributeValues provides value substitution. You use this because you
cannot use literals in any expression, including KeyConditionExpression. You use the
expression attribute value :yyyy to address this.
2. To run the program, enter the following command.
node MoviesQuery01.js
Note
The preceding program shows how to query a table by its primary key attributes. In DynamoDB,
you can optionally create one or more secondary indexes on a table, and query those indexes
in the same way that you query a table. Secondary indexes give your applications additional
flexibility by allowing queries on non-key attributes. For more information, see Improving Data
Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesQuery02.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
console.log("Querying for movies from 1992 - titles A-L, with genres and lead actor");
var params = {
TableName : "Movies",
ProjectionExpression:"#yr, title, info.genres, info.actors[0]",
KeyConditionExpression: "#yr = :yyyy and title between :letter1 and :letter2",
ExpressionAttributeNames:{
"#yr": "year"
},
ExpressionAttributeValues: {
":yyyy": 1992,
":letter1": "A",
":letter2": "L"
}
};
node MoviesQuery02.js
The following program scans the entire Movies table, which contains approximately 5,000 items. The
scan specifies the optional filter to retrieve only the movies from the 1950s (approximately 100 items),
and discard all of the others.
1. Copy the following program and paste it into a file named MoviesScan.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName: "Movies",
ProjectionExpression: "#yr, title, info.rating",
FilterExpression: "#yr between :start_yr and :end_yr",
ExpressionAttributeNames: {
"#yr": "year",
},
ExpressionAttributeValues: {
":start_yr": 1950,
":end_yr": 1959
}
};
node MoviesScan.js
Note
You can also use the Scan operation with any secondary indexes that you have created on the
table. For more information, see Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesDeleteTable.js.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});
var params = {
TableName : "Movies"
};
node MoviesDeleteTable.js
Summary
In this tutorial, you created the Movies table in Amazon DynamoDB on your computer and performed
basic operations. The downloadable version of DynamoDB is useful during application development
and testing. However, when you're ready to run your application in a production environment, you must
modify your code so that it uses the DynamoDB web service.
AWS.config.update({endpoint: "https://dynamodb.aws-region.amazonaws.com"});
For example, if you want to use the us-west-2 Region, set the following endpoint.
AWS.config.update({endpoint: "https://dynamodb.us-west-2.amazonaws.com"});
Instead of using DynamoDB on your computer, the program now uses the DynamoDB web service
endpoint in the US West (Oregon) Region.
DynamoDB is available in AWS Regions worldwide. For the complete list, see Regions and Endpoints in
the AWS General Reference. For more information about setting Regions and endpoints in your code, see
Setting the Region in the AWS SDK for JavaScript Developer Guide.
• Create a table named Movies using a utility program written in C#, and load sample data in JSON
format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
The DynamoDB module of the AWS SDK for .NET offers several programming models for different use
cases. In this exercise, the C# code uses the document model, which provides a level of abstraction that is
often convenient. It also uses the low-level API, which handles nested attributes more effectively.
For information about the document model API, see .NET: Document Model (p. 276). For information
about the low-level API, see Working with DynamoDB Tables in .NET (p. 368).
Topics
• .NET and DynamoDB Tutorial Prerequisites (p. 136)
• Step 1: Create a DynamoDB Client (p. 137)
• Step 2: Create a DynamoDB Table Using the Low-Level API (p. 139)
• Step 3: Load Sample Data into the DynamoDB Table (p. 142)
Before you begin, follow these steps to ensure that you have all the prerequisites needed to complete
the tutorial:
• Use a computer that is running a recent version of Windows and a current version of Microsoft Visual
Studio. If you don't have Visual Studio installed, you can download a free copy of the Community
edition from the Microsoft Visual Studio website.
• Download and run DynamoDB (downloadable version). For more information, see Setting Up
DynamoDB Local (Downloadable Version) (p. 46).
Note
You use the downloadable version of DynamoDB in this tutorial. For more information
about how to run the same code against the DynamoDB web service, see Step 1: Create a
DynamoDB Client (p. 137).
• Set up an AWS access key to use the AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Set up a security profile for DynamoDB in Visual Studio. For step-by-step instructions, see .NET Code
Examples (p. 333).
• Open the getting started demo solution that is used in this tutorial in Visual Studio:
1. On the Build menu, choose Build Solution (or press Ctrl+Shift+B). The solution should build
successfully.
2. Make sure that the Solution Explorer pane is being displayed and pinned in Visual Studio. If it
isn't, you can find it in the View menu, or by pressing Ctrl+Alt+L.
3. In Solution Explorer, open the 00_Main.cs file. This is the file that controls the execution of the
demo program that is used in this tutorial.
Note
This tutorial shows how to use asynchronous methods rather than synchronous methods. This
is because .NET core supports only asynchronous methods, and also because the asynchronous
model is generally preferable when performance is crucial. For more information, see AWS
Asynchronous APIs for .NET.
To install the NuGet package for the DynamoDB module of the AWS SDK for .NET version 3 in your own
programs, open the NuGet Package Manager Console on the Tools menu in Visual Studio. Then enter
the following command at the PM> prompt.
In a similar way, you can use the NuGet Package Manager Console to load the Json.NET library into
your own projects in Visual Studio. At the PM> prompt, enter the following command.
Next Step
Step 1: Create a DynamoDB Client (p. 137)
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Net.Sockets;
using Amazon.DynamoDBv2;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*-----------------------------------------------------------------------------------
* If you are creating a client for the DynamoDB service, make sure your credentials
* are set up first, as explained in:
* https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/
SettingUp.DynamoWebService.html,
*
* If you are creating a client for DynamoDBLocal (for testing purposes),
* DynamoDB-Local should be started first. For most simple testing, you can keep
* data in memory only, without writing anything to disk. To do this, use the
* following command line:
*
* java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -inMemory
*
* For information about DynamoDBLocal, see:
* https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/
DynamoDBLocal.html.
*-----------------------------------------------------------------------------------
*/
/*--------------------------------------------------------------------------
* createClient
*--------------------------------------------------------------------------*/
public static bool createClient( bool useDynamoDBLocal )
{
if( useDynamoDBLocal )
{
operationSucceeded = false;
operationFailed = false;
// First, check to see whether anyone is listening on the DynamoDB local port
// (by default, this is port 8000, so if you are using a different port, modify
this accordingly)
bool localFound = false;
try
{
using (var tcp_client = new TcpClient())
{
var result = tcp_client.BeginConnect("localhost", 8000, null, null);
localFound = result.AsyncWaitHandle.WaitOne(3000); // Wait 3 seconds
tcp_client.EndConnect(result);
}
}
catch
{
localFound = false;
}
if( !localFound )
{
Console.WriteLine("\n ERROR: DynamoDB Local does not appear to have been
started..." +
"\n (checked port 8000)");
operationFailed = true;
return (false);
}
else
{
try { client = new AmazonDynamoDBClient( ); }
catch( Exception ex )
{
Main calls this function with the useDynamoDBLocal parameter set to true. Therefore the local test
version of DynamoDB must already be running on your computer using the default port (8000), or the
call fails. If you do not have it installed yet, see Running DynamoDB on Your Computer (p. 46).
Setting the useDynamoDBLocal parameter to false creates a client for the DynamoDB service itself
rather than the local test program.
Next Step
Step 2: Create a DynamoDB Table Using the Low-Level API (p. 139)
In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you create a table named Movies in
Amazon DynamoDB. The primary key for the table is composed of the following attributes:
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.Model;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* CreatingTable_async
*--------------------------------------------------------------------------*/
public static async Task CreatingTable_async( string new_table_name,
List<AttributeDefinition> table_attributes,
List<KeySchemaElement> table_key_schema,
ProvisionedThroughput provisionedThroughput )
{
Console.WriteLine( " -- Creating a new table named {0}...", new_table_name );
if( await checkingTableExistence_async( new_table_name ) )
{
Console.WriteLine( " -- No need to create a new table..." );
return;
}
if( operationFailed )
return;
operationSucceeded = false;
Task<bool> newTbl = CreateNewTable_async( new_table_name,
table_attributes,
table_key_schema,
provisionedThroughput );
await newTbl;
}
/*--------------------------------------------------------------------------
* checkingTableExistence_async
*--------------------------------------------------------------------------*/
static async Task<bool> checkingTableExistence_async( string tblNm )
{
DescribeTableResponse descResponse;
operationSucceeded = false;
operationFailed = false;
ListTablesResponse tblResponse = await Ddb_Intro.client.ListTablesAsync();
if (tblResponse.TableNames.Contains(tblNm))
{
Console.WriteLine(" A table named {0} already exists in DynamoDB!", tblNm);
/*--------------------------------------------------------------------------
* CreateNewTable_async
*--------------------------------------------------------------------------*/
public static async Task<bool> CreateNewTable_async( string table_name,
List<AttributeDefinition>
table_attributes,
List<KeySchemaElement>
table_key_schema,
ProvisionedThroughput
provisioned_throughput )
{
CreateTableRequest request;
CreateTableResponse response;
operationSucceeded = false;
operationFailed = false;
try
{
Task<CreateTableResponse> makeTbl = Ddb_Intro.client.CreateTableAsync( request );
response = await makeTbl;
Console.WriteLine( " -- Created the \"{0}\" table successfully!", table_name );
operationSucceeded = true;
}
catch( Exception ex )
{
Console.WriteLine( " FAILED to create the new table, because: {0}.",
ex.Message );
operationFailed = true;
return( false );
}
The DynamoDB_intro sample uses asynchronous methods rather than synchronous methods wherever
possible. This is because .NET core supports only asynchronous methods, and the asynchronous model
is generally preferable when performance is crucial. For more information, see AWS Asynchronous APIs
for .NET.
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Next Step
Step 3: Load Sample Data into the DynamoDB Table (p. 142)
For each movie, moviedata.json defines a year name-value pair, a title name-value pair, and a
complex info object, as illustrated by the following example.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
Before loading the moviedata.json file, the Main function in DynamoDB_intro checks to
determine whether the Movies table exists and is still empty. If so, it waits on an asynchronous
LoadingData_async function that is implemented in the 03_LoadingData.cs file.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* LoadingData_async
*--------------------------------------------------------------------------*/
public static async Task LoadingData_async( Table table, string filePath )
{
JArray movieArray;
/*--------------------------------------------------------------------------
* ReadJsonMovieFile_async
*--------------------------------------------------------------------------*/
public static async Task<JArray> ReadJsonMovieFile_async( string JsonMovieFilePath )
{
StreamReader sr = null;
JsonTextReader jtr = null;
JArray movieArray = null;
return ( null );
}
/*--------------------------------------------------------------------------
* LoadJsonMovieData_async
*--------------------------------------------------------------------------*/
public static async Task LoadJsonMovieData_async( Table moviesTable, JArray
moviesArray )
{
operationSucceeded = false;
operationFailed = false;
int n = moviesArray.Count;
Console.Write( " -- Starting to load {0:#,##0} movie records into the Movies
table asynchronously...\n" + "" +
" Wrote: ", n );
for( int i = 0, j = 99; i < n; i++ )
{
try
{
string itemJson = moviesArray[i].ToString();
Document doc = Document.FromJson(itemJson);
Task putItem = moviesTable.PutItemAsync(doc);
if( i >= j )
{
j++;
Console.Write( "{0,5:#,##0}, ", j );
if( j % 1000 == 0 )
Console.Write( "\n " );
j += 99;
}
await putItem;
}
catch( Exception ex )
{
Console.WriteLine( "\n ERROR: Could not write the movie record #{0:#,##0},
because:\n {1}",
i, ex.Message );
operationFailed = true;
break;
}
}
if( !operationFailed )
{
operationSucceeded = true;
Console.WriteLine( "\n -- Finished writing all movie records to DynamoDB!" );
}
}
}
When the data has been read successfully, LoadingData_async waits on LoadJsonMovieData_async
to load the movie records into the Movies table using the DynamoDB document-model
Table.PutItemAsync API. For information about the document model API, see .NET: Document
Model (p. 276).
Next Step
Step 4: Add a Movie to the DynamoDB Table (p. 145)
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.DocumentModel;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* WritingNewMovie
*--------------------------------------------------------------------------*/
public static async Task WritingNewMovie_async( Document newItem )
{
operationSucceeded = false;
operationFailed = false;
WritingNewMovie_async begins by checking to determine whether the new movie has already been
added to the Movies table. If it has not, it waits for the DynamoDB Table.PutItemAsyn method to
add the new movie record.
Next Step
Step 5: Read and Display a Record from the DynamoDB Table (p. 146)
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.DocumentModel;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* ReadingMovie_async
*--------------------------------------------------------------------------*/
public static async Task<bool> ReadingMovie_async( int year, string title, bool
report )
{
// Create Primitives for the HASH and RANGE portions of the primary key
Primitive hash = new Primitive(year.ToString(), true);
Primitive range = new Primitive(title, false);
operationSucceeded = false;
operationFailed = false;
try
{
Task<Document> readMovie = moviesTable.GetItemAsync(hash, range, token);
if( report )
Console.WriteLine( " -- Reading the {0} movie \"{1}\" from the Movies table...",
year, title );
movie_record = await readMovie;
if( movie_record == null )
{
if( report )
Console.WriteLine( " -- Sorry, that movie isn't in the Movies table." );
return ( false );
}
else
{
if( report )
Console.WriteLine( " -- Found it! The movie record looks like this:\n" +
movie_record.ToJsonPretty( ) );
operationSucceeded = true;
return ( true );
}
}
catch( Exception ex )
{
Console.WriteLine( " FAILED to get the movie, because: {0}.", ex.Message );
operationFailed = true;
}
return ( false );
}
}
Next Step
Step 6: Update the New Movie Record in the DynamoDB Table (p. 147)
Topics
• Change Plot and Rating, and Add Actors (p. 148)
• Increment the Movie Rating Atomically (p. 149)
• Try to Update Using a Condition That Fails (p. 150)
• For More Information (p. 150)
Setting ReturnValues to NONE specifies that no update information should be returned. However,
when Main then waits on UpdatingMovie_async, it sets the report parameter to true. This causes
UpdatingMovie_async to change ReturnValues to ALL_NEW, meaning that the updated item should
be returned in its entirety.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text;
using Amazon.DynamoDBv2.Model;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* UpdatingMovie_async
*--------------------------------------------------------------------------*/
public static async Task<bool> UpdatingMovie_async( UpdateItemRequest updateRequest,
bool report )
{
UpdateItemResponse updateResponse = null;
operationSucceeded = false;
operationFailed = false;
if( report )
{
Console.WriteLine( " -- Trying to update a movie item..." );
updateRequest.ReturnValues = "ALL_NEW";
}
try
{
updateResponse = await client.UpdateItemAsync( updateRequest );
Console.WriteLine( " -- SUCCEEDED in updating the movie item!" );
}
catch( Exception ex )
{
Console.WriteLine( " -- FAILED to update the movie item, because:\n
{0}.", ex.Message );
if( updateResponse != null )
Console.WriteLine( " -- The status code was " +
updateResponse.HttpStatusCode.ToString( ) );
operationFailed = true;return ( false );
}
if( report )
{
Console.WriteLine( " Here is the updated movie informtion:" );
Console.WriteLine( movieAttributesToJson( updateResponse.Attributes ) );
}
operationSucceeded = true;
return ( true );
}
}
}
Where the document model has a handy Document.ToJsonPretty( ) method for displaying
document content, working with low-level attribute values is a little more complicated. The
00b_DDB_Attributes.cs file can provide some examples of how to access and work with
AttributeValue objects.
To increment the rating value in the movie that you just created, the Main function makes the following
changes in the UpdateItemRequest that it used in the previous update.
To demonstrate this, the Main function makes the following changes to the UpdateItemRequest that
it just used to increment the movie rating.
The update can now occur only if there are more than three actors in the movie record being
updated. Because there are only three actors listed, the condition fails when Main waits on
UpdatingMovie_async, and the update does not occur.
Next Step
Step 7: Conditionally Delete (p. 150)
The Main function then passes the Expression as one of the parameters of DeletingItem_async
and waits on it. DeletingItem_async is implemented in the 07_DeletingItem.cs file.
/**
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* DeletingItem_async
*--------------------------------------------------------------------------*/
public static async Task<bool> DeletingItem_async( Table table, int year, string title,
Expression condition=null )
{
Document deletedItem = null;
operationSucceeded = false;
operationFailed = false;
// Create Primitives for the HASH and RANGE portions of the primary key
Primitive hash = new Primitive(year.ToString(), true);
Primitive range = new Primitive(title, false);
DeleteItemOperationConfig deleteConfig = new DeleteItemOperationConfig( );
deleteConfig.ConditionalExpression = condition;
deleteConfig.ReturnValues = ReturnValues.AllOldAttributes;
Console.WriteLine( " -- Trying to delete the {0} movie \"{1}\"...", year, title );
try
{
Task<Document> delItem = table.DeleteItemAsync( hash, range, deleteConfig );
deletedItem = await delItem;
}
catch( Exception ex )
{
Console.WriteLine( " FAILED to delete the movie item, for this reason:\n
{0}\n", ex.Message );
operationFailed = true;
return ( false );
}
Console.WriteLine( " -- SUCCEEDED in deleting the movie record that looks like
this:\n" +
deletedItem.ToJsonPretty( ) );
operationSucceeded = true;
return ( true );
}
}
Because the movie's rating is 6.5, which is higher than 5.0, the condition is not met, and the deletion
fails.
Then, when the Main function changes the rating threshold in the condition to 7.0 instead of 5.0, the
deletion succeeds.
Next Step
Step 8: Query a DynamoDB Table with .NET (p. 152)
Topics
• Use a Simple Document Model Search to Query for 1985 Movies (p. 152)
• Use a QueryOperationConfig to Create a More Complex Query Search (p. 154)
• Use a Low-Level Query to Find 1992 Movies with Titles Between 'M...' and 'Tzz...' (p. 154)
• Next Step (p. 155)
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Text;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DocumentModel;
using System.Collections.Generic;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* SearchListing_async
*--------------------------------------------------------------------------*/
public static async Task<bool> SearchListing_async( Search search )
{
int i = 0;
List<Document> docList = new List<Document>( );
do
{
try
{
getNextBatch = search.GetNextSetAsync( );
docList = await getNextBatch;
}
catch( Exception ex )
{
Console.WriteLine( " FAILED to get the next batch of movies from Search!
Reason:\n " +
ex.Message );
operationFailed = true;
return ( false );
}
/*--------------------------------------------------------------------------
* ClientQuerying_async
*--------------------------------------------------------------------------*/
public static async Task<bool> ClientQuerying_async( QueryRequest qRequest )
{
operationSucceeded = false;
operationFailed = false;
QueryResponse qResponse;
try
{
Task<QueryResponse> clientQueryTask = client.QueryAsync( qRequest );
qResponse = await clientQueryTask;
}
catch( Exception ex )
{
Console.WriteLine( " The low-level query FAILED, because:\n {0}.",
ex.Message );
operationFailed = true;
return ( false );
}
Console.WriteLine( " -- The low-level query succeeded, and returned {0} movies!",
qResponse.Items.Count );
if( !pause( ) )
{
operationFailed = true;
return ( false );
}
Console.WriteLine( " Here are the movies retrieved:" +
"
--------------------------------------------------------------------------" );
foreach( Dictionary<string, AttributeValue> item in qResponse.Items )
showMovieAttrsShort( item );
Once again, it then creates a Search object by calling the Table.Query API, this time with the
QueryOperationConfig object as the only parameter.
And again, it waits on SearchListing_async to retrieve and display the query results.
Next Step
Step 9: Scan the Movies Table with .NET (p. 155)
Topics
• Use a Document Model Search to Scan for 1950s Movies (p. 155)
• Use a Low-Level Scan to Retrieve 1960s Movies (p. 155)
• Next Step (p. 156)
To obtain a Search object for the scan, it passes the ScanOperationConfig object to Table.Scan.
Using the Search object, it then waits on SearchListing_async (implemented in 08_Querying.cs)
to retrieve and display the scan results.
},
FilterExpression = "#yr between :y_a and :y_z",
ProjectionExpression = "#yr, title, info.actors[0], info.directors,
info.running_time_secs"
};
Next Step
Step 10: Delete the Movies Table with .NET (p. 156)
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Threading.Tasks;
namespace DynamoDB_intro
{
public static partial class Ddb_Intro
{
/*--------------------------------------------------------------------------
* DeletingTable_async
*--------------------------------------------------------------------------*/
public static async Task<bool> DeletingTable_async( string tableName )
{
operationSucceeded = false;
operationFailed = false;
catch( Exception ex )
{
Console.WriteLine( " ERROR: Failed to delete the table, because:\n "
+ ex.Message );
operationFailed = true;
return ( false );
}
Console.WriteLine( " -- Successfully deleted the table!" );
operationSucceeded = true;
pause( );
return ( true );
}
}
• Create a table called Movies and load sample data in JSON format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
As you work through this tutorial, you can refer to the AWS SDK for PHP Developer Guide. The Amazon
DynamoDB section in the AWS SDK for PHP API Reference describes the parameters and results for
DynamoDB operations.
Tutorial Prerequisites
• Download and run DynamoDB on your computer. For more information, see Setting Up DynamoDB
Local (Downloadable Version) (p. 46).
Note
You use the downloadable version of DynamoDB in this tutorial. For information about how to
run the same code against the DynamoDB service, see the Summary (p. 177).
• Set up an AWS access key to use the AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Set up the AWS SDK for PHP:
• Install PHP.
• Install the SDK for PHP.
For more information, see Getting Started in the AWS SDK for PHP Getting Started Guide.
1. Copy the following program and paste it into a file named MoviesCreateTable.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
$dynamodb = $sdk->createDynamoDb();
$params = [
'TableName' => 'Movies',
'KeySchema' => [
[
'AttributeName' => 'year',
'KeyType' => 'HASH' //Partition key
],
[
'AttributeName' => 'title',
'KeyType' => 'RANGE' //Sort key
]
],
'AttributeDefinitions' => [
[
'AttributeName' => 'year',
'AttributeType' => 'N'
],
[
'AttributeName' => 'title',
'AttributeType' => 'S'
],
],
'ProvisionedThroughput' => [
'ReadCapacityUnits' => 10,
'WriteCapacityUnits' => 10
]
];
try {
$result = $dynamodb->createTable($params);
echo 'Created table. Status: ' .
$result['TableDescription']['TableStatus'] ."\n";
Note
• You set the endpoint to indicate that you are creating the table in Amazon DynamoDB on
your computer.
• In the createTable call, you specify the table name, primary key attributes, and its data
types.
• The ProvisionedThroughput parameter is required, but the downloadable version of
DynamoDB ignores it. (Provisioned throughput is beyond the scope of this exercise.)
2. To run the program, enter the following command.
php MoviesCreateTable.php
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Topics
• Step 2.1: Download the Sample Data File (p. 160)
• Step 2.2: Load the Sample Data into the Movies Table (p. 160)
This scenario uses a sample data file that contains information about a few thousand movies from the
Internet Movie Database (IMDb). The movie data is in JSON format, as shown in the following example.
For each movie, there is a year, a title, and a JSON map named info.
[
{
"year" : ... ,
"title" : ... ,
"info" : { ... }
},
{
"year" : ...,
"title" : ...,
"info" : { ... }
},
...
• The year and title are used as the primary key attribute values for the Movies table.
• The rest of the info values are stored in a single attribute called info. This program illustrates how
you can store JSON in an Amazon DynamoDB attribute.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
Step 2.2: Load the Sample Data into the Movies Table
After you download the sample data, you can run the following program to populate the Movies table.
1. Copy the following program and paste it into a file named MoviesLoadData.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = $movie['year'];
$title = $movie['title'];
$info = $movie['info'];
$json = json_encode([
'year' => $year,
'title' => $title,
'info' => $info
]);
$params = [
'TableName' => $tableName,
'Item' => $marshaler->marshalJson($json)
];
try {
$result = $dynamodb->putItem($params);
echo "Added movie: " . $movie['year'] . " " . $movie['title'] . "\n";
} catch (DynamoDbException $e) {
echo "Unable to add movie:\n";
echo $e->getMessage() . "\n";
break;
}
Note
The DynamoDB Marshaler class has methods for converting JSON documents and PHP
arrays to the DynamoDB format. In this program, $marshaler->marshalJson($json)
takes a JSON document and converts it into a DynamoDB item.
2. To run the program, enter the following command.
php MoviesLoadData.php
To learn more about reading and writing data, see Working with Items and Attributes (p. 375).
Topics
• Step 3.1: Create a New Item (p. 162)
• Step 3.2: Read an Item (p. 163)
• Step 3.3: Update an Item (p. 165)
• Step 3.4: Increment an Atomic Counter (p. 167)
• Step 3.5: Update an Item (Conditionally) (p. 168)
• Step 3.6: Delete an Item (p. 169)
1. Copy the following program and paste it into a file named MoviesItemOps01.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = 2015;
$title = 'The Big New Movie';
$item = $marshaler->marshalJson('
{
"year": ' . $year . ',
"title": "' . $title . '",
"info": {
"plot": "Nothing happens at all.",
"rating": 0
}
}
');
$params = [
'TableName' => 'Movies',
'Item' => $item
];
try {
$result = $dynamodb->putItem($params);
echo "Added item: $year - $title\n";
Note
The primary key is required. This code adds an item that has primary key (year, title) and
info attributes. The info attribute stores a map that provides more information about the
movie.
2. To run the program, enter the following command.
php MoviesItemOps01.php
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
You can use the getItem method to read the item from the Movies table. You must specify the primary
key values so that you can read any item from Movies if you know its year and title.
1. Copy the following program and paste it into a file named MoviesItemOps02.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = 2015;
$title = 'The Big New Movie';
$key = $marshaler->marshalJson('
{
"year": ' . $year . ',
"title": "' . $title . '"
}
');
$params = [
'TableName' => $tableName,
'Key' => $key
];
try {
$result = $dynamodb->getItem($params);
print_r($result["Item"]);
php MoviesItemOps02.php
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]
}
}
1. Copy the following program and paste it into a file named MoviesItemOps03.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = 2015;
$title = 'The Big New Movie';
$key = $marshaler->marshalJson('
{
"year": ' . $year . ',
"title": "' . $title . '"
}
');
$eav = $marshaler->marshalJson('
{
":r": 5.5 ,
":p": "Everything happens all at once.",
":a": [ "Larry", "Moe", "Curly" ]
}
');
$params = [
'TableName' => $tableName,
'Key' => $key,
'UpdateExpression' =>
'set info.rating = :r, info.plot=:p, info.actors=:a',
'ExpressionAttributeValues'=> $eav,
'ReturnValues' => 'UPDATED_NEW'
];
try {
$result = $dynamodb->updateItem($params);
echo "Updated item.\n";
print_r($result['Attributes']);
Note
This program uses UpdateExpression to describe all updates you want to perform on the
specified item.
The ReturnValues parameter instructs Amazon DynamoDB to return only the updated
attributes (UPDATED_NEW).
2. To run the program, enter the following command.
php MoviesItemOps03.php
The following program shows how to increment the rating for a movie. Each time you run the program,
it increments this attribute by one.
1. Copy the following program and paste it into a file named MoviesItemOps04.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = 2015;
$title = 'The Big New Movie';
$key = $marshaler->marshalJson('
{
"year": ' . $year . ',
"title": "' . $title . '"
}
');
$eav = $marshaler->marshalJson('
{
":val": 1
}
');
$params = [
'TableName' => $tableName,
'Key' => $key,
'UpdateExpression' => 'set info.rating = info.rating + :val',
'ExpressionAttributeValues'=> $eav,
'ReturnValues' => 'UPDATED_NEW'
];
try {
$result = $dynamodb->updateItem($params);
echo "Updated item. ReturnValues are:\n";
print_r($result['Attributes']);
php MoviesItemOps04.php
In this case, the item is updated only if there are more than three actors in the movie.
1. Copy the following program and paste it into a file named MoviesItemOps05.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = 2015;
$title = 'The Big New Movie';
$key = $marshaler->marshalJson('
{
"year": ' . $year . ',
"title": "' . $title . '"
}
');
$eav = $marshaler->marshalJson('
{
":num": 3
}
');
$params = [
'TableName' => $tableName,
'Key' => $key,
'UpdateExpression' => 'remove info.actors[0]',
'ConditionExpression' => 'size(info.actors) > :num',
'ExpressionAttributeValues'=> $eav,
'ReturnValues' => 'UPDATED_NEW'
];
try {
$result = $dynamodb->updateItem($params);
echo "Updated item. ReturnValues are:\n";
print_r($result['Attributes']);
php MoviesItemOps05.php
The program fails because the movie has three actors in it, but the condition is checking for greater
than three actors.
3. Modify the program so that the ConditionExpression looks like the following.
In the following example, you try to delete a specific movie item if its rating is 5 or less.
1. Copy the following program and paste it into a file named MoviesItemOps06.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$year = 2015;
$title = 'The Big New Movie';
$key = $marshaler->marshalJson('
{
"year": ' . $year . ',
"title": "' . $title . '"
}
');
$eav = $marshaler->marshalJson('
{
":val": 5
}
');
$params = [
'TableName' => $tableName,
'Key' => $key,
'ConditionExpression' => 'info.rating <= :val',
'ExpressionAttributeValues'=> $eav
];
try {
$result = $dynamodb->deleteItem($params);
echo "Deleted item.\n";
php MoviesItemOps06.php
The program fails because the rating for this particular move is greater than 5.
3. Modify the program to remove the condition.
$params = [
'TableName' => $tableName,
'Key' => $key
];
4. Run the program. Now, the delete succeeds because you removed the condition.
The primary key for the Movies table is composed of the following:
To find all movies released during a year, you need to specify only the year. You can also provide the
title to retrieve a subset of movies based on some condition (on the sort key). For example, to find
movies released in 2014 that have a title starting with the letter "A".
In addition to the query method, you can use the scan method to retrieve all of the table data.
To learn more about querying and scanning data, see Working with Queries in DynamoDB (p. 458) and
Working with Scans in DynamoDB (p. 476), respectively.
Topics
• Step 4.1: Query - All Movies Released in a Year (p. 171)
• Step 4.2: Query - All Movies Released in a Year with Certain Titles (p. 173)
• Step 4.3: Scan (p. 174)
1. Copy the following program and paste it into a file named MoviesQuery01.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$eav = $marshaler->marshalJson('
{
":yyyy": 1985
}
');
$params = [
'TableName' => $tableName,
'KeyConditionExpression' => '#yr = :yyyy',
'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
'ExpressionAttributeValues'=> $eav
];
try {
$result = $dynamodb->query($params);
Note
php MoviesItemQuery01.php
Note
The preceding program shows how to query a table by its primary key attributes. In Amazon
DynamoDB, you can optionally create one or more secondary indexes on a table, and query
those indexes in the same way that you query a table. Secondary indexes give your applications
additional flexibility by allowing queries on non-key attributes. For more information, see
Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesQuery02.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$tableName = 'Movies';
$eav = $marshaler->marshalJson('
{
":yyyy":1992,
":letter1": "A",
":letter2": "L"
}
');
$params = [
'TableName' => $tableName,
'ProjectionExpression' => '#yr, title, info.genres, info.actors[0]',
'KeyConditionExpression' =>
'#yr = :yyyy and title between :letter1 and :letter2',
'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
'ExpressionAttributeValues'=> $eav
];
echo "Querying for movies from 1992 - titles A-L, with genres and lead actor\n";
try {
$result = $dynamodb->query($params);
php MoviesQuery02.php
The following program scans the entire Movies table, which contains approximately 5,000 items. The
scan specifies the optional filter to retrieve only the movies from the 1950s (approximately 100 items),
and discard all of the others.
1. Copy the following program and paste it into a file named MoviesScan.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;
$dynamodb = $sdk->createDynamoDb();
$params = [
'TableName' => 'Movies',
'ProjectionExpression' => '#yr, title, info.rating',
'FilterExpression' => '#yr between :start_yr and :end_yr',
'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
'ExpressionAttributeValues'=> $eav
];
try {
while (true) {
$result = $dynamodb->scan($params);
if (isset($result['LastEvaluatedKey'])) {
$params['ExclusiveStartKey'] = $result['LastEvaluatedKey'];
} else {
break;
}
}
php MoviesScan.php
Note
You can also use the Scan operation with any secondary indexes that you have created on the
table. For more information, see Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesDeleteTable.php.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
require 'vendor/autoload.php';
date_default_timezone_set('UTC');
use Aws\DynamoDb\Exception\DynamoDbException;
$dynamodb = $sdk->createDynamoDb();
$params = [
'TableName' => 'Movies'
];
try {
$result = $dynamodb->deleteTable($params);
echo "Deleted table.\n";
php MoviesDeleteTable.php
Summary
In this tutorial, you created the Movies table in Amazon DynamoDB on your computer and performed
basic operations. The downloadable version of DynamoDB is useful during application development and
testing. However, when you're ready to run your application in a production environment, you need to
modify your code so that it uses the DynamoDB web service.
Remove the endpoint parameter so that the code looks like the following.
After you remove this line, the code can access the DynamoDB web service in the AWS Region specified
by the region config value. For example, the following line specifies that you want to use the US West
(Oregon) Region.
Instead of using the downloadable version of DynamoDB on your computer, the program now uses the
DynamoDB service endpoint in the US West (Oregon) Region.
DynamoDB is available in AWS Regions worldwide. For the complete list, see Regions and Endpoints in
the AWS General Reference. For more information about setting Regions and endpoints in your code, see
the boto: A Python interface to Amazon Web Services.
• Create a table called Movies and load sample data in JSON format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
As you work through this tutorial, you can refer to the AWS SDK for Python (Boto) documentation. The
following sections are specific to DynamoDB:
• DynamoDB tutorial
• DynamoDB low-level client
Tutorial Prerequisites
• Download and run DynamoDB on your computer. For more information, see Setting Up DynamoDB
Local (Downloadable Version) (p. 46).
Note
You use the downloadable version of DynamoDB in this tutorial. In the Summary (p. 194),
we explain how to run the same code against the DynamoDB web service.
• Set up an AWS access key to use the AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Install Python 2.6 or later. For more information, see https://www.python.org/downloads. For
instructions, see Quickstart in the Boto 3 documentation.
1. Copy the following program and paste it into a file named MoviesCreateTable.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
table = dynamodb.create_table(
TableName='Movies',
KeySchema=[
{
'AttributeName': 'year',
'KeyType': 'HASH' #Partition key
},
{
'AttributeName': 'title',
'KeyType': 'RANGE' #Sort key
}
],
AttributeDefinitions=[
{
'AttributeName': 'year',
'AttributeType': 'N'
},
{
'AttributeName': 'title',
'AttributeType': 'S'
},
],
ProvisionedThroughput={
'ReadCapacityUnits': 10,
'WriteCapacityUnits': 10
}
)
Note
• You set the endpoint to indicate that you are creating the table in the downloadable
version of DynamoDB on your computer.
• In the create_table call, you specify the table name, primary key attributes, and its
data types.
• The ProvisionedThroughput parameter is required. However, the downloadable
version of DynamoDB ignores it. (Provisioned throughput is beyond the scope of this
exercise.)
• These examples use the Python 3 style print function. The line from __future__
import print_function enables Python 3 printing in Python 2.6 and later.
2. To run the program, enter the following command.
python MoviesCreateTable.py
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Topics
• Step 2.1: Download the Sample Data File (p. 181)
• Step 2.2: Load the Sample Data into the Movies Table (p. 181)
This scenario uses a sample data file that contains information about a few thousand movies from the
Internet Movie Database (IMDb). The movie data is in JSON format, as shown in the following example.
For each movie, there is a year, a title, and a JSON map named info.
[
{
"year" : ... ,
"title" : ... ,
"info" : { ... }
},
{
"year" : ...,
"title" : ...,
"info" : { ... }
},
...
• The year and title are used as the primary key attribute values for the Movies table.
• The rest of the info values are stored in a single attribute called info. This program illustrates how
you can store JSON in an Amazon DynamoDB attribute.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
Step 2.2: Load the Sample Data into the Movies Table
After you download the sample data, you can run the following program to populate the Movies table.
1. Copy the following program and paste it into a file named MoviesLoadData.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
table = dynamodb.Table('Movies')
table.put_item(
Item={
'year': year,
'title': title,
'info': info,
}
)
python MoviesLoadData.py
To learn more about reading and writing data, see Working with Items and Attributes (p. 375).
Topics
• Step 3.1: Create a New Item (p. 182)
• Step 3.2: Read an Item (p. 183)
• Step 3.3: Update an Item (p. 184)
• Step 3.4: Increment an Atomic Counter (p. 186)
• Step 3.5: Update an Item (Conditionally) (p. 187)
• Step 3.6: Delete an Item (p. 188)
1. Copy the following program and paste it into a file named MoviesItemOps01.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
table = dynamodb.Table('Movies')
response = table.put_item(
Item={
'year': year,
'title': title,
'info': {
'plot':"Nothing happens at all.",
'rating': decimal.Decimal(0)
}
}
)
print("PutItem succeeded:")
print(json.dumps(response, indent=4, cls=DecimalEncoder))
Note
• The primary key is required. This code adds an item that has primary key (year, title)
and info attributes. The info attribute stores sample JSON that provides more
information about the movie.
• The DecimalEncoder class is used to print out numbers stored using the Decimal class.
The Boto SDK uses the Decimal class to hold Amazon DynamoDB number values.
2. To run the program, enter the following command.
python MoviesItemOps01.py
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
You can use the get_item method to read the item from the Movies table. You must specify the
primary key values so that you can read any item from Movies if you know its year and title.
1. Copy the following program and paste it into a file named MoviesItemOps02.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
from boto3.dynamodb.conditions import Key, Attr
from botocore.exceptions import ClientError
table = dynamodb.Table('Movies')
try:
response = table.get_item(
Key={
'year': year,
'title': title
}
)
except ClientError as e:
print(e.response['Error']['Message'])
else:
item = response['Item']
print("GetItem succeeded:")
print(json.dumps(item, indent=4, cls=DecimalEncoder))
python MoviesItemOps02.py
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]
}
}
1. Copy the following program and paste it into a file named MoviesItemOps03.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
table = dynamodb.Table('Movies')
response = table.update_item(
Key={
'year': year,
'title': title
},
UpdateExpression="set info.rating = :r, info.plot=:p, info.actors=:a",
ExpressionAttributeValues={
':r': decimal.Decimal(5.5),
':p': "Everything happens all at once.",
':a': ["Larry", "Moe", "Curly"]
},
ReturnValues="UPDATED_NEW"
)
print("UpdateItem succeeded:")
print(json.dumps(response, indent=4, cls=DecimalEncoder))
Note
This program uses UpdateExpression to describe all updates you want to perform on the
specified item.
The ReturnValues parameter instructs DynamoDB to return only the updated attributes
(UPDATED_NEW).
2. To run the program, enter the following command.
python MoviesItemOps03.py
The following program shows how to increment the rating for a movie. Each time you run the program,
it increments this attribute by one.
1. Copy the following program and paste it into a file named MoviesItemOps04.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
table = dynamodb.Table('Movies')
response = table.update_item(
Key={
'year': year,
'title': title
},
UpdateExpression="set info.rating = info.rating + :val",
ExpressionAttributeValues={
':val': decimal.Decimal(1)
},
ReturnValues="UPDATED_NEW"
)
print("UpdateItem succeeded:")
print(json.dumps(response, indent=4, cls=DecimalEncoder))
python MoviesItemOps04.py
In this case, the item is updated only if there are more than three actors.
1. Copy the following program and paste it into a file named MoviesItemOps05.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
from botocore.exceptions import ClientError
import json
import decimal
table = dynamodb.Table('Movies')
try:
response = table.update_item(
Key={
'year': year,
'title': title
},
UpdateExpression="remove info.actors[0]",
ConditionExpression="size(info.actors) > :num",
ExpressionAttributeValues={
':num': 3
},
ReturnValues="UPDATED_NEW"
)
except ClientError as e:
if e.response['Error']['Code'] == "ConditionalCheckFailedException":
print(e.response['Error']['Message'])
else:
raise
else:
print("UpdateItem succeeded:")
print(json.dumps(response, indent=4, cls=DecimalEncoder))
python MoviesItemOps05.py
The program fails because the movie has three actors in it, but the condition is checking for greater
than three actors.
3. Modify the program so that the ConditionExpression looks like the following.
In the following example, you try to delete a specific movie item if its rating is 5 or less.
1. Copy the following program and paste it into a file named MoviesItemOps06.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
from botocore.exceptions import ClientError
import json
import decimal
table = dynamodb.Table('Movies')
try:
response = table.delete_item(
Key={
'year': year,
'title': title
},
ConditionExpression="info.rating <= :val",
ExpressionAttributeValues= {
":val": decimal.Decimal(5)
}
)
except ClientError as e:
if e.response['Error']['Code'] == "ConditionalCheckFailedException":
print(e.response['Error']['Message'])
else:
raise
else:
print("DeleteItem succeeded:")
print(json.dumps(response, indent=4, cls=DecimalEncoder))
python MoviesItemOps06.py
The program fails because the rating for this particular move is greater than 5.
response = table.delete_item(
Key={
'year': year,
'title': title
}
)
4. Run the program. Now, the delete succeeds because you removed the condition.
The primary key for the Movies table is composed of the following:
To find all movies released during a year, you need to specify only the year. You can also provide the
title to retrieve a subset of movies based on some condition (on the sort key). For example, you can
find movies released in 2014 that have a title starting with the letter "A".
In addition to the query method, you can use the scan method to retrieve all the table data.
To learn more about querying and scanning data, see Working with Queries in DynamoDB (p. 458) and
Working with Scans in DynamoDB (p. 476), respectively.
Topics
• Step 4.1: Query - All Movies Released in a Year (p. 190)
• Step 4.2: Query - All Movies Released in a Year with Certain Titles (p. 191)
• Step 4.3: Scan (p. 192)
1. Copy the following program and paste it into a file named MoviesQuery01.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
from boto3.dynamodb.conditions import Key, Attr
table = dynamodb.Table('Movies')
response = table.query(
KeyConditionExpression=Key('year').eq(1985)
)
for i in response['Items']:
print(i['year'], ":", i['title'])
Note
The Boto 3 SDK constructs a ConditionExpression for you when you use the Key and
Attr functions imported from boto3.dynamodb.conditions. You can also specify a
ConditionExpression as a string.
For a list of available conditions for Amazon DynamoDB, see DynamoDB Conditions in AWS
SDK for Python (Boto 3) Getting Started.
For more information, see Condition Expressions (p. 393).
2. To run the program, enter the following command.
python MoviesQuery01.py
Note
The preceding program shows how to query a table by its primary key attributes. In DynamoDB,
you can optionally create one or more secondary indexes on a table and query those indexes
in the same way that you query a table. Secondary indexes give your applications additional
flexibility by allowing queries on non-key attributes. For more information, see Improving Data
Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesQuery02.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
from boto3.dynamodb.conditions import Key, Attr
table = dynamodb.Table('Movies')
print("Movies from 1992 - titles A-L, with genres and lead actor")
response = table.query(
ProjectionExpression="#yr, title, info.genres, info.actors[0]",
ExpressionAttributeNames={ "#yr": "year" }, # Expression Attribute Names for
Projection Expression only.
KeyConditionExpression=Key('year').eq(1992) & Key('title').between('A', 'L')
)
for i in response[u'Items']:
print(json.dumps(i, cls=DecimalEncoder))
python MoviesQuery02.py
The following program scans the entire Movies table, which contains approximately 5,000 items. The
scan specifies the optional filter to retrieve only the movies from the 1950s (approximately 100 items)
and discard all the others.
1. Copy the following program and paste it into a file named MoviesScan.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import decimal
from boto3.dynamodb.conditions import Key, Attr
table = dynamodb.Table('Movies')
fe = Key('year').between(1950, 1959)
pe = "#yr, title, info.rating"
# Expression Attribute Names for Projection Expression only.
ean = { "#yr": "year", }
esk = None
response = table.scan(
FilterExpression=fe,
ProjectionExpression=pe,
ExpressionAttributeNames=ean
)
for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))
for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))
Note
python MoviesScan.py
Note
You can also use the Scan operation with any secondary indexes that you create on the table.
For more information, see Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesDeleteTable.py.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
from __future__ import print_function # Python 2/3 compatibility
import boto3
table = dynamodb.Table('Movies')
table.delete()
python MoviesDeleteTable.py
Summary
In this tutorial, you created the Movies table in the downloadable version of Amazon DynamoDB on
your computer and performed basic operations. The downloadable version of DynamoDB is useful
during application development and testing. However, when you're ready to run your application in a
production environment, you must modify your code so that it uses the DynamoDB web service.
dynamodb = boto3.resource('dynamodb',endpoint_url="http://localhost:8000")
For example, if you want to use the us-west-2 Region, change the code to the following.
dynamodb = boto3.resource('dynamodb',region_name='us-west-2')
Instead of using the downloadable version of DynamoDB on your computer, the program now uses the
DynamoDB web service in the US West (Oregon) Region.
DynamoDB is available in AWS Regions worldwide. For the complete list, see Regions and Endpoints in
the AWS General Reference. For more information about setting Regions and endpoints in your code, see
AWS Region Selection in the AWS SDK for Java Developer Guide.
• Create a table called Movies and load sample data in JSON format.
• Perform create, read, update, and delete operations on the table.
• Run simple queries.
As you work through this tutorial, you can refer to the AWS SDK for Ruby API Reference. The DynamoDB
section describes the parameters and results for DynamoDB operations.
Tutorial Prerequisites
• Download and run DynamoDB on your computer. For more information, see Setting Up DynamoDB
Local (Downloadable Version) (p. 46).
Note
You use the downloadable version of DynamoDB in this tutorial. For information about how to
run the same code against the DynamoDB web service, see the Summary (p. 212).
• Set up an AWS access key to use the AWS SDKs. For more information, see Setting Up DynamoDB (Web
Service) (p. 51).
• Set up the AWS SDK for Ruby:
• Install Ruby.
• Install the AWS SDK for Ruby.
For more information, see Installation in the AWS SDK for Ruby API Reference.
1. Copy the following program and paste it into a file named MoviesCreateTable.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
params = {
table_name: "Movies",
key_schema: [
{
attribute_name: "year",
key_type: "HASH" #Partition key
},
{
attribute_name: "title",
key_type: "RANGE" #Sort key
}
],
attribute_definitions: [
{
attribute_name: "year",
attribute_type: "N"
},
{
attribute_name: "title",
attribute_type: "S"
},
],
provisioned_throughput: {
read_capacity_units: 10,
write_capacity_units: 10
}
}
begin
result = dynamodb.create_table(params)
puts "Created table. Status: " +
result.table_description.table_status;
Note
• You set the endpoint to indicate that you are creating the table in the downloadable
version of Amazon DynamoDB on your computer.
• In the create_table call, you specify table name, primary key attributes, and its data
types.
• The provisioned_throughput parameter is required. However, the downloadable
version of DynamoDB ignores it. (Provisioned throughput is beyond the scope of this
exercise.)
2. To run the program, enter the following command.
ruby MoviesCreateTable.rb
To learn more about managing tables, see Working with Tables and Data in DynamoDB (p. 336).
Topics
• Step 2.1: Download the Sample Data File (p. 198)
• Step 2.2: Load the Sample Data into the Movies Table (p. 198)
You use a sample data file that contains information about a few thousand movies from the Internet
Movie Database (IMDb). The movie data is in JSON format, as shown in the following example. For each
movie, there is a year, a title, and a JSON map named info.
[
{
"year" : ... ,
"title" : ... ,
"info" : { ... }
},
{
"year" : ...,
"title" : ...,
"info" : { ... }
},
...
• The year and title are used as the primary key attribute values for the Movies table.
• You store the rest of the info values in a single attribute called info. This program illustrates how
you can store JSON in a DynamoDB attribute.
{
"year" : 2013,
"title" : "Turn It Down, Or Else!",
"info" : {
"directors" : [
"Alice Smith",
"Bob Jones"
],
"release_date" : "2013-01-18T00:00:00Z",
"rating" : 6.2,
"genres" : [
"Comedy",
"Drama"
],
"image_url" : "http://ia.media-imdb.com/images/N/
O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
"plot" : "A rock band plays their music at high volumes, annoying the neighbors.",
"rank" : 11,
"running_time_secs" : 5215,
"actors" : [
"David Matthewman",
"Ann Thomas",
"Jonathan G. Neff"
]
}
}
Step 2.2: Load the Sample Data into the Movies Table
After you download the sample data, run the following program to populate the Movies table.
1. Copy the following program and paste it into a file named MoviesLoadData.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
require "json"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
file = File.read('moviedata.json')
movies = JSON.parse(file)
movies.each{|movie|
params = {
table_name: table_name,
item: movie
}
begin
dynamodb.put_item(params)
puts "Added movie: #{movie["year"]} #{movie["title"]}"
ruby MoviesLoadData.rb
To learn more about reading and writing data, see Working with Items and Attributes (p. 375).
Topics
• Step 3.1: Create a New Item (p. 199)
• Step 3.2: Read an Item (p. 200)
• Step 3.3: Update an Item (p. 202)
• Step 3.4: Increment an Atomic Counter (p. 203)
• Step 3.5: Update an Item (Conditionally) (p. 204)
• Step 3.6: Delete an Item (p. 206)
1. Copy the following program and paste it into a file named MoviesItemOps01.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
year = 2015
title = "The Big New Movie"
item = {
year: year,
title: title,
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
params = {
table_name: table_name,
item: item
}
begin
dynamodb.put_item(params)
puts "Added item: #{year} - #{title}"
Note
The primary key is required. This code adds an item that has primary key (year, title) and
info attributes. The info attribute stores a map that provides more information about the
movie.
2. To run the program, enter the following command.
ruby MoviesItemOps01.rb
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
You can use the get_item method to read the item from the Movies table. You must specify the
primary key values so that you can read any item from Movies if you know its year and title.
1. Copy the following program and paste it into a file named MoviesItemOps02.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
year = 2015
title = "The Big New Movie"
params = {
table_name: table_name,
key: {
year: year,
title: title
}
}
begin
result = dynamodb.get_item(params)
printf "%i - %s\n%s\n%d\n",
result.item["year"],
result.item["title"],
result.item["info"]["plot"],
result.item["info"]["rating"]
ruby MoviesItemOps02.rb
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}
{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]
}
}
1. Copy the following program and paste it into a file named MoviesItemOps03.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
year = 2015
title = "The Big New Movie"
params = {
table_name: table_name,
key: {
year: year,
title: title
},
update_expression: "set info.rating = :r, info.plot=:p, info.actors=:a",
expression_attribute_values: {
":r" => 5.5,
":p" => "Everything happens all at once.", # value
<Hash,Array,String,Numeric,Boolean,IO,Set,nil>
":a" => ["Larry", "Moe", "Curly"]
},
return_values: "UPDATED_NEW"
}
begin
dynamodb.update_item(params)
puts "Added item: #{year} - #{title}"
Note
This program uses update_expression to describe all updates you want to perform on
the specified item.
The return_values parameter instructs Amazon DynamoDB to return only the updated
attributes (UPDATED_NEW).
2. To run the program, enter the following command.
ruby MoviesItemOps03.rb
The following program shows how to increment the rating for a movie. Each time you run the program,
it increments this attribute by one.
1. Copy the following program and paste it into a file named MoviesItemOps04.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
year = 2015
title = "The Big New Movie"
params = {
table_name: table_name,
key: {
year: year,
title: title
},
update_expression: "set info.rating = info.rating + :val",
expression_attribute_values: {
":val" => 1
},
return_values: "UPDATED_NEW"
}
begin
result = dynamodb.update_item(params)
puts "Updated item. ReturnValues are:"
result.attributes["info"].each do |key, value|
if key == "rating"
puts "#{key}: #{value.to_f}"
else
puts "#{key}: #{value}"
end
end
rescue Aws::DynamoDB::Errors::ServiceError => error
puts "Unable to update item:"
puts "#{error.message}"
end
ruby MoviesItemOps04.rb
In this case, the item is updated only if the number of actors is greater than three.
1. Copy the following program and paste it into a file named MoviesItemOps05.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
year = 2015
title = "The Big New Movie"
params = {
table_name: table_name,
key: {
year: year,
title: title
},
update_expression: "remove info.actors[0]",
condition_expression: "size(info.actors) > :num",
expression_attribute_values: {
":num" => 3
},
return_values: "UPDATED_NEW"
}
begin
result = dynamodb.update_item(params)
puts "Updated item. ReturnValues are:"
result.attributes["info"].each do |key, value|
if key == "rating"
puts "#{key}: #{value.to_f}"
else
puts "#{key}: #{value}"
end
end
ruby MoviesItemOps05.rb
The program fails because the movie has three actors in it, but the condition is checking for greater
than three actors.
3. Modify the program so that the ConditionExpression looks like the following.
In the following example, you try to delete a specific movie item if its rating is 5 or less.
1. Copy the following program and paste it into a file named MoviesItemOps06.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = 'Movies'
year = 2015
title = "The Big New Movie"
params = {
table_name: table_name,
key: {
year: year,
title: title
},
condition_expression: "info.rating <= :val",
expression_attribute_values: {
":val" => 5
}
}
begin
dynamodb.delete_item(params)
puts "Deleted item."
ruby MoviesItemOps06.rb
The program fails because the rating for this particular move is greater than 5.
3. Modify the program to remove the condition.
params = {
table_name: "Movies",
key: {
year: year,
title: title
}
}
4. Run the program. Now, the delete succeeds because you removed the condition.
The primary key for the Movies table is composed of the following:
To find all movies released during a year, you need to specify only the year. You can also provide the
title to retrieve a subset of movies based on some condition (on the sort key). For example, you can
find movies released in 2014 that have a title starting with the letter "A".
In addition to the query method, you can use the scan method to retrieve all of the table data.
To learn more about querying and scanning data, see Working with Queries in DynamoDB (p. 458) and
Working with Scans in DynamoDB (p. 476), respectively.
Topics
• Step 4.1: Query - All Movies Released in a Year (p. 207)
• Step 4.2: Query - All Movies Released in a Year with Certain Titles (p. 209)
• Step 4.3: Scan (p. 210)
1. Copy the following program and paste it into a file named MoviesQuery01.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = "Movies"
params = {
table_name: table_name,
key_condition_expression: "#yr = :yyyy",
expression_attribute_names: {
"#yr" => "year"
},
expression_attribute_values: {
":yyyy" => 1985
}
}
begin
result = dynamodb.query(params)
puts "Query succeeded."
result.items.each{|movie|
puts "#{movie["year"].to_i} #{movie["title"]}"
}
Note
ruby MoviesItemQuery01.rb
Note
The preceding program shows how to query a table by its primary key attributes. In DynamoDB,
you can optionally create one or more secondary indexes on a table and query those indexes
in the same way that you query a table. Secondary indexes give your applications additional
flexibility by allowing queries on non-key attributes. For more information, see Improving Data
Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesQuery02.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = "Movies"
params = {
table_name: table_name,
projection_expression: "#yr, title, info.genres, info.actors[0]",
key_condition_expression:
"#yr = :yyyy and title between :letter1 and :letter2",
expression_attribute_names: {
"#yr" => "year"
},
expression_attribute_values: {
":yyyy" => 1992,
":letter1" => "A",
":letter2" => "L"
}
}
puts "Querying for movies from 1992 - titles A-L, with genres and lead actor";
begin
result = dynamodb.query(params)
puts "Query succeeded."
result.items.each{|movie|
print "#{movie["year"].to_i}: #{movie["title"]} ... "
movie['info']['genres'].each{|gen|
print gen + " "
}
ruby MoviesQuery02.rb
The following program scans the Movies table, which contains approximately 5,000 items. The scan
specifies the optional filter to retrieve only the movies from the 1950s (approximately 100 items) and
discard all the others.
1. Copy the following program and paste it into a file named MoviesScan.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
table_name = "Movies"
params = {
table_name: table_name,
begin
loop do
result = dynamodb.scan(params)
result.items.each{|movie|
puts "#{movie["year"].to_i}: " +
"#{movie["title"]} ... " +
"#{movie["info"]["rating"].to_f}"
}
break if result.last_evaluated_key.nil?
ruby MoviesScan.rb
Note
You can also use the scan method with any secondary indexes that you create on the table. For
more information, see Improving Data Access with Secondary Indexes (p. 497).
1. Copy the following program and paste it into a file named MoviesDeleteTable.rb.
#
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
require "aws-sdk"
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
dynamodb = Aws::DynamoDB::Client.new
params = {
table_name: "Movies"
}
begin
dynamodb.delete_table(params)
puts "Deleted table."
ruby MoviesDeleteTable.rb
Summary
In this tutorial, you created the Movies table in the downloadable version of Amazon DynamoDB on
your computer and performed basic operations. The downloadable version of DynamoDB is useful
during application development and testing. However, when you're ready to run your application in a
production environment, you must modify your code so that it uses the DynamoDB web service.
Aws.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
})
Remove the endpoint parameter so that the code looks like the following.
Aws.config.update({
region: "us-west-2"
]);
After you remove this line, the code can access the DynamoDB service in the AWS Region specified by the
region config value.
Instead of using the version of DynamoDB on your computer, the program uses the DynamoDB web
service endpoint in the US West (Oregon) Region.
DynamoDB is available in AWS Regions worldwide. For the complete list, see Regions and Endpoints in
the AWS General Reference. For more information, see the AWS SDK for Ruby Getting Started Guide.
Topics
• Overview of AWS SDK Support for DynamoDB (p. 214)
• Programmatic Interfaces (p. 216)
• DynamoDB Low-Level API (p. 220)
• Error Handling with DynamoDB (p. 223)
• Higher-Level Programming Interfaces for DynamoDB (p. 229)
• Running the Code Examples in This Developer Guide (p. 325)
1. You write an application using an AWS SDK for your programming language.
2. Each AWS SDK provides one or more programmatic interfaces for working with DynamoDB. The
specific interfaces available depend on which programming language and AWS SDK you use.
3. The AWS SDK constructs HTTP(S) requests for use with the low-level DynamoDB API.
4. The AWS SDK sends the request to the DynamoDB endpoint.
5. DynamoDB executes the request. If the request is successful, DynamoDB returns an HTTP 200
response code (OK). If the request is unsuccessful, DynamoDB returns an HTTP error code and an error
message.
6. The AWS SDK processes the response and propagates it back to your application.
Each of the AWS SDKs provides important services to your application, including the following:
Programmatic Interfaces
Every AWS SDK provides one or more programmatic interfaces for working with Amazon DynamoDB.
These interfaces range from simple low-level DynamoDB wrappers to object-oriented persistence layers.
The available interfaces vary depending on the AWS SDK and programming language that you use.
The following section highlights some of the interfaces available, using the AWS SDK for Java as an
example. (Not all interfaces are available in all AWS SDKs.)
Topics
Low-Level Interfaces
Every language-specific AWS SDK provides a low-level interface for Amazon DynamoDB, with methods
that closely resemble low-level DynamoDB API requests.
In some cases, you will need to identify the data types of the attributes using Data Type
Descriptors (p. 222), such as S for string or N for number.
Note
A low-level interface is available in every language-specific AWS SDK.
The following Java program uses the low-level interface of the AWS SDK for Java. The program issues a
GetItem request for a song in the Music table and prints the year that the song was released.
package com.amazonaws.codesamples;
import java.util.HashMap;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
try {
GetItemResult result = client.getItem(request);
if (result && result.getItem() != null) {
AttributeValue year = result.getItem().get("Year");
System.out.println("The song was released in " + year.getN());
} else {
System.out.println("No matching song was found");
}
} catch (Exception e) {
System.err.println("Unable to retrieve data: ");
System.err.println(e.getMessage());
}
}
}
Document Interfaces
Many AWS SDKs provide a document interface, allowing you to perform data plane operations (create,
read, update, delete) on tables and indexes. With a document interface, you do not need to specify Data
Type Descriptors (p. 222). The data types are implied by the semantics of the data itself. These AWS
SDKs also provide methods to easily convert JSON documents to and from native Amazon DynamoDB
data types.
Note
Document interfaces are available in the AWS SDKs for Java, .NET, Node.js, and JavaScript in
the browser.
The following Java program uses the document interface of the AWS SDK for Java. The program creates
a Table object that represents the Music table, and then asks that object to use GetItem to retrieve a
song. The program then prints the year that the song was released.
package com.amazonaws.codesamples.gsg;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.GetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
}
}
The following Java program uses DynamoDBMapper, the object persistence interface of the AWS SDK for
Java. The MusicItem class represents an item in the Music table.
package com.amazonaws.codesamples;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
@DynamoDBTable(tableName="Music")
public class MusicItem {
private String artist;
private String songTitle;
private String albumTitle;
private int year;
@DynamoDBHashKey(attributeName="Artist")
public String getArtist() { return artist;}
public void setArtist(String artist) {this.artist = artist;}
@DynamoDBRangeKey(attributeName="SongTitle")
public String getSongTitle() { return songTitle;}
public void setSongTitle(String songTitle) {this.songTitle = songTitle;}
@DynamoDBAttribute(attributeName = "AlbumTitle")
public String getAlbumTitle() { return albumTitle;}
public void setAlbumTitle(String albumTitle) {this.albumTitle = albumTitle;}
@DynamoDBAttribute(attributeName = "Year")
public int getYear() { return year; }
public void setYear(int year) { this.year = year; }
}
You can then instantiate a MusicItem object, and retrieve a song using the load() method of
DynamoDBMapper. The program then prints the year that the song was released.
package com.amazonaws.codesamples;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
try {
MusicItem result = mapper.load(keySchema);
if (result != null) {
System.out.println(
"The song was released in "+ result.getYear());
} else {
System.out.println("No matching song was found");
}
} catch (Exception e) {
System.err.println("Unable to retrieve data: ");
System.err.println(e.getMessage());
}
The Amazon DynamoDB low-level API is the protocol-level interface for DynamoDB. At this level, every
HTTP(S) request must be correctly formatted and carry a valid digital signature.
The AWS SDKs construct low-level DynamoDB API requests on your behalf and process the responses
from DynamoDB. This lets you focus on your application logic, instead of low-level details. However, you
can still benefit from a basic knowledge of how the low-level DynamoDB API works.
For more information about the low-level DynamoDB API, see Amazon DynamoDB API Reference.
Note
DynamoDB Streams has its own low-level API, which is separate from that of DynamoDB and is
fully supported by the AWS SDKs.
For more information, see Capturing Table Activity with DynamoDB Streams (p. 574). For the
low-level DynamoDB Streams API, see the Amazon DynamoDB Streams API Reference.
The low-level DynamoDB API uses JavaScript Object Notation (JSON) as a wire protocol format. JSON
presents data in a hierarchy so that both data values and data structure are conveyed simultaneously.
Name-value pairs are defined in the format name:value. The data hierarchy is defined by nested
brackets of name-value pairs.
DynamoDB uses JSON only as a transport protocol, not as a storage format. The AWS SDKs use JSON
to send data to DynamoDB, and DynamoDB responds with JSON. DynamoDB does not store data
persistently in JSON format.
Note
For more information about JSON, see Introducing JSON on the JSON.org website.
Request Format
The DynamoDB low-level API accepts HTTP(S) POST requests as input. The AWS SDKs construct these
requests for you.
Suppose that you have a table named Pets, with a key schema consisting of AnimalType (partition key)
and Name (sort key). Both of these attributes are of type string. To retrieve an item from Pets, the
AWS SDK constructs the following request.
POST / HTTP/1.1
Host: dynamodb.<region>.<domain>;
Accept-Encoding: identity
Content-Length: <PayloadSizeBytes>
User-Agent: <UserAgentString>
Content-Type: application/x-amz-json-1.0
Authorization: AWS4-HMAC-SHA256 Credential=<Credential>, SignedHeaders=<Headers>,
Signature=<Signature>
X-Amz-Date: <Date>
X-Amz-Target: DynamoDB_20120810.GetItem
{
"TableName": "Pets",
"Key": {
"AnimalType": {"S": "Dog"},
"Name": {"S": "Fido"}
}
}
• The Authorization header contains information required for DynamoDB to authenticate the
request. For more information, see Signing AWS API Requests and Signature Version 4 Signing Process
in the Amazon Web Services General Reference.
• The X-Amz-Target header contains the name of a DynamoDB operation: GetItem. (This is also
accompanied by the low-level API version, in this case 20120810.)
• The payload (body) of the request contains the parameters for the operation, in JSON format. For the
GetItem operation, the parameters are TableName and Key.
Response Format
Upon receipt of the request, DynamoDB processes it and returns a response. For the request shown
previously, the HTTP(S) response payload contains the results from the operation, as shown in the
following example.
HTTP/1.1 200 OK
x-amzn-RequestId: <RequestId>
x-amz-crc32: <Checksum>
Content-Type: application/x-amz-json-1.0
Content-Length: <PayloadSizeBytes>
Date: <Date>
{
"Item": {
"Age": {"N": "8"},
"Colors": {
"L": [
{"S": "White"},
{"S": "Brown"},
{"S": "Black"}
]
},
"Name": {"S": "Fido"},
"Vaccinations": {
"M": {
"Rabies": {
"L": [
{"S": "2009-03-17"},
{"S": "2011-09-21"},
{"S": "2014-07-08"}
]
},
"Distemper": {"S": "2015-10-13"}
}
},
"Breed": {"S": "Beagle"},
"AnimalType": {"S": "Dog"}
}
}
At this point, the AWS SDK returns the response data to your application for further processing.
Note
If DynamoDB can't process a request, it returns an HTTP error code and message. The AWS SDK
propagates these to your application in the form of exceptions. For more information, see Error
Handling with DynamoDB (p. 223).
The examples in Request Format (p. 221) and Response Format (p. 222) show examples of how
data type descriptors are used. The GetItem request specifies S for the Pets key schema attributes
(AnimalType and Name), which are of type string. The GetItem response contains a Pets item with
attributes of type string (S), number (N), map (M), and list (L).
• S – String
• N – Number
• B – Binary
• BOOL – Boolean
• NULL – Null
• M – Map
• L – List
• SS – String Set
• NS – Number Set
• BS – Binary Set
Note
For detailed descriptions of DynamoDB data types, see Data Types (p. 13).
Numeric Data
Different programming languages offer different levels of support for JSON. In some cases, you might
decide to use a third-party library for validating and parsing JSON documents.
Some third-party libraries build upon the JSON number type, providing their own types such as int,
long, or double. However, the native number data type in DynamoDB does not map exactly to these
other data types, so these type distinctions can cause conflicts. In addition, many JSON libraries do
not handle fixed-precision numeric values, and they automatically infer a double data type for digit
sequences that contain a decimal point.
To solve these problems, DynamoDB provides a single numeric type with no data loss. To avoid
unwanted implicit conversions to a double value, DynamoDB uses strings for the data transfer of numeric
values. This approach provides flexibility for updating attribute values while maintaining proper sorting
semantics, such as putting the values "01", "2", and "03" in the proper sequence.
If number precision is important to your application, you should convert numeric values to strings before
you pass them to DynamoDB.
Binary Data
DynamoDB supports binary attributes. However, JSON does not natively support encoding binary
data. To send binary data in a request, you will need to encode it in base64 format. Upon receiving the
request, DynamoDB decodes the base64 data back to binary.
The base64 encoding scheme used by DynamoDB is described at RFC 4648 on the Internet Engineering
Task Force (IETF) website.
Topics
Error Components
When your program sends a request, DynamoDB attempts to process it. If the request is successful,
DynamoDB returns an HTTP success status code (200 OK), along with the results from the requested
operation.
If the request is unsuccessful, DynamoDB returns an error. Each error has three components:
The AWS SDKs take care of propagating errors to your application so that you can take
appropriate action. For example, in a Java program, you can write try-catch logic to handle a
ResourceNotFoundException.
If you are not using an AWS SDK, you need to parse the content of the low-level response from
DynamoDB. The following is an example of such a response.
{"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",
"message":"Requested resource not found: Table: tablename not found"}
AccessDeniedException
The client did not correctly sign the request. If you are using an AWS SDK, requests are signed for
you automatically; otherwise, go to the Signature Version 4 Signing Process in the AWS General
Reference.
OK to retry? No
ConditionalCheckFailedException
You specified a condition that evaluated to false. For example, you might have tried to perform a
conditional update on an item, but the actual value of the attribute did not match the expected
value in the condition.
OK to retry? No
IncompleteSignatureException
The request signature did not include all of the required components. If you are using an AWS SDK,
requests are signed for you automatically; otherwise, go to the Signature Version 4 Signing Process
in the AWS General Reference.
OK to retry? No
ItemCollectionSizeLimitExceededException
For a table with a local secondary index, a group of items with the same partition key value has
exceeded the maximum size limit of 10 GB. For more information on item collections, see Item
Collections (p. 545).
OK to retry? Yes
LimitExceededException
There are too many concurrent control plane operations. The cumulative number of tables and
indexes in the CREATING, DELETING, or UPDATING state cannot exceed 50.
OK to retry? Yes
MissingAuthenticationTokenException
Message: Request must contain a valid (registered) AWS Access Key ID.
The request did not include the required authorization header, or it was malformed. See DynamoDB
Low-Level API (p. 220).
OK to retry? No
ProvisionedThroughputExceededException
Message: You exceeded your maximum allowed provisioned throughput for a table or for one or more
global secondary indexes. To view performance metrics for provisioned throughput vs. consumed
throughput, open the Amazon CloudWatch console.
Example: Your request rate is too high. The AWS SDKs for DynamoDB automatically retry requests
that receive this exception. Your request is eventually successful, unless your retry queue is too large
to finish. Reduce the frequency of requests using Error Retries and Exponential Backoff (p. 228).
OK to retry? Yes
RequestLimitExceeded
Message: Throughput exceeds the current throughput limit for your account. To request a limit
increase, contact AWS Support at https://aws.amazon.com/support.
OK to retry? Yes
ResourceInUseException
Example: You tried to re-create an existing table, or delete a table currently in the CREATING state.
OK to retry? No
ResourceNotFoundException
Example: The table that is being requested does not exist, or is too early in the CREATING state.
OK to retry? No
ThrottlingException
This exception might be returned if you perform any of the following operations too rapidly:
CreateTable, UpdateTable, DeleteTable.
OK to retry? Yes
UnrecognizedClientException
The request signature is incorrect. The most likely cause is an invalid AWS access key ID or secret key.
OK to retry? Yes
ValidationException
This error can occur for several reasons, such as a required parameter that is missing, a value that is
out of range, or mismatched data types. The error message contains details about the specific part
of the request that caused the error.
OK to retry? No
OK to retry? Yes
Note
You might encounter internal server errors while working with items. These are expected
during the lifetime of a table. Any failed requests can be retried immediately.
OK to retry? Yes
The AWS SDKs perform their own retries and error checking. If you encounter an error while using one of
the AWS SDKs, the error code and description can help you troubleshoot it.
You should also see a Request ID in the response. The Request ID can be helpful if you need to work
with AWS Support to diagnose an issue.
The following Java code example tries to delete an item from a DynamoDB table and performs
rudimentary error handling. (In this case, it simply informs the user that the request failed.)
try {
Item item = table.getItem("year", 1978, "title", "Superman");
if (item != null) {
System.out.println("Result: " + item);
} else {
//No such item exists in the table
System.out.println("Item not found");
}
In this code example, the try-catch construct handles two different kinds of exceptions:
Each AWS SDK implements retry logic automatically. You can modify the retry parameters to your
needs. For example, consider a Java application that requires a fail-fast strategy, with no retries allowed
in case of an error. With the AWS SDK for Java, you could use the ClientConfiguration class and
provide a maxErrorRetry value of 0 to turn off the retries. For more information, see the AWS SDK
documentation for your programming language.
If you're not using an AWS SDK, you should retry original requests that receive server
errors (5xx). However, client errors (4xx, other than a ThrottlingException or a
ProvisionedThroughputExceededException) indicate that you need to revise the request itself to
correct the problem before trying again.
In addition to simple retries, each AWS SDK implements an exponential backoff algorithm for better
flow control. The concept behind exponential backoff is to use progressively longer waits between retries
for consecutive error responses. For example, up to 50 milliseconds before the first retry, up to 100
milliseconds before the second, up to 200 milliseconds before third, and so on. However, after a minute,
if the request has not succeeded, the problem might be the request size exceeding your provisioned
throughput, and not the request rate. Set the maximum number of retries to stop around one minute. If
the request is not successful, investigate your provisioned throughput options.
Note
The AWS SDKs implement automatic retry logic and exponential backoff.
Most exponential backoff algorithms use jitter (randomized delay) to prevent successive collisions.
Because you aren't trying to avoid such collisions in these cases, you do not need to use this random
number. However, if you use concurrent clients, jitter can help your requests succeed faster. For more
information, see the blog post about Exponential Backoff and Jitter.
A batch operation can tolerate the failure of individual requests in the batch. For example, consider a
BatchGetItem request to read five items. Even if some of the underlying GetItem requests fail, this
does not cause the entire BatchGetItem operation to fail. However, if all five read operations fail, then
the entire BatchGetItem fails.
The batch operations return information about individual requests that fail so that you can diagnose
the problem and retry the operation. For BatchGetItem, the tables and primary keys in question are
returned in the UnprocessedKeys value of the response. For BatchWriteItem, similar information is
returned in UnprocessedItems.
The most likely cause of a failed read or a failed write is throttling. For BatchGetItem, one or more
of the tables in the batch request does not have enough provisioned read capacity to support the
operation. For BatchWriteItem, one or more of the tables does not have enough provisioned write
capacity.
If DynamoDB returns any unprocessed items, you should retry the batch operation on those items.
However, we strongly recommend that you use an exponential backoff algorithm. If you retry the batch
operation immediately, the underlying read or write requests can still fail due to throttling on the
individual tables. If you delay the batch operation using exponential backoff, the individual requests in
the batch are much more likely to succeed.
To simplify development, the AWS SDKs for Java and .NET provide additional interfaces with higher
levels of abstraction. The higher-level interfaces for DynamoDB let you define the relationships between
objects in your program and the database tables that store those objects' data. After you define this
mapping, you call simple object methods such as save, load, or delete, and the underlying low-level
DynamoDB operations are automatically invoked on your behalf. This allows you to write object-centric
code, rather than database-centric code.
The higher-level programming interfaces for DynamoDB are available in the AWS SDKs for Java
and .NET.
Java
.NET
Java: DynamoDBMapper
Topics
• Supported Data Types (p. 231)
• Java Annotations for DynamoDB (p. 232)
• DynamoDBMapper Class (p. 237)
• Optional Configuration Settings for DynamoDBMapper (p. 244)
• Example: CRUD Operations (p. 245)
• Example: Batch Write Operations (p. 247)
• Example: Query and Scan (p. 254)
• Example: Transaction Operations (p. 263)
• Optimistic Locking with Version Number (p. 270)
• Mapping Arbitrary Data (p. 272)
The AWS SDK for Java provides a DynamoDBMapper class, allowing you to map your client-side classes
to Amazon DynamoDB tables. To use DynamoDBMapper, you define the relationship between items in
a DynamoDB table and their corresponding object instances in your code. The DynamoDBMapper class
enables you to access your tables; perform various create, read, update, and delete (CRUD) operations;
and execute queries.
Note
The DynamoDBMapper class does not allow you to create, update, or delete tables. To perform
those tasks, use the low-level SDK for Java interface instead. For more information, see Working
with DynamoDB Tables in Java (p. 363).
The SDK for Java provides a set of annotation types so that you can map your classes to tables. For
example, consider a ProductCatalog table that has Id as the partition key.
ProductCatalog(Id, ...)
You can map a class in your client application to the ProductCatalog table as shown in the following
Java code. This code defines a plain old Java object (POJO) named CatalogItem, which uses
annotations to map object fields to DynamoDB attribute names.
Example
package com.amazonaws.codesamples;
import java.util.Set;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBIgnore;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {
@DynamoDBHashKey(attributeName="Id")
public Integer getId() { return id; }
public void setId(Integer id) {this.id = id; }
@DynamoDBAttribute(attributeName="Title")
public String getTitle() {return title; }
public void setTitle(String title) { this.title = title; }
@DynamoDBAttribute(attributeName="ISBN")
public String getISBN() { return ISBN; }
public void setISBN(String ISBN) { this.ISBN = ISBN; }
@DynamoDBAttribute(attributeName="Authors")
public Set<String> getBookAuthors() { return bookAuthors; }
public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; }
@DynamoDBIgnore
public String getSomeProp() { return someProp; }
public void setSomeProp(String someProp) { this.someProp = someProp; }
}
In the preceding code, the @DynamoDBTable annotation maps the CatalogItem class to the
ProductCatalog table. You can store individual class instances as items in the table. In the class
definition, the @DynamoDBHashKey annotation maps the Id property to the primary key.
By default, the class properties map to the same name attributes in the table. The properties Title and
ISBN map to the same name attributes in the table.
The @DynamoDBAttribute annotation is optional when the name of the DynamoDB attribute
matches the name of the property declared in the class. When they differ, use this annotation with the
attributeName() parameter to specify which DynamoDB attribute this property corresponds to.
In the preceding example, the @DynamoDBAttribute annotation is added to each property to ensure
that the property names match exactly with the tables created in Creating Tables and Loading Data for
Code Examples in DynamoDB (p. 326), and to be consistent with the attribute names used in other
code examples in this guide.
Your class definition can have properties that don't map to any attributes in the table. You identify these
properties by adding the @DynamoDBIgnore annotation. In the preceding example, the SomeProp
property is marked with the @DynamoDBIgnore annotation. When you upload a CatalogItem instance
to the table, your DynamoDBMapper instance does not include the SomeProp property. In addition, the
mapper does not return this attribute when you retrieve an item from the table.
After you define your mapping class, you can use DynamoDBMapper methods to write an instance of
that class to a corresponding item in the Catalog table. The following code example demonstrates this
technique.
mapper.save(item);
The following code example shows how to retrieve the item and access some of its attributes.
partitionKey.setId(102);
DynamoDBQueryExpression<CatalogItem> queryExpression = new
DynamoDBQueryExpression<CatalogItem>()
.withHashKeyValues(partitionKey);
DynamoDBMapper offers an intuitive, natural way of working with DynamoDB data within Java. It also
provides several built-in features, such as optimistic locking, ACID transactions, autogenerated partition
key and sort key values, and object versioning.
Amazon DynamoDB supports the following primitive Java data types and primitive wrapper classes.
• String
• Boolean, boolean
• Byte, byte
• Date (as ISO_8601 millisecond-precision string, shifted to UTC)
• Calendar (as ISO_8601 millisecond-precision string, shifted to UTC)
• Long, long
• Integer, int
• Double, double
• Float, float
• BigDecimal
• BigInteger
Note
For more information about DynamoDB naming rules and the various supported data types, see
Naming Rules and Data Types (p. 12).
DynamoDB supports the Java Set, List, and Map collection types. The following table summarizes how
these Java types map to the DynamoDB types.
The DynamoDBTypeConverter interface lets you map your own arbitrary data types to a data type that
is natively supported by DynamoDB. For more information, see Mapping Arbitrary Data (p. 272).
For the corresponding Javadoc documentation, see Annotation Types Summary in the AWS SDK for Java
API Reference.
Note
In the following annotations, only DynamoDBTable and the DynamoDBHashKey are required.
Topics
• DynamoDBAttribute (p. 233)
• DynamoDBAutoGeneratedKey (p. 233)
DynamoDBAttribute
Maps a property to a table attribute. By default, each class property maps to an item attribute with the
same name. However, if the names are not the same, you can use this annotation to map a property to
the attribute. In the following Java snippet, the DynamoDBAttribute maps the BookAuthors property
to the Authors attribute name in the table.
@DynamoDBAttribute(attributeName = "Authors")
public List<String> getBookAuthors() { return BookAuthors; }
public void setBookAuthors(List<String> BookAuthors) { this.BookAuthors = BookAuthors; }
The DynamoDBMapper uses Authors as the attribute name when saving the object to the table.
DynamoDBAutoGeneratedKey
Marks a partition key or sort key property as being autogenerated. DynamoDBMapper generates a
random UUID when saving these attributes. Only String properties can be marked as autogenerated
keys.
@DynamoDBTable(tableName="AutoGeneratedKeysExample")
public class AutoGeneratedKeys {
private String id;
private String payload;
@DynamoDBHashKey(attributeName = "Id")
@DynamoDBAutoGeneratedKey
public String getId() { return id; }
public void setId(String id) { this.id = id; }
@DynamoDBAttribute(attributeName="payload")
public String getPayload() { return this.payload; }
public void setPayload(String payload) { this.payload = payload; }
DynamoDBDocument
Indicates that a class can be serialized as an Amazon DynamoDB document.
For example, suppose that you wanted to map a JSON document to a DynamoDB attribute of type Map
(M). The following code example defines an item containing a nested attribute (Pictures) of type Map.
@DynamoDBHashKey(attributeName="Id")
public Integer getId() { return id;}
public void setId(Integer id) {this.id = id;}
@DynamoDBAttribute(attributeName="Pictures")
public Pictures getPictures() { return pictures;}
public void setPictures(Pictures pictures) {this.pictures = pictures;}
@DynamoDBDocument
public static class Pictures {
private String frontView;
private String rearView;
private String sideView;
@DynamoDBAttribute(attributeName = "FrontView")
public String getFrontView() { return frontView; }
public void setFrontView(String frontView) { this.frontView = frontView; }
@DynamoDBAttribute(attributeName = "RearView")
public String getRearView() { return rearView; }
public void setRearView(String rearView) { this.rearView = rearView; }
@DynamoDBAttribute(attributeName = "SideView")
public String getSideView() { return sideView; }
public void setSideView(String sideView) { this.sideView = sideView; }
}
}
You could then save a new ProductCatalog item, with Pictures, as shown in the following example.
item.setId(123);
mapper.save(item);
The resulting ProductCatalog item would look like the following (in JSON format).
{
"Id" : 123
"Pictures" : {
"SideView" : "http://example.com/products/123_left_side.jpg",
"RearView" : "http://example.com/products/123_rear.jpg",
"FrontView" : "http://example.com/products/123_front.jpg"
}
}
DynamoDBHashKey
Maps a class property to the partition key of the table. The property must be one of the scalar string,
number, or binary types. The property can't be a collection type.
Assume that you have a table, ProductCatalog, that has Id as the primary key. The following
Java code defines a CatalogItem class and maps its Id property to the primary key of the
ProductCatalog table using the @DynamoDBHashKey tag.
@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {
private Integer Id;
@DynamoDBHashKey(attributeName="Id")
public Integer getId() {
return Id;
}
public void setId(Integer Id) {
this.Id = Id;
}
// Additional properties go here.
}
DynamoDBIgnore
Indicates to the DynamoDBMapper instance that the associated property should be ignored. When saving
data to the table, the DynamoDBMapper does not save this property to the table.
Applied to the getter method or the class field for a non-modeled property. If the annotation is applied
directly to the class field, the corresponding getter and setter must be declared in the same class.
DynamoDBIndexHashKey
Maps a class property to the partition key of a global secondary index. The property must be one of the
scalar string, number, or binary types. The property can't be a collection type.
Use this annotation if you need to Query a global secondary index. You must specify the index name
(globalSecondaryIndexName). If the name of the class property is different from the index partition
key, you also must specify the name of that index attribute (attributeName).
DynamoDBIndexRangeKey
Maps a class property to the sort key of a global secondary index or a local secondary index. The
property must be one of the scalar string, number, or binary types. The property can't be a collection
type.
Use this annotation if you need to Query a local secondary index or a global secondary index
and want to refine your results using the index sort key. You must specify the index name (either
globalSecondaryIndexName or localSecondaryIndexName). If the name of the class
property is different from the index sort key, you must also specify the name of that index attribute
(attributeName).
DynamoDBRangeKey
Maps a class property to the sort key of the table. The property must be one of the scalar string, number,
or binary types. It cannot be a collection type.
If the primary key is composite (partition key and sort key), you can use this tag to map your class
field to the sort key. For example, assume that you have a Reply table that stores replies for forum
threads. Each thread can have many replies. So the primary key of this table is both the ThreadId and
ReplyDateTime. The ThreadId is the partition key, and ReplyDateTime is the sort key.
The following Java code defines a Reply class and maps it to the Reply table. It uses both the
@DynamoDBHashKey and @DynamoDBRangeKey tags to identify class properties that map to the
primary key.
@DynamoDBTable(tableName="Reply")
public class Reply {
private Integer id;
private String replyDateTime;
@DynamoDBHashKey(attributeName="Id")
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
@DynamoDBRangeKey(attributeName="ReplyDateTime")
public String getReplyDateTime() { return replyDateTime; }
public void setReplyDateTime(String replyDateTime) { this.replyDateTime =
replyDateTime; }
DynamoDBTable
Identifies the target table in DynamoDB. For example, the following Java code defines a class
Developer and maps it to the People table in DynamoDB.
@DynamoDBTable(tableName="People")
public class Developer { ...}
The @DynamoDBTable annotation can be inherited. Any new class that inherits from the Developer
class also maps to the People table. For example, assume that you create a Lead class that inherits from
the Developer class. Because you mapped the Developer class to the People table, the Lead class
objects are also stored in the same table.
The @DynamoDBTable can also be overridden. Any new class that inherits from the Developer class by
default maps to the same People table. However, you can override this default mapping. For example,
if you create a class that inherits from the Developer class, you can explicitly map it to another table by
adding the @DynamoDBTable annotation as shown in the following Java code example.
@DynamoDBTable(tableName="Managers")
public class Manager extends Developer { ...}
DynamoDBTypeConverted
An annotation to mark a property as using a custom type converter. Can be annotated on a user-defined
annotation to pass additional properties to the DynamoDBTypeConverter.
The DynamoDBTypeConverter interface lets you map your own arbitrary data types to a data type that
is natively supported by DynamoDB. For more information, see Mapping Arbitrary Data (p. 272).
DynamoDBTyped
An annotation to override the standard attribute type binding. Standard types do not require the
annotation if applying the default attribute binding for that type.
DynamoDBVersionAttribute
Identifies a class property for storing an optimistic locking version number. DynamoDBMapper
assigns a version number to this property when it saves a new item, and increments it each time you
update the item. Only number scalar types are supported. For more information about data types,
see Data Types (p. 13). For more information about versioning, see Optimistic Locking with Version
Number (p. 270).
DynamoDBMapper Class
The DynamoDBMapper class is the entry point to Amazon DynamoDB. It provides access to a DynamoDB
endpoint and enables you to access your data in various tables. It also enables you to perform various
create, read, update, and delete (CRUD) operations on items, and execute queries and scans against
tables. This class provides the following methods for working with DynamoDB.
For the corresponding Javadoc documentation, see DynamoDBMapper in the AWS SDK for Java API
Reference.
Topics
• save (p. 237)
• load (p. 238)
• delete (p. 238)
• query (p. 238)
• queryPage (p. 240)
• scan (p. 240)
• scanPage (p. 240)
• parallelScan (p. 241)
• batchSave (p. 241)
• batchLoad (p. 241)
• batchDelete (p. 242)
• batchWrite (p. 242)
• transactionWrite (p. 242)
• transactionLoad (p. 243)
• count (p. 243)
• generateCreateTableRequest (p. 243)
• createS3Link (p. 243)
• getS3ClientCache (p. 244)
save
Saves the specified object to the table. The object that you want to save is the only required parameter
for this method. You can provide optional configuration parameters using the DynamoDBMapperConfig
object.
If an item that has the same primary key does not exist, this method creates a new item in the table.
If an item that has the same primary key exists, it updates the existing item. If the partition key and
sort key are of type String and are annotated with @DynamoDBAutoGeneratedKey, they are given a
random universally unique identifier (UUID) if left uninitialized. Version fields that are annotated with
@DynamoDBVersionAttribute are incremented by one. Additionally, if a version field is updated or a
key generated, the object passed in is updated as a result of the operation.
By default, only attributes corresponding to mapped class properties are updated. Any additional
existing attributes on an item are unaffected. However, if you specify SaveBehavior.CLOBBER, you can
force the item to be completely overwritten.
If you have versioning enabled, the client-side and server-side item versions must match. However, the
version does not need to match if the SaveBehavior.CLOBBER option is used. For more information
about versioning, see Optimistic Locking with Version Number (p. 270).
load
Retrieves an item from a table. You must provide the primary key of the item that you want to retrieve.
You can provide optional configuration parameters using the DynamoDBMapperConfig object. For
example, you can optionally request strongly consistent reads to ensure that this method retrieves only
the latest item values as shown in the following Java statement.
By default, DynamoDB returns the item that has values that are eventually consistent. For information
about the eventual consistency model of DynamoDB, see Read Consistency (p. 16).
delete
Deletes an item from the table. You must pass in an object instance of the mapped class.
If you have versioning enabled, the client-side and server-side item versions must match. However, the
version does not need to match if the SaveBehavior.CLOBBER option is used. For more information
about versioning, see Optimistic Locking with Version Number (p. 270).
query
Queries a table or a secondary index. You can query a table or an index only if it has a composite primary
key (partition key and sort key). This method requires you to provide a partition key value and a query
filter that is applied on the sort key. A filter expression includes a condition and a value.
Assume that you have a table, Reply, that stores forum thread replies. Each thread subject can have
zero or more replies. The primary key of the Reply table consists of the Id and ReplyDateTime fields,
where Id is the partition key and ReplyDateTime is the sort key of the primary key.
Assume that you created a mapping between a Reply class and the corresponding Reply table in
DynamoDB. The following Java code uses DynamoDBMapper to find all replies in the past two weeks for
a specific thread subject.
Example
By default, the query method returns a "lazy-loaded" collection. It initially returns only one page of
results, and then makes a service call for the next page if needed. To obtain all the matching items,
iterate over the latestReplies collection.
To query an index, you must first model the index as a mapper class. Suppose that the Reply table has
a global secondary index named PostedBy-Message-Index. The partition key for this index is PostedBy,
and the sort key is Message. The class definition for an item in the index would look like the following.
@DynamoDBTable(tableName="Reply")
public class PostedByMessage {
private String postedBy;
private String message;
@DynamoDBIndexHashKey(globalSecondaryIndexName = "PostedBy-Message-Index",
attributeName = "PostedBy")
public String getPostedBy() { return postedBy; }
public void setPostedBy(String postedBy) { this.postedBy = postedBy; }
@DynamoDBIndexRangeKey(globalSecondaryIndexName = "PostedBy-Message-Index",
attributeName = "Message")
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
The @DynamoDBTable annotation indicates that this index is associated with the Reply table.
The @DynamoDBIndexHashKey annotation denotes the partition key (PostedBy) of the index, and
@DynamoDBIndexRangeKey denotes the sort key (Message) of the index.
Now you can use DynamoDBMapper to query the index, retrieving a subset of messages that were
posted by a particular user. You must specify withIndexName so that DynamoDB knows which
index to query. The following code queries a global secondary index. Because global secondary
indexes support eventually consistent reads but not strongly consistent reads, you must specify
withConsistentRead(false).
queryPage
Queries a table or secondary index and returns a single page of matching results. As with the query
method, you must specify a partition key value and a query filter that is applied on the sort key attribute.
However, queryPage returns only the first "page" of data, that is, the amount of data that fits in 1 MB
scan
Scans an entire table or a secondary index. You can optionally specify a FilterExpression to filter the
result set.
Assume that you have a table, Reply, that stores forum thread replies. Each thread subject can have
zero or more replies. The primary key of the Reply table consists of the Id and ReplyDateTime fields,
where Id is the partition key and ReplyDateTime is the sort key of the primary key.
If you mapped a Java class to the Reply table, you can use the DynamoDBMapper to scan the table. For
example, the following Java code scans the entire Reply table, returning only the replies for a particular
year.
Example
By default, the scan method returns a "lazy-loaded" collection. It initially returns only one page of
results, and then makes a service call for the next page if needed. To obtain all the matching items,
iterate over the replies collection.
To scan an index, you must first model the index as a mapper class. Suppose that the Reply table
has a global secondary index named PostedBy-Message-Index. The partition key for this index is
PostedBy, and the sort key is Message. A mapper class for this index is shown in the query (p. 238)
section. It uses the @DynamoDBIndexHashKey and @DynamoDBIndexRangeKey annotations to specify
the index partition key and sort key.
The following code example scans PostedBy-Message-Index. It does not use a scan filter, so all of the
items in the index are returned to you.
scanPage
Scans a table or secondary index and returns a single page of matching results. As with the scan
method, you can optionally specify a FilterExpression to filter the result set. However, scanPage
only returns the first "page" of data, that is, the amount of data that fits within 1 MB.
parallelScan
Performs a parallel scan of an entire table or secondary index. You specify a number of logical segments
for the table, along with a scan expression to filter the results. The parallelScan divides the scan
task among multiple workers, one for each logical segment; the workers process the data in parallel and
return the results.
The following Java code example performs a parallel scan on the Product table.
int numberOfThreads = 4;
For a Java code example illustrating the usage of parallelScan, see Example: Query and
Scan (p. 254).
batchSave
Saves objects to one or more tables using one or more calls to the AmazonDynamoDB.batchWriteItem
method. This method does not provide transaction guarantees.
The following Java code saves two items (books) to the ProductCatalog table.
mapper.batchSave(Arrays.asList(book1, book2));
batchLoad
Retrieves multiple items from one or more tables using their primary keys.
The following Java code retrieves two items from two different tables.
batchDelete
Deletes objects from one or more tables using one or more calls to the
AmazonDynamoDB.batchWriteItem method. This method does not provide transaction guarantees.
The following Java code deletes two items (books) from the ProductCatalog table.
batchWrite
Saves objects to and deletes objects from one or more tables using one or more calls to the
AmazonDynamoDB.batchWriteItem method. This method does not provide transaction guarantees or
support versioning (conditional puts or deletes).
The following Java code writes a new item to the Forum table, writes a new item to the Thread table,
and deletes an item from the ProductCatalog table.
mapper.batchWrite(objectsToWrite, objectsToDelete);
transactionWrite
Saves objects to and deletes objects from one or more tables using one call to the
AmazonDynamoDB.transactWriteItems method.
For more information about DynamoDB transactions and the provided atomicity, consistency, isolation,
and durability (ACID) guarantees see Amazon DynamoDB Transactions.
Note
This method does not support the following:
• DynamoDBMapperConfig.SaveBehavior.
The following Java code writes a new item to each of the Forum and Thread tables, transactionally.
transactionLoad
Loads objects from one or more tables using one call to the AmazonDynamoDB.transactGetItems
method.
For more information about DynamoDB transactions and the provided atomicity, consistency, isolation,
and durability (ACID) guarantees see Amazon DynamoDB Transactions.
The following Java code loads one item from each of the Forum and Thread tables, transactionally.
count
Evaluates the specified scan expression and returns the count of matching items. No item data is
returned.
generateCreateTableRequest
Parses a POJO class that represents a DynamoDB table, and returns a CreateTableRequest for that
table.
createS3Link
Creates a link to an object in Amazon S3. You must specify a bucket name and a key name, which
uniquely identifies the object in the bucket.
To use createS3Link, your mapper class must define getter and setter methods. The following code
example illustrates this by adding a new attribute and getter/setter methods to the CatalogItem class.
@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {
...
....
@DynamoDBAttribute(attributeName = "ProductImage")
public S3Link getProductImage() {
return productImage;
}
...
}
The following Java code defines a new item to be written to the Product table. The item includes a link
to a product image; the image data is uploaded to Amazon S3.
item.id = 150;
item.title = "Book 150 Title";
item.getProductImage().uploadFrom(new File("/file/path/book_150_cover.jpg"));
mapper.save(item);
The S3Link class provides many other methods for manipulating objects in Amazon S3. For more
information, see the Javadocs for S3Link.
getS3ClientCache
Returns the underlying S3ClientCache for accessing Amazon S3. An S3ClientCache is a smart Map
for AmazonS3Client objects. If you have multiple clients, an S3ClientCache can help you keep the
clients organized by AWS Region, and can create new Amazon S3 clients on demand.
.withPaginationLoadingStrategy(DynamoDBMapperConfig.PaginationLoadingStrategy.EAGER_LOADING)
.build();
For more information, see DynamoDBMapperConfig in the AWS SDK for Java API Reference.
If you do not specify a read consistency setting for your mapper instance, the default is EVENTUAL.
• A DynamoDBMapperConfig.PaginationLoadingStrategy enumeration value—Controls how the
mapper instance processes a paginated list of data, such as the results from a query or scan:
• LAZY_LOADING—the mapper instance loads data when possible, and keeps all loaded results in
memory.
• EAGER_LOADING—the mapper instance loads the data as soon as the list is initialized.
• ITERATION_ONLY—you can only use an Iterator to read from the list. During the iteration, the list
will clear all the previous results before loading the next page, so that the list will keep at most
one page of the loaded results in memory. This also means the list can only be iterated once. This
strategy is recommended when handling large items, in order to reduce memory overhead.
If you do not specify a pagination loading strategy for your mapper instance, the default is
LAZY_LOADING.
• A DynamoDBMapperConfig.SaveBehavior enumeration value - Specifies how the mapper instance
should deal with attributes during save operations:
• UPDATE—during a save operation, all modeled attributes are updated, and unmodeled attributes are
unaffected. Primitive number types (byte, int, long) are set to 0. Object types are set to null.
• CLOBBER—clears and replaces all attributes, included unmodeled ones, during a save operation. This
is done by deleting the item and re-creating it. Versioned field constraints are also disregarded.
If you do not specify the save behavior for your mapper instance, the default is UPDATE.
Note
DynamoDBMapper transactional operations do not support
DynamoDBMapperConfig.SaveBehavior enumeration.
• A DynamoDBMapperConfig.TableNameOverride object—Instructs the mapper instance to ignore
the table name specified by a class's DynamoDBTable annotation, and instead use a different table
name that you supply. This is useful when partitioning your data into multiple tables at runtime.
You can override the default configuration object for DynamoDBMapper per operation, as needed.
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.datamodeling;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
@DynamoDBTable(tableName = "ProductCatalog")
public static class CatalogItem {
private Integer id;
private String title;
private String ISBN;
private Set<String> bookAuthors;
// Partition key
@DynamoDBHashKey(attributeName = "Id")
public Integer getId() {
return id;
}
@DynamoDBAttribute(attributeName = "Title")
public String getTitle() {
return title;
}
@DynamoDBAttribute(attributeName = "ISBN")
public String getISBN() {
return ISBN;
}
@DynamoDBAttribute(attributeName = "Authors")
public Set<String> getBookAuthors() {
return bookAuthors;
}
@Override
public String toString() {
return "Book [ISBN=" + ISBN + ", bookAuthors=" + bookAuthors + ", id=" + id +
", title=" + title + "]";
}
}
For more information about the tables used in this example, see Creating Tables and Loading Data for
Code Examples in DynamoDB (p. 326). For step-by-step instructions for testing the following example,
see Java Code Examples (p. 331).
Example
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.datamodeling;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
testBatchSave(mapper);
testBatchDelete(mapper);
testBatchWrite(mapper);
System.out.println("Example complete!");
}
catch (Throwable t) {
@DynamoDBTable(tableName = "ProductCatalog")
public static class Book {
private int id;
private String title;
private String ISBN;
private int price;
private int pageCount;
private String productCategory;
private boolean inPublication;
// Partition key
@DynamoDBHashKey(attributeName = "Id")
public int getId() {
return id;
}
@DynamoDBAttribute(attributeName = "Title")
public String getTitle() {
return title;
}
@DynamoDBAttribute(attributeName = "ISBN")
public String getISBN() {
return ISBN;
}
@DynamoDBAttribute(attributeName = "Price")
public int getPrice() {
return price;
}
@DynamoDBAttribute(attributeName = "PageCount")
public int getPageCount() {
return pageCount;
}
@DynamoDBAttribute(attributeName = "ProductCategory")
public String getProductCategory() {
return productCategory;
}
@DynamoDBAttribute(attributeName = "InPublication")
public boolean getInPublication() {
return inPublication;
}
@Override
public String toString() {
return "Book [ISBN=" + ISBN + ", price=" + price + ", product category=" +
productCategory + ", id=" + id
+ ", title=" + title + "]";
}
@DynamoDBTable(tableName = "Reply")
public static class Reply {
private String id;
private String replyDateTime;
private String message;
private String postedBy;
// Partition key
@DynamoDBHashKey(attributeName = "Id")
public String getId() {
return id;
}
// Sort key
@DynamoDBRangeKey(attributeName = "ReplyDateTime")
public String getReplyDateTime() {
return replyDateTime;
}
@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}
@DynamoDBAttribute(attributeName = "PostedBy")
public String getPostedBy() {
return postedBy;
}
@DynamoDBTable(tableName = "Thread")
public static class Thread {
private String forumName;
private String subject;
private String message;
private String lastPostedDateTime;
private String lastPostedBy;
private Set<String> tags;
private int answered;
private int views;
private int replies;
// Partition key
@DynamoDBHashKey(attributeName = "ForumName")
public String getForumName() {
return forumName;
}
// Sort key
@DynamoDBRangeKey(attributeName = "Subject")
public String getSubject() {
return subject;
}
@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}
@DynamoDBAttribute(attributeName = "LastPostedDateTime")
public String getLastPostedDateTime() {
return lastPostedDateTime;
}
@DynamoDBAttribute(attributeName = "LastPostedBy")
public String getLastPostedBy() {
return lastPostedBy;
}
@DynamoDBAttribute(attributeName = "Tags")
public Set<String> getTags() {
return tags;
}
@DynamoDBAttribute(attributeName = "Answered")
public int getAnswered() {
return answered;
}
@DynamoDBAttribute(attributeName = "Views")
public int getViews() {
return views;
}
@DynamoDBAttribute(attributeName = "Replies")
public int getReplies() {
return replies;
}
@DynamoDBTable(tableName = "Forum")
public static class Forum {
private String name;
private String category;
private int threads;
// Partition key
@DynamoDBHashKey(attributeName = "Name")
public String getName() {
return name;
}
@DynamoDBAttribute(attributeName = "Category")
public String getCategory() {
return category;
}
@DynamoDBAttribute(attributeName = "Threads")
public int getThreads() {
return threads;
}
The example then executes the follow query and scan operations using a DynamoDBMapper instance.
The ProductCatalog table has Id as its primary key. It does not have a sort key as part of its primary
key. Therefore, you cannot query the table. You can get an item using its Id value.
• Execute the following queries against the Reply table.
The Reply table's primary key is composed of Id and ReplyDateTime attributes. ReplyDateTime is
a sort key. Therefore, you can query this table.
• Find replies to a forum thread posted in the last 15 days.
• Find replies to a forum thread posted in a specific date range.
• Scan the ProductCatalog table to find books whose price is less than a specified value.
For performance reasons, you should use the query operation instead of the scan operation. However,
there are times you might need to scan a table. Suppose that there was a data entry error and one of
the book prices was set to less than 0. This example scans the ProductCategory table to find book
items (ProductCategory is book) whose price is less than 0.
• Perform a parallel scan of the ProductCatalog table to find bicycles of a specific type.
Note
This code example assumes that you have already loaded data into DynamoDB for your account
by following the instructions in the Creating Tables and Loading Data for Code Examples in
DynamoDB (p. 326) section.
For step-by-step instructions to run the following example, see Java Code Examples (p. 331).
Example
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.datamodeling;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
// Scan a table and find book items priced less than specified
// value.
FindBooksPricedLessThanSpecifiedValue(mapper, "20");
// Scan a table with multiple threads and find bicycle items with a
// specified bicycle type
int numberOfThreads = 16;
FindBicyclesOfSpecificTypeWithMultipleThreads(mapper, numberOfThreads, "Road");
System.out.println("Example complete!");
}
catch (Throwable t) {
System.err.println("Error running the DynamoDBMapperQueryScanExample: " + t);
t.printStackTrace();
}
}
System.out.println("Book table has no sort key. You can do GetItem, but not
Query.");
Book book = mapper.load(Book.class, id);
System.out.format("Id = %s Title = %s, ISBN = %s %n", book.getId(),
book.getTitle(), book.getISBN());
}
System.out.println(
"FindRepliesPostedWithinTimePeriod: Find replies for thread Message = 'DynamoDB
Thread 2' posted within a period.");
long startDateMilli = (new Date()).getTime() - (14L * 24L * 60L * 60L * 1000L); //
Two
//
weeks
//
ago.
long endDateMilli = (new Date()).getTime() - (7L * 24L * 60L * 60L * 1000L); // One
//
week
//
ago.
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-
dd'T'HH:mm:ss.SSS'Z'");
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String startDate = dateFormatter.format(startDateMilli);
String endDate = dateFormatter.format(endDateMilli);
System.out.println("FindBicyclesOfSpecificTypeWithMultipleThreads: Scan
ProductCatalog With Multiple Threads.");
Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
eav.put(":val1", new AttributeValue().withS("Bicycle"));
eav.put(":val2", new AttributeValue().withS(bicycleType));
@DynamoDBTable(tableName = "ProductCatalog")
public static class Book {
private int id;
private String title;
private String ISBN;
@DynamoDBHashKey(attributeName = "Id")
public int getId() {
return id;
}
@DynamoDBAttribute(attributeName = "Title")
public String getTitle() {
return title;
}
@DynamoDBAttribute(attributeName = "ISBN")
public String getISBN() {
return ISBN;
}
@DynamoDBAttribute(attributeName = "Price")
public int getPrice() {
return price;
}
@DynamoDBAttribute(attributeName = "PageCount")
public int getPageCount() {
return pageCount;
}
@DynamoDBAttribute(attributeName = "ProductCategory")
public String getProductCategory() {
return productCategory;
}
@DynamoDBAttribute(attributeName = "InPublication")
public boolean getInPublication() {
return inPublication;
}
@Override
public String toString() {
return "Book [ISBN=" + ISBN + ", price=" + price + ", product category=" +
productCategory + ", id=" + id
+ ", title=" + title + "]";
}
@DynamoDBTable(tableName = "ProductCatalog")
public static class Bicycle {
private int id;
private String title;
private String description;
private String bicycleType;
private String brand;
private int price;
private List<String> color;
private String productCategory;
@DynamoDBHashKey(attributeName = "Id")
public int getId() {
return id;
}
@DynamoDBAttribute(attributeName = "Title")
public String getTitle() {
return title;
}
@DynamoDBAttribute(attributeName = "Description")
public String getDescription() {
return description;
}
@DynamoDBAttribute(attributeName = "BicycleType")
public String getBicycleType() {
return bicycleType;
}
@DynamoDBAttribute(attributeName = "Brand")
public String getBrand() {
return brand;
}
@DynamoDBAttribute(attributeName = "Price")
public int getPrice() {
return price;
}
@DynamoDBAttribute(attributeName = "Color")
public List<String> getColor() {
return color;
}
@DynamoDBAttribute(attributeName = "ProductCategory")
public String getProductCategory() {
return productCategory;
}
@Override
public String toString() {
return "Bicycle [Type=" + bicycleType + ", color=" + color + ", price=" + price
+ ", product category="
+ productCategory + ", id=" + id + ", title=" + title + "]";
}
@DynamoDBTable(tableName = "Reply")
public static class Reply {
private String id;
private String replyDateTime;
private String message;
private String postedBy;
// Partition key
@DynamoDBHashKey(attributeName = "Id")
public String getId() {
return id;
}
// Range key
@DynamoDBRangeKey(attributeName = "ReplyDateTime")
public String getReplyDateTime() {
return replyDateTime;
}
@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}
@DynamoDBAttribute(attributeName = "PostedBy")
public String getPostedBy() {
return postedBy;
}
@DynamoDBTable(tableName = "Thread")
public static class Thread {
private String forumName;
private String subject;
private String message;
private String lastPostedDateTime;
private String lastPostedBy;
private Set<String> tags;
private int answered;
private int views;
private int replies;
// Partition key
@DynamoDBHashKey(attributeName = "ForumName")
public String getForumName() {
return forumName;
}
// Range key
@DynamoDBRangeKey(attributeName = "Subject")
public String getSubject() {
return subject;
}
@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}
@DynamoDBAttribute(attributeName = "LastPostedDateTime")
public String getLastPostedDateTime() {
return lastPostedDateTime;
}
@DynamoDBAttribute(attributeName = "LastPostedBy")
public String getLastPostedBy() {
return lastPostedBy;
}
@DynamoDBAttribute(attributeName = "Tags")
public Set<String> getTags() {
return tags;
}
@DynamoDBAttribute(attributeName = "Answered")
public int getAnswered() {
return answered;
}
@DynamoDBAttribute(attributeName = "Views")
public int getViews() {
return views;
}
@DynamoDBAttribute(attributeName = "Replies")
public int getReplies() {
return replies;
}
@DynamoDBTable(tableName = "Forum")
public static class Forum {
private String name;
private String category;
private int threads;
@DynamoDBHashKey(attributeName = "Name")
public String getName() {
return name;
}
@DynamoDBAttribute(attributeName = "Category")
public String getCategory() {
return category;
@DynamoDBAttribute(attributeName = "Threads")
public int getThreads() {
return threads;
}
• transactionWrite to add, update, and delete multiple items from one or more tables in one
transaction.
• transactionLoad to retrieve multiple items from one or more tables in one transaction.
Example
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.TransactionWriteRequest;
import com.amazonaws.services.dynamodbv2.datamodeling.TransactionLoadRequest;
import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTransactionWriteExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTransactionLoadExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException;
import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException;
import com.amazonaws.services.dynamodbv2.model.InternalServerErrorException;
testPutAndUpdateInTransactionWrite();
testPutWithConditionalUpdateInTransactionWrite();
testPutWithConditionCheckInTransactionWrite();
testMixedOperationsInTransactionWrite();
testTransactionLoadWithSave();
testTransactionLoadWithTransactionWrite();
System.out.println("Example complete");
}
catch (Throwable t) {
System.err.println("Error running the DynamoDBMapperTransactionWriteExample: "
+ t);
t.printStackTrace();
}
}
// Read DynamoDB Forum item and Thread item at the same time in a serializable
manner
TransactionLoadRequest transactionLoadRequest = new TransactionLoadRequest();
.withProjectionExpression("Subject, Message");
transactionLoadRequest.addLoad(dynamodbForumThread, loadExpressionForThread);
// Loaded objects are guaranteed to be in same order as the order in which they are
// added to TransactionLoadRequest
List<Object> loadedObjects = executeTransactionLoad(transactionLoadRequest);
Forum loadedDynamoDBForum = (Forum) loadedObjects.get(0);
System.out.println("Forum: " + loadedDynamoDBForum.name);
System.out.println("Threads: " + loadedDynamoDBForum.threads);
Thread loadedDynamodbForumThread = (Thread) loadedObjects.get(1);
System.out.println("Subject: " + loadedDynamodbForumThread.subject);
System.out.println("Message: " + loadedDynamodbForumThread.message);
}
// Update Forum item for DynamoDB and add a thread to DynamoDB Forum, in
// an ACID manner using transactionWrite
dynamodbForum.threads = 1;
Thread dynamodbForumThread = new Thread();
dynamodbForumThread.forumName = "DynamoDB New Forum";
dynamodbForumThread.subject = "Sample Subject 2";
dynamodbForumThread.message = "Sample Question 2";
TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();
transactionWriteRequest.addPut(dynamodbForumThread);
transactionWriteRequest.addUpdate(dynamodbForum);
executeTransactionWrite(transactionWriteRequest);
// Read DynamoDB Forum item and Thread item at the same time in a serializable
manner
TransactionLoadRequest transactionLoadRequest = new TransactionLoadRequest();
.withProjectionExpression("Subject, Message");
transactionLoadRequest.addLoad(dynamodbForumThread, loadExpressionForThread);
// Loaded objects are guaranteed to be in same order as the order in which they are
// added to TransactionLoadRequest
List<Object> loadedObjects = executeTransactionLoad(transactionLoadRequest);
Forum loadedDynamoDBForum = (Forum) loadedObjects.get(0);
System.out.println("Forum: " + loadedDynamoDBForum.name);
System.out.println("Threads: " + loadedDynamoDBForum.threads);
Thread loadedDynamodbForumThread = (Thread) loadedObjects.get(1);
System.out.println("Subject: " + loadedDynamodbForumThread.subject);
System.out.println("Message: " + loadedDynamodbForumThread.message);
}
mapper.save(s3Forum);
// Update Forum item for S3 and Create new Forum item for DynamoDB using
transactionWrite
s3Forum.category = "Amazon Web Services";
Forum dynamodbForum = new Forum();
dynamodbForum.name = "DynamoDB Forum";
dynamodbForum.category = "Amazon Web Services";
dynamodbForum.threads = 0;
TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();
transactionWriteRequest.addUpdate(s3Forum);
transactionWriteRequest.addPut(dynamodbForum);
executeTransactionWrite(transactionWriteRequest);
}
.withConditionExpression("attribute_exists(Category)");
.withConditionExpression("attribute_exists(Subject)");
executeTransactionWrite(transactionWriteRequest);
}
.withConditionExpression("attribute_exists(Subject)");
return loadedObjects;
}
private static void executeTransactionWrite(TransactionWriteRequest
transactionWriteRequest) {
try {
mapper.transactionWrite(transactionWriteRequest);
} catch (DynamoDBMappingException ddbme) {
System.err.println("Client side error in Mapper, fix before retrying. Error: "
+ ddbme.getMessage());
} catch (ResourceNotFoundException rnfe) {
System.err.println("One of the tables was not found, verify table exists before
retrying. Error: " + rnfe.getMessage());
} catch (InternalServerErrorException ise) {
System.err.println("Internal Server Error, generally safe to retry with back-
off. Error: " + ise.getMessage());
} catch (TransactionCanceledException tce) {
System.err.println("Transaction Canceled, implies a client issue, fix before
retrying. Error: " + tce.getMessage());
} catch (Exception ex) {
System.err.println("An exception occurred, investigate and configure retry
strategy. Error: " + ex.getMessage());
}
}
@DynamoDBTable(tableName = "Thread")
public static class Thread {
private String forumName;
private String subject;
private String message;
private String lastPostedDateTime;
private String lastPostedBy;
private Set<String> tags;
private int answered;
private int views;
private int replies;
// Partition key
@DynamoDBHashKey(attributeName = "ForumName")
public String getForumName() {
return forumName;
}
// Sort key
@DynamoDBRangeKey(attributeName = "Subject")
public String getSubject() {
return subject;
}
@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}
@DynamoDBAttribute(attributeName = "LastPostedDateTime")
@DynamoDBAttribute(attributeName = "LastPostedBy")
public String getLastPostedBy() {
return lastPostedBy;
}
@DynamoDBAttribute(attributeName = "Tags")
public Set<String> getTags() {
return tags;
}
@DynamoDBAttribute(attributeName = "Answered")
public int getAnswered() {
return answered;
}
@DynamoDBAttribute(attributeName = "Views")
public int getViews() {
return views;
}
@DynamoDBAttribute(attributeName = "Replies")
public int getReplies() {
return replies;
}
@DynamoDBTable(tableName = "Forum")
public static class Forum {
private String name;
private String category;
private int threads;
// Partition key
@DynamoDBHashKey(attributeName = "Name")
public String getName() {
return name;
}
@DynamoDBAttribute(attributeName = "Category")
public String getCategory() {
return category;
}
@DynamoDBAttribute(attributeName = "Threads")
public int getThreads() {
return threads;
}
With optimistic locking, each item has an attribute that acts as a version number. If you retrieve an item
from a table, the application records the version number of that item. You can update the item, but only
if the version number on the server side has not changed. If there is a version mismatch, it means that
someone else has modified the item before you did. The update attempt fails, because you have a stale
version of the item. If this happens, you simply try again by retrieving the item and then trying to update
it. Optimistic locking prevents you from accidentally overwriting changes that were made by others. It
also prevents others from accidentally overwriting your changes.
To support optimistic locking, the AWS SDK for Java provides the @DynamoDBVersionAttribute
annotation. In the mapping class for your table, you designate one property to store the version number,
and mark it using this annotation. When you save an object, the corresponding item in the DynamoDB
table will have an attribute that stores the version number. The DynamoDBMapper assigns a version
number when you first save the object, and it automatically increments the version number each time
you update the item. Your update or delete requests succeed only if the client-side object version
matches the corresponding version number of the item in the DynamoDB table.
• You use optimistic locking with @DynamoDBVersionAttribute and the version value on the server is
different from the value on the client side.
• You specify your own conditional constraints while saving data by using DynamoDBMapper with
DynamoDBSaveExpression and these constraints failed.
Note
• DynamoDB global tables use a “last writer wins” reconciliation between concurrent updates.
If you use global tables, last writer policy wins. So in this case, the locking strategy does not
work as expected.
For example, the following Java code defines a CatalogItem class that has several properties. The
Version property is tagged with the @DynamoDBVersionAttribute annotation.
Example
@DynamoDBTable(tableName="ProductCatalog")
public class CatalogItem {
@DynamoDBHashKey(attributeName="Id")
public Integer getId() { return id; }
public void setId(Integer Id) { this.id = Id; }
@DynamoDBAttribute(attributeName="Title")
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
@DynamoDBAttribute(attributeName="ISBN")
public String getISBN() { return ISBN; }
public void setISBN(String ISBN) { this.ISBN = ISBN;}
@DynamoDBAttribute(attributeName = "Authors")
public Set<String> getBookAuthors() { return bookAuthors; }
public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; }
@DynamoDBIgnore
public String getSomeProp() { return someProp;}
public void setSomeProp(String someProp) {this.someProp = someProp;}
@DynamoDBVersionAttribute
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version;}
}
You can apply the @DynamoDBVersionAttribute annotation to nullable types provided by the
primitive wrappers classes that provide a nullable type, such as Long and Integer.
• save — For a new item, the DynamoDBMapper assigns an initial version number of 1. If you
retrieve an item, update one or more of its properties, and attempt to save the changes, the save
operation succeeds only if the version number on the client side and the server side match. The
DynamoDBMapper increments the version number automatically.
• delete — The delete method takes an object as a parameter, and the DynamoDBMapper
performs a version check before deleting the item. The version check can be disabled if
DynamoDBMapperConfig.SaveBehavior.CLOBBER is specified in the request.
The internal implementation of optimistic locking within DynamoDBMapper uses conditional update
and conditional delete support provided by DynamoDB.
• transactionWrite —
• Put — For a new item, the DynamoDBMapper assigns an initial version number of 1. If you
retrieve an item, update one or more of its properties, and attempt to save the changes, the put
operation succeeds only if the version number on the client side and the server side match. The
DynamoDBMapper increments the version number automatically.
• Update — For a new item, the DynamoDBMapper assigns an initial version number of 1. If you
retrieve an item, update one or more of its properties, and attempt to save the changes, the update
operation succeeds only if the version number on the client side and the server side match. The
DynamoDBMapper increments the version number automatically.
• Delete — The DynamoDBMapper performs a version check before deleting the item. The delete
operation succeeds only if the version number on the client side and the server side match.
• ConditionCheck — The @DynamoDBVersionAttribute annotation is not supported for
ConditionCheck operations. An SdkClientException will be thrown when a ConditionCheck item
is annotated with @DynamoDBVersionAttribute.
You can also set locking behavior for a specific operation only. For example, the
following Java snippet uses the DynamoDBMapper to save a catalog item. It specifies
DynamoDBMapperConfig.SaveBehavior by adding the optional DynamoDBMapperConfig parameter
to the save method.
Note
The transactionWrite method does not support DynamoDBMapperConfig.SaveBehavior
configuration. Disabling optimistic locking for transactionWrite is not supported.
Example
For example, consider the following CatalogItem class that defines a property, Dimension, that is of
DimensionType. This property stores the item dimensions as height, width, and thickness. Assume that
you decide to store these item dimensions as a string (such as 8.5x11x.05) in DynamoDB. The following
example provides converter code that converts the DimensionType object to a string and a string to the
DimensionType.
Note
This code example assumes that you have already loaded data into DynamoDB for your account
by following the instructions in the Creating Tables and Loading Data for Code Examples in
DynamoDB (p. 326) section.
For step-by-step instructions to run the following example, see Java Code Examples (p. 331).
Example
/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.amazonaws.codesamples.datamodeling;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverted;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
bookRetrieved.getDimensions().setHeight("9.0");
bookRetrieved.getDimensions().setLength("12.0");
bookRetrieved.getDimensions().setThickness("2.0");
mapper.save(bookRetrieved);
@DynamoDBTable(tableName = "ProductCatalog")
public static class Book {
private int id;
private String title;
private String ISBN;
private Set<String> bookAuthors;
private DimensionType dimensionType;
// Partition key
@DynamoDBHashKey(attributeName = "Id")
public int getId() {
return id;
}
@DynamoDBAttribute(attributeName = "Title")
public String getTitle() {
return title;
}
@DynamoDBAttribute(attributeName = "ISBN")
public String getISBN() {
return ISBN;
}
@DynamoDBAttribute(attributeName = "Authors")
public Set<String> getBookAuthors() {
return bookAuthors;
}
@DynamoDBTypeConverted(converter = DimensionTypeConverter.class)
@DynamoDBAttribute(attributeName = "Dimensions")
public DimensionType getDimensions() {
return dimensionType;
}
@DynamoDBAttribute(attributeName = "Dimensions")
public void setDimensions(DimensionType dimensionType) {
this.dimensionType = dimensionType;
}
@Override
public String toString() {
return "Book [ISBN=" + ISBN + ", bookAuthors=" + bookAuthors + ",
dimensionType= "
+ dimensionType.getHeight() + " X " + dimensionType.getLength() + " X " +
dimensionType.getThickness()
+ ", Id=" + id + ", Title=" + title + "]";
}
}
@Override
public String convert(DimensionType object) {
DimensionType itemDimensions = (DimensionType) object;
String dimension = null;
try {
if (itemDimensions != null) {
dimension = String.format("%s x %s x %s", itemDimensions.getLength(),
itemDimensions.getHeight(),
itemDimensions.getThickness());
}
}
catch (Exception e) {
e.printStackTrace();
}
return dimension;
@Override
public DimensionType unconvert(String s) {
return itemDimension;
}
}
}
The AWS SDK for .NET provides document model classes that wrap some of the low-level Amazon
DynamoDB operations, further simplifying your coding. In the document model, the primary classes are
Table and Document. The Table class provides data operation methods such as PutItem, GetItem,
and DeleteItem. It also provides the Query and the Scan methods. The Document class represents a
single item in a table.
Working with Items in DynamoDB Using the AWS SDK for .NET
Document Model
Topics
To perform data operations using the document model, you must first call the Table.LoadTable
method, which creates an instance of the Table class that represents a specific table. The following C#
example creates a Table object that represents the ProductCatalog table in Amazon DynamoDB.
Example
Note
In general, you use the LoadTable method once at the beginning of your application because it
makes a DescribeTable call that adds to the round trip to DynamoDB.
You can then use the Table object to perform various data operations. Each data operation has
two types of overloads: One takes the minimum required parameters and the other takes optional,
operation-specific configuration information. For example, to retrieve an item, you must provide the
table's primary key value, in which case you can use the following GetItem overload.
Example
// Get the item from a table that has a primary key that is composed of only a partition
key.
Table.GetItem(Primitive partitionKey);
// Get the item from a table whose primary key is composed of both a partition key and sort
key.
Table.GetItem(Primitive partitionKey, Primitive sortKey);
You also can pass optional parameters to these methods. For example, the preceding GetItem returns
the entire item including all its attributes. You can optionally specify a list of attributes to retrieve. In this
case, you use the following GetItem overload that takes in the operation-specific configuration object
parameter.
Example
You can use the configuration object to specify several optional parameters such as request a specific
list of attributes or specify the page size (number of items per page). Each data operation method has
its own configuration class. For example, you can use the GetItemOperationConfig class to provide
options for the GetItem operation. You can use the PutItemOperationConfig class to provide
optional parameters for the PutItem operation.
The following sections discuss each of the data operations that are supported by the Table class.
The following are the steps to put a new item into a table using the AWS SDK for .NET document model.
1. Execute the Table.LoadTable method that provides the table name in which you want to put an
item.
2. Create a Document object that has a l