0% found this document useful (0 votes)
101 views1,144 pages

Dynamodb DG

AWS

Uploaded by

habriwwo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
101 views1,144 pages

Dynamodb DG

AWS

Uploaded by

habriwwo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1144

Amazon DynamoDB

Developer Guide
API Version 2012-08-10
Amazon DynamoDB Developer Guide

Amazon DynamoDB: Developer Guide


Copyright © 2020 Amazon Web Services, Inc. and/or its affiliates. All rights reserved.

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

API Version 2012-08-10


iii
Amazon DynamoDB Developer Guide

Step 5: Query Data .................................................................................................................. 67


Step 6: Create a Global Secondary Index ..................................................................................... 69
Step 7: Query the Global Secondary Index .................................................................................. 72
Step 8: (Optional) Clean Up ....................................................................................................... 74
Next Steps ............................................................................................................................... 74
Getting Started with the AWS SDKs ................................................................................................... 76
Java and DynamoDB ................................................................................................................. 76
Tutorial Prerequisites ........................................................................................................ 76
Step 1: Create a Table ...................................................................................................... 77
Step 2: Load Sample Data ................................................................................................. 78
Step 3: Create, Read, Update, and Delete an Item ................................................................. 81
Step 4: Query and Scan the Data ....................................................................................... 89
Step 5: (Optional) Delete the Table .................................................................................... 94
Summary ........................................................................................................................ 95
JavaScript and DynamoDB ......................................................................................................... 95
Tutorial Prerequisites ........................................................................................................ 96
Step 1: Create a Table ...................................................................................................... 96
Step 2: Load Sample Data ................................................................................................. 98
Step 3: Create, Read, Update, and Delete an Item ............................................................... 101
Step 4: Query and Scan the Data ..................................................................................... 111
Step 5: (Optional): Delete the Table .................................................................................. 116
Summary ....................................................................................................................... 117
Node.js and DynamoDB ........................................................................................................... 118
Tutorial Prerequisites ...................................................................................................... 118
Step 1: Create a Table ..................................................................................................... 118
Step 2: Load Sample Data ............................................................................................... 119
Step 3: Create, Read, Update, and Delete an Item ............................................................... 122
Step 4: Query and Scan Data ........................................................................................... 130
Step 5: (Optional): Delete the Table .................................................................................. 134
Summary ....................................................................................................................... 135
.NET and DynamoDB ............................................................................................................... 135
Tutorial Prerequisites ...................................................................................................... 136
Step 1: Create a Client .................................................................................................... 137
Step 2: Create a Table ..................................................................................................... 139
Step 3: Load Data .......................................................................................................... 142
Step 4: Add a Movie ....................................................................................................... 145
Step 5: Read a Movie ...................................................................................................... 146
Step 6: Update the Movie ................................................................................................ 147
Step 7: Delete an Item with Conditions ............................................................................. 150
Step 8: Query a Table ..................................................................................................... 152
Step 9: Scan a Table ....................................................................................................... 155
Step 10: Delete the Table ................................................................................................ 156
PHP and DynamoDB ............................................................................................................... 157
Tutorial Prerequisites ...................................................................................................... 157
Step 1: Create a Table ..................................................................................................... 158
Step 2: Load Sample Data ............................................................................................... 159
Step 3: Create, Read, Update, and Delete an Item ............................................................... 162
Step 4: Query and Scan the Data ..................................................................................... 171
Step 5: (Optional) Delete the Table ................................................................................... 176
Summary ....................................................................................................................... 177
Python and DynamoDB ........................................................................................................... 178
Tutorial Prerequisites ...................................................................................................... 178
Step 1: Create a Table ..................................................................................................... 178
Step 2: Load Sample Data ............................................................................................... 179
Step 3: Crud Operations .................................................................................................. 182
Step 4: Query and Scan the Data ..................................................................................... 190
Step 5: (Optional) Delete the Table ................................................................................... 194

API Version 2012-08-10


iv
Amazon DynamoDB Developer Guide

Summary ....................................................................................................................... 194


Ruby and DynamoDB .............................................................................................................. 195
Tutorial Prerequisites ...................................................................................................... 195
Step 1: Create a Table ..................................................................................................... 196
Step 2: Load Sample Data ............................................................................................... 197
Step 3: Create, Read, Update, and Delete an Item ............................................................... 199
Step 4: Query and Scan the Data ..................................................................................... 207
Step 5: (Optional) Delete the Table ................................................................................... 211
Summary ....................................................................................................................... 212
Programming with DynamoDB ......................................................................................................... 214
Overview of AWS SDK Support for DynamoDB ........................................................................... 214
Programmatic Interfaces .......................................................................................................... 216
Low-Level Interfaces ....................................................................................................... 217
Document Interfaces ....................................................................................................... 218
Object Persistence Interface ............................................................................................. 218
Low-Level API ........................................................................................................................ 220
Request Format .............................................................................................................. 221
Response Format ............................................................................................................ 222
Data Type Descriptors ..................................................................................................... 222
Numeric Data ................................................................................................................. 223
Binary Data .................................................................................................................... 223
Error Handling ....................................................................................................................... 223
Error Components .......................................................................................................... 224
Error Messages and Codes ............................................................................................... 224
Error Handling in Your Application .................................................................................... 227
Error Retries and Exponential Backoff ............................................................................... 228
Batch Operations and Error Handling ................................................................................ 228
Higher-Level Programming Interfaces for DynamoDB .................................................................. 229
Java: DynamoDBMapper .................................................................................................. 229
.NET: Document Model .................................................................................................... 276
.NET: Object Persistence Model ........................................................................................ 297
Running the Code Examples .................................................................................................... 325
Load Sample Data .......................................................................................................... 326
Java Code Examples ........................................................................................................ 331
.NET Code Examples ....................................................................................................... 333
Working with DynamoDB ................................................................................................................ 336
Working with Tables ............................................................................................................... 336
Basic Operations on Tables .............................................................................................. 336
Considerations When Changing Read/Write Capacity Mode .................................................. 341
Provisioned Capacity Tables ............................................................................................. 342
Item Sizes and Formats ................................................................................................... 346
Managing Throughput Capacity with Auto Scaling .............................................................. 346
Tagging Resources .......................................................................................................... 360
Working with Tables: Java .............................................................................................. 363
Working with Tables: .NET ............................................................................................... 368
Working with Items ................................................................................................................ 375
Reading an Item ............................................................................................................. 376
Writing an Item .............................................................................................................. 376
Return Values ................................................................................................................. 378
Batch Operations ............................................................................................................ 379
Atomic Counters ............................................................................................................. 381
Conditional Writes .......................................................................................................... 381
Using Expressions ........................................................................................................... 386
Expiring Items with Time to Live ...................................................................................... 409
Working with Items: Java ................................................................................................ 415
Working with Items: .NET ................................................................................................ 435
Working with Queries ............................................................................................................. 458

API Version 2012-08-10


v
Amazon DynamoDB Developer Guide

Key Condition Expression ................................................................................................. 459


Filter Expressions for Query ............................................................................................. 461
Limiting the Number of Items in the Result Set .................................................................. 461
Paginating Query Results ................................................................................................ 462
Counting the Items in the Results ..................................................................................... 463
Capacity Units Consumed by Query .................................................................................. 463
Read Consistency for Query ............................................................................................. 464
Querying: Java ............................................................................................................... 464
Querying: .NET ............................................................................................................... 470
Working with Scans ................................................................................................................ 476
Filter Expressions for Scan ............................................................................................... 476
Limiting the Number of Items in the Result Set .................................................................. 477
Paginating the Results .................................................................................................... 477
Counting the Items in the Results ..................................................................................... 478
Capacity Units Consumed by Scan .................................................................................... 479
Read Consistency for Scan ............................................................................................... 479
Parallel Scan .................................................................................................................. 480
Scanning: Java ............................................................................................................... 482
Scanning: .NET ............................................................................................................... 489
Working with Indexes .............................................................................................................. 497
Global Secondary Indexes ................................................................................................ 500
Local Secondary Indexes .................................................................................................. 537
Working with Streams ............................................................................................................. 574
Endpoints for DynamoDB Streams .................................................................................... 575
Enabling a Stream .......................................................................................................... 576
Reading and Processing a Stream ..................................................................................... 577
DynamoDB Streams and TTL ........................................................................................... 579
Using the DynamoDB Streams Kinesis Adapter to Process Stream Records .............................. 579
DynamoDB Streams Low-Level API: Java Example ............................................................... 591
Cross-Region Replication ................................................................................................. 595
DynamoDB Streams and AWS Lambda Triggers .................................................................. 595
On-Demand Backup and Restore ...................................................................................................... 604
How It Works ......................................................................................................................... 604
Backups ......................................................................................................................... 604
Restores ........................................................................................................................ 605
Backing Up a Table ................................................................................................................. 606
Creating a Table Backup (Console) .................................................................................... 607
Creating a Table Backup (AWS CLI) ................................................................................... 608
Restoring a Table from a Backup .............................................................................................. 609
Restoring a Table from a Backup (Console) ........................................................................ 609
Restoring a Table from a Backup (AWS CLI) ....................................................................... 612
Deleting a Table Backup .......................................................................................................... 614
Deleting a Table Backup (Console) .................................................................................... 614
Deleting a Table Backup (AWS CLI) ................................................................................... 616
Using IAM .............................................................................................................................. 616
Example 1: Allow the CreateBackup and RestoreTableFromBackup Actions ............................ 616
Example 2: Allow CreateBackup and Deny RestoreTableFromBackup ..................................... 617
Example 3: Allow ListBackups and Deny CreateBackup and RestoreTableFromBackup .............. 617
Example 4: Allow ListBackups and Deny DeleteBackup ....................................................... 618
Example 5: Allow RestoreTableFromBackup and DescribeBackup for All Resources and Deny
DeleteBackup for a Specific Backup .................................................................................. 618
Example 6: Allow CreateBackup for a Specific Table ........................................................... 619
Example 7: Allow ListBackups ......................................................................................... 619
Point-in-Time Recovery ................................................................................................................... 620
How It Works ......................................................................................................................... 620
Before You Begin .................................................................................................................... 621
Restoring a Table To a Point in Time ........................................................................................ 622

API Version 2012-08-10


vi
Amazon DynamoDB Developer Guide

Restoring a Table to a Point in Time (Console) ................................................................... 622


Restoring a Table to a Point in Time (AWS CLI) ................................................................... 623
Global Tables ................................................................................................................................. 626
Determine Version .................................................................................................................. 627
Version 2019.11.21 (Current) ................................................................................................... 627
How It Works ................................................................................................................. 628
Best Practices and Requirements ...................................................................................... 629
Tutorial: Creating a Global Table ...................................................................................... 629
Monitoring Global Tables ................................................................................................. 634
Using IAM with Global Tables .......................................................................................... 635
Updating ....................................................................................................................... 637
Version 2017.11.29 ................................................................................................................. 640
How It Works ................................................................................................................. 640
Best Practices and Requirements ...................................................................................... 642
Creating a Global Table ................................................................................................... 644
Monitoring Global Tables ................................................................................................. 646
Using IAM with Global Tables .......................................................................................... 647
DynamoDB Transactions .................................................................................................................. 650
How It Works ......................................................................................................................... 650
TransactWriteItems ......................................................................................................... 651
TransactGetItems ............................................................................................................ 652
Isolation Levels .............................................................................................................. 652
Transaction Conflict Handling .......................................................................................... 654
Transactions in DAX ........................................................................................................ 654
Capacity Management ..................................................................................................... 654
Best Practices ................................................................................................................. 655
Integration with Other Features ....................................................................................... 655
Transactions vs. the Client Library .................................................................................... 655
Using IAM with Transactions .................................................................................................... 656
Example 1: Allow Transactional Operations ........................................................................ 656
Example 2: Allow Only Transactional Operations ................................................................ 656
Example 3: Allow Nontransactional Reads and Writes, and Block Transactional Reads and
Writes ........................................................................................................................... 657
Example 4: Prevent Information from Being Returned on a ConditionCheck Failure .................. 657
Example Code ........................................................................................................................ 658
Making an Order ............................................................................................................ 658
Reading the Order Details ............................................................................................... 660
Additional Examples ....................................................................................................... 660
In-Memory Acceleration with DAX .................................................................................................... 661
Use Cases for DAX .................................................................................................................. 661
DAX Usage Notes ................................................................................................................... 662
How It Works ......................................................................................................................... 663
How DAX Processes Requests ........................................................................................... 664
Item Cache .................................................................................................................... 665
Query Cache .................................................................................................................. 665
DAX Cluster Components ......................................................................................................... 666
Nodes ........................................................................................................................... 666
Clusters ......................................................................................................................... 666
Regions and Availability Zones ......................................................................................... 667
Parameter Groups ........................................................................................................... 668
Security Groups .............................................................................................................. 668
Cluster ARN ................................................................................................................... 668
Cluster Endpoint ............................................................................................................. 668
Node Endpoints .............................................................................................................. 668
Subnet Groups ............................................................................................................... 669
Events ........................................................................................................................... 669
Maintenance Window ...................................................................................................... 669

API Version 2012-08-10


vii
Amazon DynamoDB Developer Guide

Creating a DAX Cluster ............................................................................................................ 670


Creating an IAM Service Role for DAX to Access DynamoDB ................................................. 670
Using the AWS CLI .......................................................................................................... 671
Using the Console .......................................................................................................... 675
Consistency Models ................................................................................................................. 678
Consistency Among DAX Cluster Nodes ............................................................................. 678
DAX Item Cache Behavior ................................................................................................ 678
DAX Query Cache Behavior .............................................................................................. 680
Strongly Consistent and Transactional Reads ...................................................................... 681
Negative Caching ............................................................................................................ 681
Strategies for Writes ....................................................................................................... 682
Developing with the DAX Client ............................................................................................... 684
Tutorial: Running a Sample Application ............................................................................. 684
Modifying an Existing Application to Use DAX .................................................................... 722
Querying Global Secondary Indexes .................................................................................. 725
Managing DAX Clusters ........................................................................................................... 728
IAM Permissions for Managing a DAX Cluster ..................................................................... 728
Scaling a DAX Cluster ..................................................................................................... 730
Customizing DAX Cluster Settings ..................................................................................... 731
Configuring TTL Settings ................................................................................................. 731
Tagging Support for DAX ................................................................................................ 732
AWS CloudTrail Integration .............................................................................................. 733
Deleting a DAX Cluster .................................................................................................... 733
Monitoring DAX ...................................................................................................................... 734
Monitoring Tools ............................................................................................................ 734
Monitoring with CloudWatch ............................................................................................ 735
Logging DAX Operations Using AWS CloudTrail .................................................................. 747
DAX Access Control ................................................................................................................. 747
IAM Service Role for DAX ................................................................................................ 747
IAM Policy to Allow DAX Cluster Access ............................................................................. 748
Case Study: Accessing DynamoDB and DAX ........................................................................ 749
Access to DynamoDB, But No Access with DAX ................................................................... 750
Access to DynamoDB and to DAX ..................................................................................... 751
Access to DynamoDB Via DAX, But No Direct Access to DynamoDB ........................................ 755
DAX Encryption at Rest ........................................................................................................... 757
Enabling Encryption at Rest Using the AWS Management Console ........................................ 758
Using Service-Linked Roles for DAX .......................................................................................... 758
Service-Linked Role Permissions for DAX ........................................................................... 759
Creating a Service-Linked Role for DAX ............................................................................. 760
Editing a Service-Linked Role for DAX ............................................................................... 760
Deleting a Service-Linked Role for DAX ............................................................................. 760
Accessing DAX Across AWS Accounts ......................................................................................... 761
Set Up IAM .................................................................................................................... 762
Set Up a VPC ................................................................................................................. 763
Modify the DAX Client to Allow Cross-account Access .......................................................... 765
DAX Cluster Sizing Guide ......................................................................................................... 768
Overview ....................................................................................................................... 768
Estimating Traffic ........................................................................................................... 769
Load Testing .................................................................................................................. 769
API Reference ......................................................................................................................... 770
NoSQL Workbench .......................................................................................................................... 771
Download .............................................................................................................................. 771
Data Modeler ......................................................................................................................... 772
Creating a New Model ..................................................................................................... 772
Importing an Existing Model ............................................................................................ 776
Exporting a Model .......................................................................................................... 777
Editing an Existing Model ................................................................................................ 778

API Version 2012-08-10


viii
Amazon DynamoDB Developer Guide

Data Visualizer ....................................................................................................................... 781


Adding Sample Data ....................................................................................................... 781
Facets ........................................................................................................................... 782
Aggregate View .............................................................................................................. 783
Committing a Data Model ............................................................................................... 784
Operation Builder ................................................................................................................... 787
Exploring Datasets .......................................................................................................... 787
Building Operations ........................................................................................................ 791
Release History ...................................................................................................................... 800
Contributor Insights ........................................................................................................................ 801
How It Works ......................................................................................................................... 801
CloudWatch Contributor Insights for DynamoDB Rules ........................................................ 801
Understanding CloudWatch Contributor Insights for DynamoDB Graphs ................................. 802
Interactions with Other DynamoDB Features ...................................................................... 804
CloudWatch Contributor Insights for DynamoDB Billing ....................................................... 805
Getting Started ...................................................................................................................... 805
Using Contributor Insights (Console) ................................................................................. 806
Using Contributor Insights (AWS CLI) ................................................................................ 807
Using IAM .............................................................................................................................. 808
.................................................................................................................................... 808
Example: Enable or Disable CloudWatch Contributor Insights for DynamoDB .......................... 808
Example: Retrieve CloudWatch Contributor Insights Rule Report ........................................... 809
Example: Selectively Apply CloudWatch Contributor Insights for DynamoDB Permissions Based
on Resource ................................................................................................................... 809
Using Service-Linked Roles .............................................................................................. 810
Security ......................................................................................................................................... 812
Data Protection ...................................................................................................................... 812
Encryption at Rest .......................................................................................................... 813
Data Protection in DAX ................................................................................................... 822
Internetwork Traffic Privacy ............................................................................................. 822
Identity and Access Management .............................................................................................. 822
Identity and Access Management ...................................................................................... 823
Identity and Access Management in DAX ........................................................................... 854
Logging and Monitoring .......................................................................................................... 854
Logging and Monitoring in DynamoDB .............................................................................. 854
Logging and Monitoring in DAX ....................................................................................... 884
Compliance Validation ............................................................................................................. 884
Resilience .............................................................................................................................. 885
Infrastructure Security ............................................................................................................. 885
Using VPC Endpoints ...................................................................................................... 886
Configuration and Vulnerability Analysis .................................................................................... 892
Security Best Practices ............................................................................................................ 892
Preventative Security Best Practices .................................................................................. 892
Detective Security Best Practices ...................................................................................... 894
Best Practices ................................................................................................................................. 896
NoSQL Design ........................................................................................................................ 897
NoSQL vs. RDBMS .......................................................................................................... 897
Two Key Concepts .......................................................................................................... 898
General Approach ........................................................................................................... 898
Partition Key Design ............................................................................................................... 899
Burst Capacity ................................................................................................................ 899
Adaptive Capacity ........................................................................................................... 899
Distributing Workloads .................................................................................................... 901
Write Sharding ............................................................................................................... 902
Uploading Data Efficiently ............................................................................................... 903
Sort Key Design ..................................................................................................................... 904
Version Control .............................................................................................................. 904

API Version 2012-08-10


ix
Amazon DynamoDB Developer Guide

Secondary Indexes .................................................................................................................. 905


General Guidelines .......................................................................................................... 906
Sparse Indexes ............................................................................................................... 907
Aggregation ................................................................................................................... 909
GSI Overloading ............................................................................................................. 909
GSI Sharding .................................................................................................................. 910
Creating a Replica ........................................................................................................... 911
Large Items ........................................................................................................................... 912
Compression .................................................................................................................. 912
Using Amazon S3 ........................................................................................................... 912
Time Series Data .................................................................................................................... 913
Design Pattern for Time Series Data ................................................................................. 913
Time Series Table Examples ............................................................................................. 913
Many-to-Many Relationships .................................................................................................... 914
Adjacency Lists ............................................................................................................... 914
Materialized Graphs ........................................................................................................ 915
Hybrid DynamoDB–RDBMS ...................................................................................................... 918
Not Migrating ................................................................................................................ 918
Hybrid System Implementation ........................................................................................ 919
Relational Modeling ................................................................................................................ 919
First Steps ..................................................................................................................... 921
Example ........................................................................................................................ 923
Querying and Scanning ........................................................................................................... 924
Scan Performance ........................................................................................................... 924
Avoid Spikes .................................................................................................................. 925
Parallel Scans ................................................................................................................. 927
Global Tables ......................................................................................................................... 928
Integrating with Other AWS Services ................................................................................................ 929
Integrating with Amazon Cognito ............................................................................................. 929
Integrating with Amazon Redshift ............................................................................................ 931
Integrating with Amazon EMR .................................................................................................. 932
Overview ....................................................................................................................... 932
Tutorial: Working with Amazon DynamoDB and Apache Hive ................................................ 933
Creating an External Table in Hive .................................................................................... 939
Processing HiveQL Statements ......................................................................................... 941
Querying Data in DynamoDB ........................................................................................... 942
Copying Data to and from Amazon DynamoDB .................................................................. 944
Performance Tuning ........................................................................................................ 955
Limits ............................................................................................................................................ 959
Read/Write Capacity Mode and Throughput ............................................................................... 959
Capacity Unit Sizes (for Provisioned Tables) ....................................................................... 959
Request Unit Sizes (for On-Demand Tables) ....................................................................... 959
Throughput Default Limits ............................................................................................... 960
Increasing or Decreasing Throughput (for Provisioned Tables) ............................................... 960
Tables ................................................................................................................................... 961
Table Size ...................................................................................................................... 961
Tables Per Account ......................................................................................................... 961
Global Tables ......................................................................................................................... 961
Secondary Indexes .................................................................................................................. 962
Secondary Indexes Per Table ............................................................................................ 962
Projected Secondary Index Attributes Per Table .................................................................. 962
Partition Keys and Sort Keys .................................................................................................... 962
Partition Key Length ....................................................................................................... 962
Partition Key Values ........................................................................................................ 962
Sort Key Length ............................................................................................................. 962
Sort Key Values .............................................................................................................. 962
Naming Rules ......................................................................................................................... 963

API Version 2012-08-10


x
Amazon DynamoDB Developer Guide

Table Names and Secondary Index Names ......................................................................... 963


Attribute Names ............................................................................................................. 963
Data Types ............................................................................................................................ 963
String ............................................................................................................................ 963
Number ......................................................................................................................... 963
Binary ........................................................................................................................... 964
Items .................................................................................................................................... 964
Item Size ....................................................................................................................... 964
Item Size for Tables with Local Secondary Indexes .............................................................. 964
Attributes .............................................................................................................................. 964
Attribute Name-Value Pairs Per Item ................................................................................. 964
Number of Values in List, Map, or Set ............................................................................... 964
Attribute Values ............................................................................................................. 964
Nested Attribute Depth ................................................................................................... 965
Expression Parameters ............................................................................................................ 965
Lengths ......................................................................................................................... 965
Operators and Operands ................................................................................................. 965
Reserved Words .............................................................................................................. 965
DynamoDB Transactions .......................................................................................................... 965
DynamoDB Streams ................................................................................................................ 966
Simultaneous Readers of a Shard in DynamoDB Streams ..................................................... 966
Maximum Write Capacity for a Table with a Stream Enabled ................................................ 966
DynamoDB Accelerator (DAX) ................................................................................................... 966
AWS Region Availability .................................................................................................. 966
Nodes ........................................................................................................................... 966
Parameter Groups ........................................................................................................... 966
Subnet Groups ............................................................................................................... 967
API-Specific Limits .................................................................................................................. 967
DynamoDB Encryption at Rest ................................................................................................. 968
API Reference ................................................................................................................................. 969
Appendix ....................................................................................................................................... 970
Troubleshooting SSL/TLS connection establishment issues ........................................................... 970
Testing your application or service .................................................................................... 970
Testing your client browser .............................................................................................. 971
Updating your software application client ......................................................................... 971
Updating your client browser ........................................................................................... 971
Manually updating your certificate bundle ......................................................................... 971
Example Tables and Data ........................................................................................................ 972
Sample Data Files ........................................................................................................... 972
Creating Example Tables and Uploading Data ............................................................................ 981
Creating Example Tables and Uploading Data - Java ........................................................... 981
Creating Example Tables and Uploading Data - .NET ........................................................... 988
Example Application Using AWS SDK for Python (Boto3) ............................................................. 997
Step 1: Deploy and Test Locally ....................................................................................... 997
Step 2: Examine the Data Model and Implementation Details ............................................. 1001
Step 3: Deploy in Production ......................................................................................... 1009
Step 4: Clean Up Resources ............................................................................................ 1015
Integrating with Amazon Data Pipeline ................................................................................... 1016
Prerequisites to Export and Import Data .......................................................................... 1018
Exporting Data From DynamoDB to Amazon S3 ................................................................ 1021
Importing Data From Amazon S3 to DynamoDB ............................................................... 1022
Troubleshooting ............................................................................................................ 1023
Predefined Templates for AWS Data Pipeline and DynamoDB ............................................. 1024
Amazon DynamoDB Storage Backend for Titan ......................................................................... 1024
Reserved Words in DynamoDB ............................................................................................... 1025
Legacy Conditional Parameters ............................................................................................... 1034
AttributesToGet ............................................................................................................ 1035

API Version 2012-08-10


xi
Amazon DynamoDB Developer Guide

AttributeUpdates .......................................................................................................... 1035


ConditionalOperator ...................................................................................................... 1037
Expected ...................................................................................................................... 1037
KeyConditions .............................................................................................................. 1040
QueryFilter ................................................................................................................... 1042
ScanFilter ..................................................................................................................... 1044
Writing Conditions With Legacy Parameters ..................................................................... 1045
Previous Low-Level API Version (2011-12-05) ........................................................................... 1050
BatchGetItem ............................................................................................................... 1051
BatchWriteItem ............................................................................................................. 1056
CreateTable .................................................................................................................. 1060
DeleteItem ................................................................................................................... 1065
DeleteTable .................................................................................................................. 1069
DescribeTables .............................................................................................................. 1072
GetItem ....................................................................................................................... 1075
ListTables ..................................................................................................................... 1077
PutItem ....................................................................................................................... 1079
Query .......................................................................................................................... 1084
Scan ............................................................................................................................ 1093
UpdateItem .................................................................................................................. 1103
UpdateTable ................................................................................................................. 1109
Document History ......................................................................................................................... 1113
Earlier Updates ..................................................................................................................... 1115

API Version 2012-08-10


xii
Amazon DynamoDB Developer Guide
High Availability and Durability

What Is Amazon DynamoDB?


Welcome to the Amazon DynamoDB Developer Guide.

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

High Availability and Durability


DynamoDB automatically spreads the data and traffic for your tables over a sufficient number of
servers to handle your throughput and storage requirements, while maintaining consistent and fast
performance. All of your data is stored on solid-state disks (SSDs) and is automatically replicated across
multiple Availability Zones in an AWS Region, providing built-in high availability and data durability. You
can use global tables to keep DynamoDB tables in sync across AWS Regions. For more information, see
Global Tables: Multi-Region Replication with DynamoDB (p. 626).

Getting Started with DynamoDB


We recommend that you begin by reading the following sections:

• 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.

API Version 2012-08-10


1
Amazon DynamoDB Developer Guide
How It Works

To get started quickly with DynamoDB, see Getting Started with DynamoDB and AWS SDKs (p. 76).

To learn more about application development, see the following:

• Programming with DynamoDB and the AWS SDKs (p. 214)


• Working with Tables, Items, Queries, Scans, and Indexes (p. 336)

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.

Amazon DynamoDB: How It Works


The following sections provide an overview of Amazon DynamoDB service components and how they
interact.

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)

Core Components of Amazon DynamoDB


In DynamoDB, tables, items, and attributes are the core components that you work with. A table is a
collection of items, and each item is a collection of attributes. DynamoDB uses primary keys to uniquely
identify each item in a table and secondary indexes to provide more querying flexibility. You can use
DynamoDB Streams to capture data modification events in DynamoDB tables.

There are limits in DynamoDB. For more information, see Service, Account, and Table Limits in Amazon
DynamoDB (p. 959).

API Version 2012-08-10


2
Amazon DynamoDB Developer Guide
Core Components

Topics
• Tables, Items, and Attributes (p. 3)
• Primary Key (p. 6)
• Secondary Indexes (p. 7)
• DynamoDB Streams (p. 9)

Tables, Items, and Attributes


The following are the basic DynamoDB components:

• 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.

API Version 2012-08-10


3
Amazon DynamoDB Developer Guide
Core Components

Note the following about the People table:

• 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.

API Version 2012-08-10


4
Amazon DynamoDB Developer Guide
Core Components

• 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.

Note the following about the Music table:

• 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.

API Version 2012-08-10


5
Amazon DynamoDB Developer Guide
Core Components

• 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.

DynamoDB supports two different kinds of primary keys:

• 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.

DynamoDB supports two kinds of indexes:

• 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.

API Version 2012-08-10


7
Amazon DynamoDB Developer Guide
Core Components

Note the following about the GenreAlbumTitle index:

• 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.

API Version 2012-08-10


8
Amazon DynamoDB Developer Guide
Core Components

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.

API Version 2012-08-10


9
Amazon DynamoDB Developer Guide
DynamoDB API

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.

API Version 2012-08-10


10
Amazon DynamoDB Developer Guide
DynamoDB API

• 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.

API Version 2012-08-10


11
Amazon DynamoDB Developer Guide
Naming Rules and Data Types

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.

Naming Rules and Data Types


This section describes the Amazon DynamoDB naming rules and the various data types that DynamoDB
supports. There are limits that apply to data types. For more information, see Data Types (p. 963).

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.

The following are the naming rules for DynamoDB:

• All names must be encoded using UTF-8, and are case-sensitive.


• Table names and index names must be between 3 and 255 characters long, and can contain only the
following characters:
• a-z
• A-Z
• 0-9
• _ (underscore)
• - (dash)
• . (dot)
• Attribute names must be between 1 and 255 characters long.
API Version 2012-08-10
12
Amazon DynamoDB Developer Guide
Naming Rules and Data Types

Reserved Words and Special Characters


DynamoDB has a list of reserved words and special characters. For a complete list of reserved words in
DynamoDB, see Reserved Words in DynamoDB (p. 1025). Also, the following characters have special
meaning in DynamoDB: # (hash) and : (colon).

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.

• Positive range: 1E-130 to 9.9999999999999999999999999999999999999E+125


• Negative range: -9.9999999999999999999999999999999999999E+125 to -1E-130

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.

API Version 2012-08-10


13
Amazon DynamoDB Developer Guide
Naming Rules and Data Types

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.

For more information, see http://en.wikipedia.org/wiki/Unix_time.

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

For more information, see http://en.wikipedia.org/wiki/ISO_8601.

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.

The following example is a binary attribute, using base64-encoded text.

dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk

API Version 2012-08-10


14
Amazon DynamoDB Developer Guide
Naming Rules and Data Types

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.

FavoriteThings: ["Cookies", "Coffee", 3.14159]

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}
}
]
}

API Version 2012-08-10


15
Amazon DynamoDB Developer Guide
Read Consistency

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:

["Black", "Green", "Red"]

[42.2, -19, 7.5, 3.14]

["U3Vubnk=", "UmFpbnk=", "U25vd3k="]

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.

DynamoDB supports eventually consistent and strongly consistent reads.

Eventually Consistent Reads

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.

Strongly Consistent Reads

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

API Version 2012-08-10


16
Amazon DynamoDB Developer Guide
Read/write Capacity Mode

• 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.

Read/Write Capacity Mode


Amazon DynamoDB has two read/write capacity modes for processing reads and writes on your tables:

• 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.

On-demand mode is a good option if any of the following are true:

• You create new tables with unknown workloads.


• You have unpredictable application traffic.
• You prefer the ease of paying for only what you use.

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

API Version 2012-08-10


17
Amazon DynamoDB Developer Guide
Read/write Capacity Mode

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)

Read Request Units and Write Request Units


For on-demand mode tables, you don't need to specify how much read and write throughput you expect
your application to perform. DynamoDB charges you for the reads and writes that your application
performs on your tables in terms of read request units and write request units.

• 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.

Peak Traffic and Scaling Properties


DynamoDB tables using on-demand capacity mode automatically adapt to your application’s traffic
volume. On-demand capacity mode instantly accommodates up to double the previous peak traffic on
a table. 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 previous traffic peak, on-demand
capacity mode instantly accommodates sustained traffic of up to 100,000 reads per second. If your
application sustains traffic of 100,000 reads per second, that peak becomes your new previous peak,
enabling subsequent traffic to reach up to 200,000 reads per second.

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.

API Version 2012-08-10


18
Amazon DynamoDB Developer Guide
Read/write Capacity Mode

Initial Throughput for On-Demand Capacity Mode


If you recently switched an existing table to on-demand capacity mode for the first time, or if you
created a new table with on-demand capacity mode enabled, the table has the following previous peak
settings, even though the table has not served traffic previously using on-demand capacity mode:

• 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.

Table Behavior while Switching Read/Write Capacity Mode


When you switch a table from provisioned capacity mode to on-demand capacity mode, DynamoDB
makes several changes to the structure of your table and partitions. This process can take several
minutes. During the switching period, your table delivers throughput that is consistent with the
previously provisioned write capacity unit and read capacity unit amounts. When switching from on-
demand capacity mode back to provisioned capacity mode, your table delivers throughput consistent
with the previous peak reached when the table was set 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.

Provisioned mode is a good option if any of the following are true:

• You have predictable application traffic.


• You run applications whose traffic is consistent or ramps gradually.
• You can forecast capacity requirements to control costs.

Read Capacity Units and Write Capacity Units


For provisioned mode tables, you specify throughput capacity in terms of read capacity units (RCUs) and
write capacity units (WCUs):

• 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.

API Version 2012-08-10


19
Amazon DynamoDB Developer Guide
Read/write Capacity Mode

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:

• Perform strongly consistent reads of up to 24 KB per second (4 KB × 6 read capacity units).


• Perform eventually consistent reads of up to 48 KB per second (twice as much read throughput).
• Perform transactional read requests of up to 12 KB per second.
• Write up to 6 KB per second (1 KB × 6 write capacity units).
• Perform transactional write requests of up to 3 KB per second.

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.

DynamoDB Auto Scaling


DynamoDB auto scaling actively manages throughput capacity for tables and global secondary indexes.
With auto scaling, you define a range (upper and lower limits) for read and write capacity units. You also
define a target utilization percentage within that range. DynamoDB auto scaling seeks to maintain your
target utilization, even as your application workload increases or decreases.

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

API Version 2012-08-10


20
Amazon DynamoDB Developer Guide
Partitions and Data Distribution

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

Partitions and Data Distribution


Amazon DynamoDB stores data in partitions. A partition is an allocation of storage for a table, backed by
solid state drives (SSDs) and automatically replicated across multiple Availability Zones within an AWS
Region. Partition management is handled entirely by DynamoDB—you never have to manage partitions
yourself.

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.

DynamoDB allocates additional partitions to a table in the following situations:

• 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.

For more details, see Partition Key Design (p. 899).

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.

Data Distribution: Partition Key


If your table has a simple primary key (partition key only), DynamoDB stores and retrieves each item
based on its partition key value.

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.

API Version 2012-08-10


21
Amazon DynamoDB Developer Guide
Partitions and Data Distribution

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.

Data Distribution: Partition Key and Sort Key


If the table has a composite primary key (partition key and sort key), DynamoDB calculates the hash
value of the partition key in the same way as described in Data Distribution: Partition Key (p. 21).
However, it stores all the items with the same partition key value physically close together, ordered by
sort key value.

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.

API Version 2012-08-10


22
Amazon DynamoDB Developer Guide
From SQL to NoSQL

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.

From SQL to NoSQL


If you are an application developer, you might have some experience using a relational database
management system (RDBMS) and Structured Query Language (SQL). As you begin working with
Amazon DynamoDB, you will encounter many similarities, but also many things that are different.
This section describes common database tasks, comparing and contrasting SQL statements with their
equivalent DynamoDB operations.

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)

API Version 2012-08-10


23
Amazon DynamoDB Developer Guide
Relational or NoSQL?

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)

Relational (SQL) or NoSQL?


Today's applications have more demanding requirements than ever before. For example, an online game
might start out with just a few users and a very small amount of data. However, if the game becomes
successful, it can easily outstrip the resources of the underlying database management system. It is
common for web-based applications to have hundreds, thousands, or millions of concurrent users, with
terabytes or more of new data generated per day. Databases for such applications must handle tens (or
hundreds) of thousands of reads and writes per second.

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.

Characteristic Relational Database Amazon DynamoDB


Management System (RDBMS)

Optimal Workloads Ad hoc queries; data Web-scale applications,


warehousing; OLAP (online including social networks,
analytical processing). gaming, media sharing, and
Internet of Things (IoT).

Data Model The relational model requires DynamoDB is schemaless. Every


a well-defined schema, where table must have a primary
data is normalized into tables, key to uniquely identify each
rows, and columns. In addition, data item, but there are no
all of the relationships are similar constraints on other
defined among tables, columns, non-key attributes. DynamoDB
indexes, and other database can manage structured or
elements. semistructured data, including
JSON documents.

API Version 2012-08-10


24
Amazon DynamoDB Developer Guide
Characteristics of Databases

Characteristic Relational Database Amazon DynamoDB


Management System (RDBMS)

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.

Performance Relational databases are DynamoDB is optimized for


optimized for storage, so compute, so performance
performance generally is mainly a function of the
depends on the disk subsystem. underlying hardware and
Developers and database network latency. As a managed
administrators must optimize service, DynamoDB insulates
queries, indexes, and table you and your applications from
structures in order to achieve these implementation details, so
peak performance. that you can focus on designing
and building robust, high-
performance applications.

Scaling It is easiest to scale up with DynamoDB is designed to scale


faster hardware. It is also out using distributed clusters
possible for database tables to of hardware. This design allows
span across multiple hosts in increased throughput without
a distributed system, but this increased latency. Customers
requires additional investment. specify their throughput
Relational databases have requirements, and DynamoDB
maximum sizes for the number allocates sufficient resources
and size of files, which imposes to meet those requirements.
upper limits on scalability. There are no upper limits on the
number of items per table, nor
the total size of that table.

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.

API Version 2012-08-10


25
Amazon DynamoDB Developer Guide
Characteristics of Databases

The following table has more details about client interaction tasks.

Characteristic Relational Database Amazon DynamoDB


Management System (RDBMS)

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.

Connecting to the Database An application program DynamoDB is a web service, and


establishes and maintains a interactions with it are stateless.
network connection with the Applications do not need to
database. When the application maintain persistent network
is finished, it terminates the connections. Instead, interaction
connection. with DynamoDB occurs using
HTTP(S) requests and responses.

Authentication An application cannot connect Every request to DynamoDB


to the database until it is must be accompanied by a
authenticated. The RDBMS can cryptographic signature, which
perform the authentication authenticates that particular
itself, or it can offload this task request. The AWS SDKs provide
to the host operating system or all of the logic necessary for
a directory service. creating signatures and signing
requests. For more information,

API Version 2012-08-10


26
Amazon DynamoDB Developer Guide
Creating a Table

Characteristic Relational Database Amazon DynamoDB


Management System (RDBMS)
see Signing AWS API Requests in
the AWS General Reference.

Authorization Applications can perform only In DynamoDB, authorization is


the actions for which they have handled by AWS Identity and
been authorized. Database Access Management (IAM). You
administrators or application can write an IAM policy to grant
owners can use the SQL GRANT permissions on a DynamoDB
and REVOKE statements to resource (such as a table), and
control access to database then allow IAM users and roles
objects (such as tables), data to use that policy. IAM also
(such as rows within a table), or features fine-grained access
the ability to issue certain SQL control for individual data items
statements. in DynamoDB tables. For more
information, see Identity and
Access Management in Amazon
DynamoDB (p. 823).

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.

CREATE TABLE Music (


Artist VARCHAR(20) NOT NULL,
SongTitle VARCHAR(30) NOT NULL,
AlbumTitle VARCHAR(25),

API Version 2012-08-10


27
Amazon DynamoDB Developer Guide
Creating a Table

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

You must provide the following parameters to CreateTable:

• TableName – Name of the table.


• KeySchema – Attributes that are used for the primary key. For more information, see Tables, Items,
and Attributes (p. 3) and Primary Key (p. 6).
• AttributeDefinitions – Data types for the key schema attributes.
• ProvisionedThroughput (for provisioned tables) – Number of reads and writes per second
that you need for this table. DynamoDB reserves sufficient storage and system resources so that your
throughput requirements are always met. You can use the UpdateTable action to change these later,

API Version 2012-08-10


28
Amazon DynamoDB Developer Guide
Getting Information About a Table

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

Getting Information About a Table


You can verify that a table has been created according to your specifications. In a relational database,
all of the table's schema is shown. Amazon DynamoDB tables are schemaless, so only the primary key
attributes are shown.

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"
}

The reply from DescribeTable looks like the following.

{
"Table": {
"AttributeDefinitions": [
{

API Version 2012-08-10


29
Amazon DynamoDB Developer Guide
Writing Data to a Table

"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.

Writing Data to a Table


Relational database tables contain rows of data. Rows are composed of columns. Amazon DynamoDB
tables contain items. Items are composed of attributes.

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.

In SQL, you use the INSERT statement to add a row to a table.

INSERT INTO Music


(Artist, SongTitle, AlbumTitle,
Year, Price, Genre,
Tags)
VALUES(
'No One You Know', 'Call Me Today', 'Somewhat Famous',
2015, 2.14, 'Country',
'{"Composers": ["Smith", "Jones", "Davis"],"LengthInSeconds": 214}'
);

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.

API Version 2012-08-10


30
Amazon DynamoDB Developer Guide
Writing Data to a Table

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

The following are some other PutItem examples.

{
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",

API Version 2012-08-10


31
Amazon DynamoDB Developer Guide
Reading Data from a Table

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.

Key Differences When Reading Data from a Table


With SQL, you use the SELECT statement to retrieve one or more rows from a table. You use the WHERE
clause to determine the data that is returned to you.

Amazon DynamoDB provides the following operations for reading data:

• 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).)

API Version 2012-08-10


32
Amazon DynamoDB Developer Guide
Reading Data from a Table

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

Reading an Item Using Its Primary Key


One common access pattern for databases is to read a single item from a table. You have to specify the
primary key of the item you want.

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.

SELECT AlbumTitle, Year, Price


FROM Music
WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today'

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

API Version 2012-08-10


33
Amazon DynamoDB Developer Guide
Reading Data from a Table

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 a single song, by primary key */

API Version 2012-08-10


34
Amazon DynamoDB Developer Guide
Reading Data from a Table

SELECT * FROM Music


WHERE Artist='No One You Know' AND SongTitle = 'Call Me Today';

/* Return all of the songs by an artist */

SELECT * FROM Music


WHERE Artist='No One You Know';

/* Return all of the songs by an artist, matching first part of title */

SELECT * FROM Music


WHERE Artist='No One You Know' AND SongTitle LIKE 'Call%';

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

SELECT * FROM Music


WHERE Artist='No One You Know' AND SongTitle LIKE '%Today%'
AND Price < 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.

In DynamoDB, you must use ExpressionAttributeValues as placeholders in expression parameters


(such as KeyConditionExpression and FilterExpression). This is analogous to the use of bind
variables in relational databases, where you substitute the actual values into the SELECT statement at
runtime.

Note that the primary key for this table consists of Artist and SongTitle.

The following are some DynamoDB Query examples.

// Return a single song, by primary key

{
TableName: "Music",
KeyConditionExpression: "Artist = :a and SongTitle = :t",
ExpressionAttributeValues: {
":a": "No One You Know",
":t": "Call Me Today"
}
}

// Return all of the songs by an artist

API Version 2012-08-10


35
Amazon DynamoDB Developer Guide
Reading Data from a Table

{
TableName: "Music",
KeyConditionExpression: "Artist = :a",
ExpressionAttributeValues: {
":a": "No One You Know"
}
}

// Return all of the songs by an artist, matching first part of title

{
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 (*).

The following are examples of using a SELECT statement.

/* Return all of the data in the table */


SELECT * FROM Music;

/* Return all of the values for Artist and Title */


SELECT Artist, Title FROM Music;

DynamoDB
DynamoDB provides a Scan action that works in a similar way. The following are some examples.

API Version 2012-08-10


36
Amazon DynamoDB Developer Guide
Managing Indexes

// Return all of the data in the table


{
TableName: "Music"
}

// Return all of the values for Artist and Title


{
TableName: "Music",
ProjectionExpression: "Artist, Title"
}

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.

In MySQL, you can create an index like the following.

API Version 2012-08-10


37
Amazon DynamoDB Developer Guide
Managing Indexes

CREATE INDEX GenreAndPriceIndex


ON Music (genre, price);

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.

DynamoDB supports two different kinds of indexes:

• 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
}
}
}
]
}

You must provide the following parameters to UpdateTable:

• TableName – The table that the index will be associated with.


• AttributeDefinitions – The data types for the key schema attributes of the index.
• GlobalSecondaryIndexUpdates – Details about the index you want to create:
• IndexName – A name for the index.
• KeySchema – The attributes that are used for the index's primary key.

API Version 2012-08-10


38
Amazon DynamoDB Developer Guide
Managing Indexes

• 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).

Querying and Scanning an Index


Compare querying and scanning an index using the SELECT statement in SQL with the Query and Scan
operations in Amazon DynamoDB.

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.

/* All of the rock songs */

SELECT * FROM Music


WHERE Genre = 'Rock';

/* All of the cheap country songs */

SELECT Artist, SongTitle, Price FROM Music


WHERE Genre = 'Country' AND Price < 0.50;

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

API Version 2012-08-10


39
Amazon DynamoDB Developer Guide
Modifying Data in a Table

// All of the rock songs

{
TableName: "Music",
IndexName: "GenreAndPriceIndex",
KeyConditionExpression: "Genre = :genre",
ExpressionAttributeValues: {
":genre": "Rock"
},
};

// All of the cheap country songs

{
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.

// Return all of the data in the index

{
TableName: "Music",
IndexName: "GenreAndPriceIndex"
}

Modifying Data in a Table


The SQL language provides the UPDATE statement for modifying data. Amazon DynamoDB uses the
UpdateItem operation to accomplish similar tasks.

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';

API Version 2012-08-10


40
Amazon DynamoDB Developer Guide
Modifying Data in a Table

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

The following is an example.

{
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
},

API Version 2012-08-10


41
Amazon DynamoDB Developer Guide
Deleting Data from a Table

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

Deleting Data from a Table


In SQL, the DELETE statement removes one or more rows from a table. Amazon DynamoDB uses the
DeleteItem operation to delete one item at a time.

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.

DELETE FROM Music


WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';

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.

DELETE FROM Music WHERE Artist = 'The Acme Band'

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.

API Version 2012-08-10


42
Amazon DynamoDB Developer Guide
Removing a Table

{
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.

DROP TABLE Music;

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"

API Version 2012-08-10


43
Amazon DynamoDB Developer Guide
Additional Amazon DynamoDB Resources

Note
For code examples that use DeleteTable, see Getting Started with DynamoDB and AWS
SDKs (p. 76).

Additional Amazon DynamoDB Resources


Topics
• Blog Posts, Repositories, and Guides (p. 44)
• Data Modeling and Design Patterns (p. 44)
• Advanced Design Patterns with Rick Houlihan (p. 44)
• Training Courses (p. 44)
• Tools for Coding and Visualization (p. 45)

Blog Posts, Repositories, and Guides


• How to switch from RDBMS to DynamoDB in 20 easy steps — An irreverent list from Jeremy Daly of
useful steps for learning data modeling.
• DynamoDB JavaScript DocumentClient cheat sheet — A cheat sheet to help you get started building
applications with DynamoDB in a Node.js or JavaScript environment.
• From relational database to single DynamoDB table: A step-by-step exploration — An in-depth post
from Forrest Brazeal that includes a step-by-step approach for moving to a DynamoDB-style, one-
table design.

Data Modeling and Design Patterns


• AWS re:Invent 2019: Data modeling with DynamoDB — A talk by Alex DeBrie that gets you started on
the principles of DynamoDB data modeling.

Advanced Design Patterns with Rick Houlihan


• AWS re:Invent 2019: Advanced design patterns
• Jeremy Daly shares his 12 key takeaways from this session.
• AWS re:Invent 2018: Advanced design patterns
• AWS re:Invent 2017: Advanced design patterns

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.

API Version 2012-08-10


44
Amazon DynamoDB Developer Guide
Tools for Coding and Visualization

• AWS DynamoDB — From Beginner to Pro — A course from A Cloud Guru.

Tools for Coding and Visualization


• NoSQL Workbench for Amazon DynamoDB — A unified, visual tool that provides data modeling,
data visualization, and query development features to help you design, create, query, and manage
DynamoDB tables.
• DynamoDB Toolbox — A project from Jeremy Daly that provides helpful utilities for working with data
modeling and in JavaScript and Node.js.
• Dynobase — A desktop tool that makes it easy to see and work with your DynamoDB tables, create
app code, and edit records with real-time validation.
• DynamoDB Streams Processor — A simple tool that makes working with DynamoDB Streams super
easy.

API Version 2012-08-10


45
Amazon DynamoDB Developer Guide
Setting Up DynamoDB Local (Downloadable Version)

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)

Setting Up DynamoDB Local (Downloadable


Version)
With the downloadable version of Amazon DynamoDB, you can develop and test applications without
accessing the DynamoDB web service. Instead, the database is self-contained on your computer. When
you're ready to deploy your application in production, you remove the local endpoint in the code, and
then it points to the DynamoDB web service.

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.

DynamoDB Local is available as a download (requires JRE), as an Apache Maven dependency, or as a


Docker image.

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)

Deploying DynamoDB Locally on Your Computer


The downloadable version of Amazon DynamoDB is provided as an executable .jar file. The application
runs on Windows, Linux, macOS, and other platforms that support Java.

Follow these steps to set up and run DynamoDB on your computer.

To set up DynamoDB on your computer

1. Download DynamoDB for free using one of the following links.

API Version 2012-08-10


46
Amazon DynamoDB Developer Guide
Deploying DynamoDB on Your Computer

Region Download Links Checksums

Asia Pacific (Mumbai) Region .tar.gz | .zip .tar.gz.sha256 | .zip.sha256

Asia Pacific (Singapore) Region .tar.gz | .zip .tar.gz.sha256 | .zip.sha256

Asia Pacific (Tokyo) Region .tar.gz | .zip .tar.gz.sha256 | .zip.sha256

Europe (Frankfurt) Region .tar.gz | .zip .tar.gz.sha256 | .zip.sha256

South America (São Paulo) .tar.gz | .zip .tar.gz.sha256 | .zip.sha256


Region

US West (Oregon) Region .tar.gz | .zip .tar.gz.sha256 | .zip.sha256

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.

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

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.

AWS Access Key ID: "fakeMyKeyId"


AWS Secret Access Key: "fakeSecretAccessKey"

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.

aws dynamodb list-tables --endpoint-url http://localhost:8000

API Version 2012-08-10


47
Amazon DynamoDB Developer Guide
Deploying as an Apache Maven Repository

Deploying DynamoDB by adding an Apache Maven


Repository
Follow these steps to use Amazon DynamoDB in your application as a dependency.

To deploy DynamoDB as an Apache Maven repository

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.

Install the DynamoDB Docker Image


The downloadable version of Amazon DynamoDB is available as a Docker image. For more information,
see dynamodb-local.

API Version 2012-08-10


48
Amazon DynamoDB Developer Guide
Usage Notes

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.

DynamoDB Usage Notes


Except for the endpoint, applications that run with the downloadable version of Amazon DynamoDB
should also work with the DynamoDB web service. However, when using DynamoDB locally, you should
be aware of the following:

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

Command Line Options


You can use the following command line options with the downloadable version of DynamoDB:

• -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.

API Version 2012-08-10


49
Amazon DynamoDB Developer Guide
Usage Notes

• -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.

Setting the Local Endpoint


By default, the AWS SDKs and tools use endpoints for the Amazon DynamoDB web service. To use the
SDKs and tools with the downloadable version of DynamoDB, you must specify the local endpoint:

http://localhost:8000

AWS Command Line Interface


You can use the AWS Command Line Interface (AWS CLI) to interact with downloadable DynamoDB. For
example, you can use it to perform all the steps in Creating Tables and Loading Data for Code Examples
in DynamoDB (p. 326).

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.

aws dynamodb list-tables --endpoint-url http://localhost:8000

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:

• Java: Setting the AWS Region and Endpoint (p. 333)


• .NET: Setting the AWS Region and Endpoint (p. 335)

Note
For examples in other programming languages, see Getting Started with DynamoDB and AWS
SDKs (p. 76).

Differences Between Downloadable DynamoDB and the


DynamoDB Web Service
The downloadable version of DynamoDB is intended for development and testing purposes only. By
comparison, the DynamoDB web service is a managed service with scalability, availability, and durability
features that make it ideal for production use.

The downloadable version of DynamoDB differs from the web service in the following ways:

API Version 2012-08-10


50
Amazon DynamoDB Developer Guide
Setting Up DynamoDB (Web Service)

• 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.

Setting Up DynamoDB (Web Service)


To use the Amazon DynamoDB web service:

1. Sign up for AWS. (p. 51)


2. Get an AWS access key (p. 52) (used to access DynamoDB programmatically).
Note
If you plan to interact with DynamoDB only through the AWS Management Console, you
don't need an AWS access key, and you can skip ahead to Using the Console (p. 54).
3. Configure your credentials (p. 53) (used to access DynamoDB programmatically).

Signing Up for AWS


To use the DynamoDB service, you must have an AWS account. If you don't already have an account, you
are prompted to create one when you sign up. You're not charged for any AWS services that you sign up
for unless you use them.

API Version 2012-08-10


51
Amazon DynamoDB Developer Guide
Getting an AWS Access Key

To sign up for AWS

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.

Getting an AWS Access Key


Before you can access DynamoDB programmatically or through the AWS Command Line Interface (AWS
CLI), you must have an AWS access key. You don't need an access key if you plan to use the DynamoDB
console only.

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.

To create access keys for an IAM user

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:

• Access key ID: AKIAIOSFODNN7EXAMPLE


• Secret access key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
6. To download the key pair, choose Download .csv file. Store the keys in a secure location. You will
not have access to the secret access key again after this dialog box closes.

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

• What Is IAM? in the IAM User Guide


• AWS Security Credentials in AWS General Reference

API Version 2012-08-10


52
Amazon DynamoDB Developer Guide
Configuring Your Credentials

Configuring Your Credentials


Before you can access DynamoDB programmatically or through the AWS CLI, you must configure your
credentials to enable authorization for your applications.

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

API Version 2012-08-10


53
Amazon DynamoDB Developer Guide
Using the Console

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)

Using the Console


You can access the AWS Management Console for Amazon DynamoDB at https://
console.aws.amazon.com/dynamodb/home.

You can use the console to do the following in DynamoDB:

• 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.

API Version 2012-08-10


54
Amazon DynamoDB Developer Guide
Working with User Preferences

• Access control – Set up fine-grained access control with web identity federation.
• Tags – Apply tags to your resources to help organize and identify them.

Working with User Preferences


You can configure some of the default settings in the Amazon DynamoDB console. For example, you
can change the default query type that is used when you access the Items tab. If you're signed in
to the console as an IAM user, you can store information about how you prefer to use the console.
This information, also known as your user preferences, is stored and applied every time you use the
console. Any time you access the DynamoDB console, these preferences are applied to all tables in all
AWS Regions for your IAM user. They are not table-specific or Region-specific. They don't affect your
interactions with the AWS CLI, DynamoDB API, or other services that interact with DynamoDB.

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.

User preferences include the following:

• 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.

View and Save User Preferences


You can view and change your user preferences for the DynamoDB console. These settings apply only to
your IAM user in the DynamoDB console. They don't affect other IAM users in your AWS account.

To view and save preferences on the DynamoDB console for your IAM user

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.

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.

Do one of the following:

• To save and apply your changes, choose Save.

API Version 2012-08-10


55
Amazon DynamoDB Developer Guide
Using the AWS CLI

• To view the DynamoDB console default settings, choose Restore. These defaults are applied if you
choose Save.

The default settings are as follows:


• Table detail view mode: Vertical
• Show navigation bar: Yes
• Default entry page: Dashboard
• Items editor mode: Tree
• Items default query type: Scan
• Automatic scan operation when accessing the items tab: Yes
• To return to the console page that you were on previously, choose Back. Or, choose Dashboard to
go to the DynamoDB Dashboard page.

Using the AWS CLI


You can use the AWS Command Line Interface (AWS CLI) to control multiple AWS services from the
command line and automate them through scripts. You can use the AWS CLI for ad hoc operations, such
as creating a table. You can also use it to embed Amazon DynamoDB operations within utility scripts.

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)

Downloading and Configuring the AWS CLI


The AWS CLI is available at http://aws.amazon.com/cli. It runs on Windows, macOS, or Linux. After you
download the AWS CLI, follow these steps to install and configure it:

1. Go to the AWS Command Line Interface User Guide.


2. Follow the instructions for Installing the AWS CLI and Configuring the AWS CLI.

Using the AWS CLI with DynamoDB


The command line format consists of a DynamoDB operation name followed by the parameters for that
operation. The AWS CLI supports a shorthand syntax for the parameter values, as well as JSON.

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

aws dynamodb create-table \


--table-name Music \
--attribute-definitions \

API Version 2012-08-10


56
Amazon DynamoDB Developer Guide
Using the AWS CLI with Downloadable DynamoDB

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.

aws dynamodb put-item \


--table-name Music \
--item \
'{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"},
"AlbumTitle": {"S": "Somewhat Famous"}}' \
--return-consumed-capacity TOTAL

aws dynamodb put-item \


--table-name Music \
--item '{ \
"Artist": {"S": "Acme Band"}, \
"SongTitle": {"S": "Happy Day"}, \
"AlbumTitle": {"S": "Songs About Life"} }' \
--return-consumed-capacity TOTAL

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.

aws dynamodb query --table-name Music --key-conditions file://key-conditions.json

Using the AWS CLI with Downloadable DynamoDB


The AWS CLI can also interact with DynamoDB (Downloadable Version) that runs on your computer. To
enable this, add the following parameter to each command:

--endpoint-url http://localhost:8000

The following example uses the AWS CLI to list the tables in a local database.

API Version 2012-08-10


57
Amazon DynamoDB Developer Guide
Using the API

aws dynamodb list-tables --endpoint-url http://localhost:8000

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.

Using the API


You can use the AWS Management Console and the AWS Command Line Interface to work interactively
with Amazon DynamoDB. However, to get the most out of DynamoDB, you can write application code
using the AWS SDKs.

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

Using the NoSQL Workbench for DynamoDB


You can also access DynamoDB, by downloading and using the NoSQL Workbench for Amazon
DynamoDB (p. 771).

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

API Version 2012-08-10


58
Amazon DynamoDB Developer Guide
Basic Concepts

Getting Started with DynamoDB


Use the hands-on tutorials in this section to help you get started and learn more about Amazon
DynamoDB.

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)

Basic Concepts in DynamoDB


Before you begin, you should familiarize yourself with the basic concepts in Amazon DynamoDB. For
more information, see DynamoDB Core Components.

Then continue on to Prerequisites to learn about setting up DynamoDB.

Prerequisites - Getting Started Tutorial


Before starting the Amazon DynamoDB tutorial, follow the steps in Setting Up DynamoDB. Then
continue on to Step 1: Create a Table (p. 59).
Note

• 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).

Step 1: Create a Table


In this step, you create a Music table in Amazon DynamoDB. The table has the following details:

• Partition key — Artist


• Sort key — SongTitle

API Version 2012-08-10


59
Amazon DynamoDB Developer Guide
Step 1: Create a Table

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

AWS Management Console


To create a new Music table using the DynamoDB console:

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.

4. Enter the table details as follows:

a. For the table name, enter Music.


b. For the partition key, enter Artist.
c. Choose Add sort key.
d. Enter SongTitle as the sort key.
5. Choose Create to create the table.

API Version 2012-08-10


60
Amazon DynamoDB Developer Guide
Step 1: Create a Table

AWS CLI
The following AWS CLI example creates a new Music table using create-table.

aws dynamodb create-table \


--table-name Music \
--attribute-definitions \
AttributeName=Artist,AttributeType=S \
AttributeName=SongTitle,AttributeType=S \
--key-schema \
AttributeName=Artist,KeyType=HASH \
AttributeName=SongTitle,KeyType=RANGE \
--provisioned-throughput \
ReadCapacityUnits=10,WriteCapacityUnits=5

Using create-table returns the following sample result.

{
"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
}
}

Note that the value of the TableStatus field is set to CREATING.

To verify that DynamoDB has finished creating the Music table, use the describe-table command.

aws dynamodb describe-table --table-name Music | grep TableStatus

API Version 2012-08-10


61
Amazon DynamoDB Developer Guide
Step 2: Write Data

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

Step 2: Write Data to a Table Using the Console or


AWS CLI
In this step, you insert two items into the Music table that you created in Step 1: Create a
Table (p. 59).

For more information about write operations, see Writing an Item (p. 376).

AWS Management Console


Follow these steps to write data to the Music table using the DynamoDB console.

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. In the table list, choose the Music table.
4. Choose the Items tab for the Music table.
5. On the Items tab, choose Create item.

6. Choose the plus sign (+) symbol next to SongTitle.


7. Choose Append, and then choose Number. Name the field Awards.

API Version 2012-08-10


62
Amazon DynamoDB Developer Guide
Step 2: Write Data

8. Repeat this process to create an AlbumTitle of type String.


9. Choose the following values for your item:

a. For Artist, enter No One You Know as the value.


b. For SongTitle, enter Call Me Today.
c. For AlbumTitle, enter Somewhat Famous.
d. For Awards, enter 1.
10. Choose Save.

11. Repeat this process and create another item with the following values:

a. For Artist, enter Acme Band.

API Version 2012-08-10


63
Amazon DynamoDB Developer Guide
Step 3: Read Data

b. For SongTitle enter Happy Day.


c. For AlbumTitle, enter Songs About Life.
d. For Awards, enter 10.

AWS CLI
The following AWS CLI example creates two new items in the Music table using put-item.

aws dynamodb put-item \


--table-name Music \
--item \
'{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"},
"AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}}'

aws dynamodb put-item \


--table-name Music \
--item \
'{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S":
"Songs About Life"}, "Awards": {"N": "10"} }'

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

Step 3: Read Data from a Table


In this step, you will read back an item that was created in Step 2: Write Data to a Table Using the
Console or AWS CLI (p. 62). You can use the DynamoDB console or the AWS CLI to read an item from
the Music table by specifying Artist and SongTitle.

For more information about read operations in DynamoDB, see Reading an Item (p. 376).

AWS Management Console


Follow these steps to read data from the Music table using the DynamoDB console.

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. Choose the Music table from the table list.
4. Choose the Items tab for the Music table.
5. On the Items tab, view the list of items stored in the table, sorted by Artist and SongTitle.

The first item in the list is the one with the Artist Acme Band and the SongTitle Happy Day.

API Version 2012-08-10


64
Amazon DynamoDB Developer Guide
Step 4: Update Data

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.

aws dynamodb get-item --consistent-read \


--table-name Music \
--key '{ "Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}}'

Using get-item returns the following sample result.

{
"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).

Step 4: Update Data in a Table


In this step, you update an item that you created in Step 2: Write Data to a Table Using the Console or
AWS CLI (p. 62). You can use the DynamoDB console or the AWS CLI to update the AlbumTitle of an
item in the Music table by specifying Artist, SongTitle, and the updated AlbumTitle.

API Version 2012-08-10


65
Amazon DynamoDB Developer Guide
Step 4: Update Data

For more information about write operations, see Writing an Item (p. 376).

AWS Management Console


You can use the DynamoDB console to update data in the Music table.

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. Choose the Music table from the table list.
4. Choose the Items tab for the Music table.
5. Choose the item whose Artist value is Acme Band and SongTitle value is Happy Day.
6. Update the AlbumTitle value to Updated Album Title, and then choose Save.

The following image shows the updated item on the console.

AWS CLI
The following AWS CLI example updates an item in the Music table using update-item.

aws dynamodb update-item \


--table-name Music \
--key '{ "Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}}' \
--update-expression "SET AlbumTitle = :newval" \
--expression-attribute-values '{":newval":{"S":"Updated Album Title"}}' \
--return-values ALL_NEW

Using update-item returns the following sample result.

API Version 2012-08-10


66
Amazon DynamoDB Developer Guide
Step 5: Query Data

"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).

Step 5: Query Data in a Table


In this step, you query the data that you wrote to the Music table in the section called “Step 2: Write
Data” (p. 62) by specifying Artist.

For more information about query operations, see Working with Queries in DynamoDB (p. 458).

AWS Management Console


Follow these steps to use the DynamoDB console to query data in the Music table.

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. Choose the Music table from the table list.
4. Choose the Items tab for the Music table.
5. In the drop-down list, choose Query.

6. For Partition key, enter Acme Band, and then choose Start search.

API Version 2012-08-10


67
Amazon DynamoDB Developer Guide
Step 5: Query Data

AWS CLI
The following AWS CLI example queries an item in the Music table using query.

aws dynamodb query \


--table-name Music \
--key-condition-expression "Artist = :name" \
--expression-attribute-values '{":name":{"S":"Acme Band"}}'

Using query returns the following sample result.

{
"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).

API Version 2012-08-10


68
Amazon DynamoDB Developer Guide
Step 6: Create a Global Secondary Index

Step 6: Create a Global Secondary Index


In this step, you create a global secondary index for the Music table that you created in Step 1: Create a
Table (p. 59).

For more information about global secondary indexes, see Using Global Secondary Indexes in
DynamoDB (p. 500).

AWS Management Console


To use the Amazon DynamoDB console to create a global secondary index AlbumTitle-index for the
Music table:

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. Choose the Music table from the table list.
4. Choose the Indexes tab for the Music table.
5. Choose Create index.

6. For the Partition key, enter AlbumTitle, and then choose Create index.

API Version 2012-08-10


69
Amazon DynamoDB Developer Guide
Step 6: Create a Global Secondary Index

AWS CLI
The following AWS CLI example creates a global secondary index AlbumTitle-index for the Music
table using update-table.

aws dynamodb update-table \


--table-name Music \
--attribute-definitions AttributeName=AlbumTitle,AttributeType=S \
--global-secondary-index-updates \
"[{\"Create\":{\"IndexName\": \"AlbumTitle-index\",\"KeySchema\":[{\"AttributeName\":
\"AlbumTitle\",\"KeyType\":\"HASH\"}], \
\"ProvisionedThroughput\": {\"ReadCapacityUnits\": 10, \"WriteCapacityUnits\": 5
},\"Projection\":{\"ProjectionType\":\"ALL\"}}}]"

Using update-table returns the following sample result.

{
"TableDescription": {
"TableArn": "arn:aws:dynamodb:us-west-2:522194210714:table/Music",
"AttributeDefinitions": [
{
"AttributeName": "AlbumTitle",
"AttributeType": "S"
},

API Version 2012-08-10


70
Amazon DynamoDB Developer Guide
Step 6: Create a Global Secondary Index

{
"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
}
}

Note that the value of the IndexStatus field is set to CREATING.

To verify that DynamoDB has finished creating the AlbumTitle-index global secondary index, use the
describe-table command.

aws dynamodb describe-table --table-name Music | grep IndexStatus

API Version 2012-08-10


71
Amazon DynamoDB Developer Guide
Step 7: Query the Global Secondary Index

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

Step 7: Query the Global Secondary Index


In this step, you query a global secondary index on the Music table using the Amazon DynamoDB
console or the AWS CLI.

For more information about global secondary indexes, see Using Global Secondary Indexes in
DynamoDB (p. 500).

AWS Management Console


Follow these steps to use the DynamoDB console to query data through the AlbumTitle-index global
secondary index.

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. Choose the Music table from the table list.
4. Choose the Items tab for the Music table.
5. In the drop-down list, choose Query.

6. In the drop-down list next to Query , choose [Index] AlbumTitle-index: AlbumTitle .

For AlbumTitle, enter Somewhat Famous, and then choose Start search.

API Version 2012-08-10


72
Amazon DynamoDB Developer Guide
Step 7: Query the Global Secondary Index

AWS CLI
The following AWS CLI example queries a global secondary index AlbumTitle-index on the Music
table.

aws dynamodb query \


--table-name Music \
--index-name AlbumTitle-index \
--key-condition-expression "AlbumTitle = :name" \
--expression-attribute-values '{":name":{"S":"Somewhat Famous"}}'

Using query returns the following sample result.

{
"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
}

API Version 2012-08-10


73
Amazon DynamoDB Developer Guide
Step 8: (Optional) Clean Up

Step 8: (Optional) Clean Up Resources


If you no longer need the Amazon DynamoDB table that you created for the tutorial, you can delete
it. This step helps ensure that you aren't charged for resources that you aren't using. You can use the
DynamoDB console or the AWS CLI to delete the Music table that you created in Step 1: Create a
Table (p. 59).

For more information about table operations in DynamoDB, see Working with Tables and Data in
DynamoDB (p. 336).

AWS Management Console


To delete the Music table using the console:

1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.


2. In the navigation pane on the left side of the console, choose Tables.
3. Choose the Music table from the table list.
4. Choose the Indexes tab for the Music table.
5. Choose Delete table.

AWS CLI
The following AWS CLI example deletes the Music table using delete-table.

aws dynamodb delete-table --table-name Music

Getting Started with DynamoDB: Next Steps


For more information about using Amazon DynamoDB, see the following topics:

• Working with Tables and Data in DynamoDB (p. 336)


• Working with Items and Attributes (p. 375)
• Working with Queries in DynamoDB (p. 458)
• Using Global Secondary Indexes in DynamoDB (p. 500)
• DynamoDB Transactions (p. 650)
• In-Memory Acceleration with DynamoDB Accelerator (DAX) (p. 661)

API Version 2012-08-10


74
Amazon DynamoDB Developer Guide
Next Steps

• Getting Started with DynamoDB and AWS SDKs (p. 76)


• Programming with DynamoDB and the AWS SDKs (p. 214)

API Version 2012-08-10


75
Amazon DynamoDB Developer Guide
Java and DynamoDB

Getting Started with DynamoDB and


AWS SDKs
This section contains hands-on tutorials to help you learn about Amazon DynamoDB. We encourage you
to work through one of the language-specific tutorials. The code examples in these tutorials can run
against either the downloadable version of DynamoDB or the DynamoDB web service.
Note
AWS SDKs are available for a wide variety of languages. For a complete list, see Tools for
Amazon Web Services.

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)

Getting Started with Java and DynamoDB


In this tutorial, you use the AWS SDK for Java to write simple programs to perform the following Amazon
DynamoDB operations:

• 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:

API Version 2012-08-10


76
Amazon DynamoDB Developer Guide
Step 1: Create a Table

• 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.

Step 1: Create a Table using Java and DynamoDB


In this step, you create a table named Movies. The primary key for the table is composed of the
following attributes:

• year – The partition key. The ScalarAttributeType is N for number.


• title – The sort key. The ScalarAttributeType is S for string.

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;

public class MoviesCreateTable {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

String tableName = "Movies";

API Version 2012-08-10


77
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

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

Step 2: Load Sample Data with Java and DynamoDB


In this step, you populate the Movies table with sample data.

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" : { ... }
},

API Version 2012-08-10


78
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

...

In the JSON data, note the following:

• 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.

The following is an example of movie data.

{
"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.1: Download the Sample Data File


1. Download the sample data archive: moviedata.zip
2. Extract the data file (moviedata.json) from the archive.
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 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").

API Version 2012-08-10


79
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

* 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;

public class MoviesLoadData {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

JsonParser parser = new JsonFactory().createParser(new File("moviedata.json"));

JsonNode rootNode = new ObjectMapper().readTree(parser);


Iterator<JsonNode> iter = rootNode.iterator();

ObjectNode currentNode;

while (iter.hasNext()) {
currentNode = (ObjectNode) iter.next();

int year = currentNode.path("year").asInt();


String title = currentNode.path("title").asText();

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;
}

API Version 2012-08-10


80
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

}
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.

Step 3: Create, Read, Update, and Delete an Item


In this step, you perform read and write operations on an item in the Movies table.

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)

Step 3.1: Create a New Item


In this step, you add a new item to 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.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;

API Version 2012-08-10


81
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

import com.amazonaws.services.dynamodbv2.document.Table;

public class MoviesItemOps01 {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

int year = 2015;


String title = "The Big New Movie";

final Map<String, Object> infoMap = new HashMap<String, Object>();


infoMap.put("plot", "Nothing happens at all.");
infoMap.put("rating", 0);

try {
System.out.println("Adding a new item...");
PutItemOutcome outcome = table
.putItem(new Item().withPrimaryKey("year", year, "title",
title).withMap("info", infoMap));

System.out.println("PutItem succeeded:\n" + outcome.getPutItemResult());

}
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.

Step 3.2: Read an Item


In the previous program, you added the following item to the table.

{
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.

API Version 2012-08-10


82
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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;

public class MoviesItemOps02 {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

int year = 2015;


String title = "The Big New Movie";

GetItemSpec spec = new GetItemSpec().withPrimaryKey("year", year, "title",


title);

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

}
}

2. Compile and run the program.

API Version 2012-08-10


83
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

Step 3.3: Update an Item


You can use the updateItem method to modify an existing item. You can update values of existing
attributes, add new attributes, or remove attributes.

In this example, you perform the following updates:

• Change the value of the existing attributes (rating, plot).


• Add a new list attribute (actors) to the existing info map.

The item changes from the following:

{
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;

API Version 2012-08-10


84
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class MoviesItemOps03 {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

int year = 2015;


String title = "The Big New Movie";

UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("year",


year, "title", title)
.withUpdateExpression("set info.rating = :r, info.plot=:p, info.actors=:a")
.withValueMap(new ValueMap().withNumber(":r", 5.5).withString(":p",
"Everything happens all at once.")
.withList(":a", Arrays.asList("Larry", "Moe", "Curly")))
.withReturnValues(ReturnValue.UPDATED_NEW);

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.

Step 3.4: Increment an Atomic Counter


DynamoDB supports atomic counters. Use the updateItem method to increment or decrement the
value of an existing attribute without interfering with other write requests. (All write requests are
applied in the order in which they are received.)

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.

/**

API Version 2012-08-10


85
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

* 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;
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;

public class MoviesItemOps04 {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

int year = 2015;


String title = "The Big New Movie";

UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("year",


year, "title", title)
.withUpdateExpression("set info.rating = info.rating + :val")
.withValueMap(new ValueMap().withNumber(":val",
1)).withReturnValues(ReturnValue.UPDATED_NEW);

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

2. Compile and run the program.

API Version 2012-08-10


86
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

Step 3.5: Update an Item (Conditionally)


The following program shows how to use UpdateItem with a condition. If the condition evaluates to
true, the update succeeds; otherwise, the update is not performed.

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;

public class MoviesItemOps05 {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

int year = 2015;


String title = "The Big New Movie";

UpdateItemSpec updateItemSpec = new UpdateItemSpec()


.withPrimaryKey(new PrimaryKey("year", year, "title",
title)).withUpdateExpression("remove info.actors[0]")
.withConditionExpression("size(info.actors) > :num").withValueMap(new
ValueMap().withNumber(":num", 3))
.withReturnValues(ReturnValue.UPDATED_NEW);

// Conditional update (we expect this to fail)


try {
System.out.println("Attempting a conditional update...");

API Version 2012-08-10


87
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an 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());
}
}
}

2. Compile and run the program.

The program should fail with the following message:

The conditional request failed

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.

.withConditionExpression("size(info.actors) >= :num")

The condition is now greater than or equal to 3 instead of greater than 3.


4. Compile and run the program. The UpdateItem operation should now succeed.

Step 3.6: Delete an Item


You can use the deleteItem method to delete one item by specifying its primary key. You can
optionally provide a ConditionExpression to prevent the item from being deleted if the condition is
not met.

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;

API Version 2012-08-10


88
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class MoviesItemOps06 {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

int year = 2015;


String title = "The Big New Movie";

DeleteItemSpec deleteItemSpec = new DeleteItemSpec()


.withPrimaryKey(new PrimaryKey("year", year, "title",
title)).withConditionExpression("info.rating <= :val")
.withValueMap(new ValueMap().withNumber(":val", 5.0));

// Conditional delete (we expect this to fail)

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

2. Compile and run the program.

The program should fail with the following message:

The conditional request failed

This is because the rating for this particular move is greater than 5.
3. Modify the program to remove the condition in DeleteItemSpec.

DeleteItemSpec deleteItemSpec = new DeleteItemSpec()


.withPrimaryKey(new PrimaryKey("year", 2015, "title", "The Big New Movie"));

4. Compile and run the program. Now, the delete succeeds because you removed the condition.

Step 4: Query and Scan the Data


You can use the query method to retrieve data from a table. You must specify a partition key value. The
sort key is optional.

The primary key for the Movies table is composed of the following:

• year – The partition key. The attribute type is number.

API Version 2012-08-10


89
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

• title – The sort key. The attribute type is string.

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)

Step 4.1: Query


The code included in this step performs the following queries:

• Retrieve all movies released in the year 1985.


• Retrieve all movies released in the year 1992, with a title beginning with the letter "A" through the
letter "L".

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;

public class MoviesQuery {

public static void main(String[] args) throws Exception {

API Version 2012-08-10


90
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

HashMap<String, String> nameMap = new HashMap<String, String>();


nameMap.put("#yr", "year");

HashMap<String, Object> valueMap = new HashMap<String, Object>();


valueMap.put(":yyyy", 1985);

QuerySpec querySpec = new QuerySpec().withKeyConditionExpression("#yr


= :yyyy").withNameMap(nameMap)
.withValueMap(valueMap);

ItemCollection<QueryOutcome> items = null;


Iterator<Item> iterator = null;
Item item = null;

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");

querySpec.withProjectionExpression("#yr, title, info.genres, info.actors[0]")


.withKeyConditionExpression("#yr = :yyyy and title between :letter1
and :letter2").withNameMap(nameMap)
.withValueMap(valueMap);

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

API Version 2012-08-10


91
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

}
}
}

Note

• nameMap 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. You use the expression attribute name #yr to address this.
• valueMap provides value substitution. This is used because you can't use literals in any
expression, including KeyConditionExpression. You use the expression attribute value
:yyyy to address this.

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

Step 4.2: Scan


The scan method reads every item in the entire table and returns all the data in the table. You can
provide an optional filter_expression so that only the items matching your criteria are returned.
However, the filter is applied only after the entire table has been scanned.

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;

API Version 2012-08-10


92
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

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;

public class MoviesScan {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

ScanSpec scanSpec = new ScanSpec().withProjectionExpression("#yr, title,


info.rating")
.withFilterExpression("#yr between :start_yr and :end_yr").withNameMap(new
NameMap().with("#yr", "year"))
.withValueMap(new ValueMap().withNumber(":start_yr",
1950).withNumber(":end_yr", 1959));

try {
ItemCollection<ScanOutcome> items = table.scan(scanSpec);

Iterator<Item> iter = items.iterator();


while (iter.hasNext()) {
Item item = iter.next();
System.out.println(item.toString());
}

}
catch (Exception e) {
System.err.println("Unable to scan the table:");
System.err.println(e.getMessage());
}
}
}

In the code, note the following:

• ProjectionExpression specifies the attributes you want in the scan result.


• FilterExpression specifies a condition that returns only items that satisfy the condition. All
other items are discarded.
2. Compile and run the program.

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

API Version 2012-08-10


93
Amazon DynamoDB Developer Guide
Step 5: (Optional) Delete the Table

Step 5: (Optional) Delete the Table


To delete 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 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;

public class MoviesDeleteTable {

public static void main(String[] args) throws Exception {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withEndpointConfiguration(new
AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
.build();

DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("Movies");

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

2. Compile and run the program.

API Version 2012-08-10


94
Amazon DynamoDB Developer Guide
Summary

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.

Modifying the Code to Use the DynamoDB Service


To use the DynamoDB service, you must change the endpoint in your application.

1. Remove the following import.

import com.amazonaws.client.builder.AwsClientBuilder;

2. Next, go to AmazonDynamoDB in the code.

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.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withRegion(Regions.REGION)
.build();

For example, if you want to access the us-west-2 region, you would do the following.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()


.withRegion(Regions.US_WEST_2)
.build();

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.

Getting Started with JavaScript and DynamoDB


In this tutorial, you use JavaScript to write simple programs to perform the following Amazon
DynamoDB operations:

• 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.

API Version 2012-08-10


95
Amazon DynamoDB Developer Guide
Tutorial Prerequisites

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. Download the following file: MoviesJavaScript.zip.


2. Extract the file MoviesJavaScript.html from the archive.
3. Modify the MoviesJavaScript.html file to use your endpoint.
4. Run the MoviesJavaScript.html file.

Step 1: Create a DynamoDB Table with JavaScript


In this step, you create a table named Movies. The primary key for the table is composed of the
following attributes:

• year – The partition key. The AttributeType is N for number.


• title – The sort key. The AttributeType is S for string.

1. Copy the following program and paste it into a file named MoviesCreateTable.html.

API Version 2012-08-10


96
Amazon DynamoDB Developer Guide
Step 1: Create a Table

<!--
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.
-->
<html>
<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"
});

var dynamodb = new AWS.DynamoDB();

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
}
};

dynamodb.createTable(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML = "Unable to create table: "
+ "\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "Created table: " + "\n" +
JSON.stringify(data, undefined, 2);
}
});
}

</script>
</head>

API Version 2012-08-10


97
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

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

Step 2: Load Sample Data with JavaScript into


DynamoDB
In this step, you populate the Movies table with sample data.

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" : { ... }
},

...

In the JSON data, note the following:

• The year and title are used as the primary key attribute values for the Movies table.

API Version 2012-08-10


98
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

• 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.

The following is an example of movie data.

{
"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.1: Download the Sample Data File


1. Download the sample data archive: moviedata.zip
2. Extract the data file (moviedata.json) from the archive.
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.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/

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.
-->
<html>

API Version 2012-08-10


99
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

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>

API Version 2012-08-10


100
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

<input type="file" id="fileinput" accept='application/json'/>


<br><br>
<textarea readonly id= "textarea" style="width:400px; height:800px"></textarea>

<script>
document.getElementById('fileinput').addEventListener('change', processFile,
false);
</script>
</body>
</html>

2. Open the MoviesLoadData.html file in your browser.


3. Choose Browse, and load the moviedata.json file.

Step 3: Create, Read, Update, and Delete an Item


In this step, you perform read and write operations on an item in the Movies table.

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)

Step 3.1: Create a New Item


In this step, you add a new item to the Movies table.

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/

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.
-->
<html>
<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.

API Version 2012-08-10


101
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

// 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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

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.

Step 3.2: Read an Item


In the previous program, you added the following item to the table.

{
year: 2015,
title: "The Big New Movie",
info: {

API Version 2012-08-10


102
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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

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.
-->
<html>
<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

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);
}

API Version 2012-08-10


103
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

});
}

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

2. Open the MoviesItemOps02.html file in your browser.


3. Choose Read Item.

Step 3.3: Update an Item


You can use the update method to modify an item. You can update values of existing attributes, add
new attributes, or remove attributes.

In this example, you perform the following updates:

• Change the value of the existing attributes (rating, plot).


• Add a new list attribute (actors) to the existing info map.

The item changes from the following:

{
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

API Version 2012-08-10


104
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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.
-->
<html>
<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

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"
};

docClient.update(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML = "Unable to update item: " +
"\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "UpdateItem succeeded: " +
"\n" + JSON.stringify(data, undefined, 2);
}
});
}

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

API Version 2012-08-10


105
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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

Step 3.4: Increment an Atomic Counter


DynamoDB supports atomic counters, where you use the update method to increment or decrement the
value of an attribute without interfering with other write requests. (All write requests are applied in the
order in which they are received.)

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/

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.
-->
<html>
<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

function increaseRating() {
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";

API Version 2012-08-10


106
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "set info.rating = info.rating + :val",
ExpressionAttributeValues:{
":val":1
},
ReturnValues:"UPDATED_NEW"
};

docClient.update(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML = "Unable to update rating: "
+ "\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "Increase Rating succeeded:
" + "\n" + JSON.stringify(data, undefined, 2);
}
});
}

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

2. Open the MoviesItemOps04.html file in your browser.


3. Choose Increase Rating.

Step 3.5: Update an Item (Conditionally)


The following program shows how to use UpdateItem with a condition. If the condition evaluates to
true, the update succeeds; otherwise, the update is not performed.

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/

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.
-->
<html>

API Version 2012-08-10


107
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

function conditionalUpdate() {
var table = "Movies";
var year = 2015;
var title = "The Big New Movie";

// Conditional update (will fail)


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"
};

docClient.update(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML = "The conditional update
failed: " + "\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "The conditional update
succeeded: " + "\n" + JSON.stringify(data, undefined, 2);
}
});
}

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

2. Open the MoviesItemOps05.html file in your browser.


3. Choose Conditional Update.

API Version 2012-08-10


108
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

The program should fail with the following message:

The conditional update failed

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.

ConditionExpression: "size(info.actors) >= :num",

The condition is now greater than or equal to 3 instead of greater than 3.


5. Run the program again. The updateItem operation should now succeed.

Step 3.6: Delete an Item


You can use the delete method to delete one item by specifying its primary key. You can optionally
provide a ConditionExpression to prevent the item from being deleted if the condition is not met.

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/

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.
-->
<html>
<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

function conditionalDelete() {
var table = "Movies";
var year = 2015;

API Version 2012-08-10


109
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

var title = "The Big New Movie";

var params = {
TableName:table,
Key:{
"year":year,
"title":title
},
ConditionExpression:"info.rating <= :val",
ExpressionAttributeValues: {
":val": 5.0
}
};

docClient.delete(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML = "The conditional delete
failed: " + "\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "The conditional delete
succeeded: " + "\n" + JSON.stringify(data, undefined, 2);
}
});
}

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

2. Open the MoviesItemOps06.html file in your browser.


3. Choose Conditional Delete.

The program should fail with the following message:

The conditional delete failed

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.

API Version 2012-08-10


110
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

Step 4: Query and Scan the Data with JavaScript and


DynamoDB
You can use the query method to retrieve data from a table. You must specify a partition key value; the
sort key is optional.

The primary key for the Movies table is composed of the following:

• year – The partition key. The attribute type is number. 


• title – The sort key. The attribute type is string.

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)

Step 4.1: Query - All Movies Released in a Year


The program included in this step retrieves all movies released in the year 1985.

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/

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.
-->
<html>
<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",

API Version 2012-08-10


111
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

// 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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

function queryData() {
document.getElementById('textarea').innerHTML += "Querying for movies from 1985.";

var params = {
TableName : "Movies",
KeyConditionExpression: "#yr = :yyyy",
ExpressionAttributeNames:{
"#yr": "year"
},
ExpressionAttributeValues: {
":yyyy":1985
}
};

docClient.query(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML += "Unable to query. Error: "
+ "\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML += "Querying for movies from
1985: " + "\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>

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

API Version 2012-08-10


112
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

Step 4.2: Query - All Movies Released in a Year with Certain


Titles
The program included in this step retrieves all movies released in year 1992, with title beginning with
the letter "A" through the letter "L".

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/

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.
-->
<html>
<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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

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"
}
};

docClient.query(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML += "Unable to query. Error: "
+ "\n" + JSON.stringify(err, undefined, 2);

API Version 2012-08-10


113
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

} 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>

2. Open the MoviesQuery02.html file in your browser.


3. Choose Query.

Step 4.3: Scan


The scan method reads every item in the entire table, and returns all the data in the table. You can
provide an optional filter_expression, so that only the items matching your criteria are returned.
However, the filter is applied only after the entire table has been scanned.

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/

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.
-->
<html>
<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.

API Version 2012-08-10


114
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

// For security reasons, do not store AWS Credentials in your files. Use Amazon
Cognito instead.
secretAccessKey: "fakeSecretAccessKey"
});

var docClient = new AWS.DynamoDB.DocumentClient();

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

function onScan(err, data) {


if (err) {
document.getElementById('textarea').innerHTML += "Unable to scan the table:
" + "\n" + JSON.stringify(err, undefined, 2);
} else {
// Print all the movies
document.getElementById('textarea').innerHTML += "Scan succeeded. " + "\n";
data.Items.forEach(function(movie) {
document.getElementById('textarea').innerHTML += movie.year + ": " +
movie.title + " - rating: " + movie.info.rating + "\n";
});

// Continue scanning if we have more movies (per scan 1MB limitation)


document.getElementById('textarea').innerHTML += "Scanning for more..." +
"\n";
params.ExclusiveStartKey = data.LastEvaluatedKey;
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>

In the code, note the following:

• ProjectionExpression specifies the attributes you want in the scan result.


• FilterExpression specifies a condition that returns only items that satisfy the condition. All
other items are discarded.
2. Open the MoviesScan.html file in your browser.

API Version 2012-08-10


115
Amazon DynamoDB Developer Guide
Step 5: (Optional): Delete the Table

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

Step 5: Delete the Table with JavaScript


To delete the Movies table:

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/

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.
-->
<html>
<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"
});

var dynamodb = new AWS.DynamoDB();

function deleteMovies() {
var params = {
TableName : "Movies"
};

dynamodb.deleteTable(params, function(err, data) {


if (err) {
document.getElementById('textarea').innerHTML = "Unable to delete table: "
+ "\n" + JSON.stringify(err, undefined, 2);
} else {
document.getElementById('textarea').innerHTML = "Table deleted.";
}
});
}

</script>

API Version 2012-08-10


116
Amazon DynamoDB Developer Guide
Summary

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

2. Open the MoviesDeleteTable.html file in your browser.


3. Choose Delete Table.

Summary and Review of JavaScript and DynamoDB


Tutorial
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.

Updating the AWS Configuration Region to Use the DynamoDB


Web Service
To use the DynamoDB web service, you must update the AWS Region in your application. You also have
to make sure that Amazon Cognito is available in that same Region so that your browser scripts can
authenticate successfully.

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.

Configuring AWS Credentials in Your Files Using Amazon


Cognito
The recommended way to obtain AWS credentials for your web and mobile applications is to use Amazon
Cognito. Amazon Cognito helps you avoid hardcoding your AWS credentials in your files. Amazon
Cognito uses AWS Identity and Access Management (IAM) roles to generate temporary credentials for
your application's authenticated and unauthenticated users.

For more information, see Configuring AWS Credentials in Your Files Using Amazon Cognito (p. 929).

API Version 2012-08-10


117
Amazon DynamoDB Developer Guide
Node.js and DynamoDB

Getting Started with Node.js and DynamoDB


In this tutorial, you use the AWS SDK for JavaScript to write simple applications to perform the following
Amazon DynamoDB operations:

• 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.

Step 1: Create a Table with in DynamoDB with AWS


SDK for JavaScript
In this step, you create a table named Movies. The primary key for the table is composed of the
following attributes:

• year – The partition key. The AttributeType is N for number.


• title – The sort key. The AttributeType is S for string.

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.
*/

API Version 2012-08-10


118
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

var AWS = require("aws-sdk");

AWS.config.update({
region: "us-west-2",
endpoint: "http://localhost:8000"
});

var dynamodb = new AWS.DynamoDB();

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
}
};

dynamodb.createTable(params, function(err, data) {


if (err) {
console.error("Unable to create table. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("Created table. Table description JSON:", JSON.stringify(data,
null, 2));
}
});

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

Step 2: Load Sample Data in DynamoDB with AWS


SDK for JavaScript
In this step, you populate the Movies table with sample data.

Topics
• Step 2.1: Download the Sample Data File (p. 120)
• Step 2.2: Load the Sample Data into the Movies Table (p. 121)

API Version 2012-08-10


119
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

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" : { ... }
},

...

In the JSON data, note the following:

• 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.

The following is an example of movie data.

{
"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.1: Download the Sample Data File


1. Download the sample data archive: moviedata.zip
2. Extract the data file (moviedata.json) from the archive.

API Version 2012-08-10


120
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

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"
});

var docClient = new AWS.DynamoDB.DocumentClient();

console.log("Importing movies into DynamoDB. Please wait.");

var allMovies = JSON.parse(fs.readFileSync('moviedata.json', 'utf8'));


allMovies.forEach(function(movie) {
var params = {
TableName: "Movies",
Item: {
"year": movie.year,
"title": movie.title,
"info": movie.info
}
};

docClient.put(params, function(err, data) {


if (err) {
console.error("Unable to add movie", movie.title, ". Error JSON:",
JSON.stringify(err, null, 2));
} else {
console.log("PutItem succeeded:", movie.title);
}
});
});

2. To run the program, enter the following command.

node MoviesLoadData.js

API Version 2012-08-10


121
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

Step 3: Create, Read, Update, and Delete an Item


In this step, you perform read and write operations on an item in the Movies table.

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)

Step 3.1: Create a New Item


In this step, you add a new item to the Movies table.

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 docClient = new AWS.DynamoDB.DocumentClient();

var table = "Movies";

var year = 2015;


var title = "The Big New Movie";

var params = {
TableName:table,
Item:{
"year": year,
"title": title,
"info":{
"plot": "Nothing happens at all.",
"rating": 0
}
}

API Version 2012-08-10


122
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

};

console.log("Adding a new item...");


docClient.put(params, function(err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});

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

Step 3.2: Read an Item


In the previous program, you added the following item to the table.

{
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"
});

API Version 2012-08-10


123
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

var docClient = new AWS.DynamoDB.DocumentClient();

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) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("GetItem succeeded:", JSON.stringify(data, null, 2));
}
});

2. To run the program, enter the following command.

node MoviesItemOps02.js

Step 3.3: Update an Item


You can use the update method to modify an existing item. You can update values of existing attributes,
add new attributes, or remove attributes.

In this example, you perform the following updates:

• Change the value of the existing attributes (rating, plot).


• Add a new list attribute (actors) to the existing info map.

The following shows the existing item.

{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}

The item is updated as follows.

{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Everything happens all at once.",
rating: 5.5,
actors: ["Larry", "Moe", "Curly"]

API Version 2012-08-10


124
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

}
}

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 docClient = new AWS.DynamoDB.DocumentClient()

var table = "Movies";

var year = 2015;


var title = "The Big New Movie";

// Update the item, unconditionally,

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"
};

console.log("Updating the item...");


docClient.update(params, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
});

API Version 2012-08-10


125
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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

Step 3.4: Increment an Atomic Counter


DynamoDB supports atomic counters, where you use the update method to increment or decrement
the value of an existing attribute without interfering with other write requests. (All write requests are
applied in the order in which they are received.)

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 docClient = new AWS.DynamoDB.DocumentClient()

var table = "Movies";

var year = 2015;


var title = "The Big New Movie";

// Increment an atomic counter

var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
UpdateExpression: "set info.rating = info.rating + :val",
ExpressionAttributeValues:{
":val": 1
},

API Version 2012-08-10


126
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

ReturnValues:"UPDATED_NEW"
};

console.log("Updating the item...");


docClient.update(params, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
});

2. To run the program, enter the following command.

node MoviesItemOps04.js

Step 3.5: Update an Item (Conditionally)


The following program shows how to use UpdateItem with a condition. If the condition evaluates to
true, the update succeeds; otherwise, the update is not performed.

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 docClient = new AWS.DynamoDB.DocumentClient()

var table = "Movies";

var year = 2015;


var title = "The Big New Movie";

// Conditional update (will fail)

var params = {
TableName:table,
Key:{
"year": year,

API Version 2012-08-10


127
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

"title": title
},
UpdateExpression: "remove info.actors[0]",
ConditionExpression: "size(info.actors) > :num",
ExpressionAttributeValues:{
":num": 3
},
ReturnValues:"UPDATED_NEW"
};

console.log("Attempting a conditional update...");


docClient.update(params, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
});

2. To run the program, enter the following command.

node MoviesItemOps05.js

The program should fail with the following message.

The conditional request failed

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.

ConditionExpression: "size(info.actors) >= :num",

The condition is now greater than or equal to 3 instead of greater than 3.


4. Run the program again. The updateItem operation should now succeed.

Step 3.6: Delete an Item


You can use the delete method to delete one item by specifying its primary key. You can optionally
provide a ConditionExpression to prevent the item from being deleted if the condition is not met.

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

API Version 2012-08-10


128
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

* 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 docClient = new AWS.DynamoDB.DocumentClient();

var table = "Movies";

var year = 2015;


var title = "The Big New Movie";

var params = {
TableName:table,
Key:{
"year": year,
"title": title
},
ConditionExpression:"info.rating <= :val",
ExpressionAttributeValues: {
":val": 5.0
}
};

console.log("Attempting a conditional delete...");


docClient.delete(params, function(err, data) {
if (err) {
console.error("Unable to delete item. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("DeleteItem succeeded:", JSON.stringify(data, null, 2));
}
});

2. To run the program, enter the following command.

node MoviesItemOps06.js

The program should fail with the following message.

The conditional request failed

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.

API Version 2012-08-10


129
Amazon DynamoDB Developer Guide
Step 4: Query and Scan Data

Step 4: Query and Scan Data with AWS SDK for


JavaScript in DynamoDB
You can use the query method to retrieve data from a table. You must specify a partition key value; the
sort key is optional.

The primary key for the Movies table is composed of the following:

• year – The partition key. The attribute type is number. 


• title – The sort key. The attribute type is string.

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)

Step 4.1: Query - All Movies Released in a Year


The program included in this step retrieves all movies released in the year 1985.

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 docClient = new AWS.DynamoDB.DocumentClient();

API Version 2012-08-10


130
Amazon DynamoDB Developer Guide
Step 4: Query and Scan Data

console.log("Querying for movies from 1985.");

var params = {
TableName : "Movies",
KeyConditionExpression: "#yr = :yyyy",
ExpressionAttributeNames:{
"#yr": "year"
},
ExpressionAttributeValues: {
":yyyy": 1985
}
};

docClient.query(params, function(err, data) {


if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log(" -", item.year + ": " + item.title);
});
}
});

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

Step 4.2: Query - All Movies Released in a Year with Certain


Titles
The program included in this step retrieves all movies released in year 1992, with title beginning with
the letter "A" through the letter "L".

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

API Version 2012-08-10


131
Amazon DynamoDB Developer Guide
Step 4: Query and Scan Data

* 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 docClient = new AWS.DynamoDB.DocumentClient();

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"
}
};

docClient.query(params, function(err, data) {


if (err) {
console.log("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log(" -", item.year + ": " + item.title
+ " ... " + item.info.genres
+ " ... " + item.info.actors[0]);
});
}
});

2. To run the program, enter the following command.

node MoviesQuery02.js

Step 4.3: Scan


The scan method reads every item in the table and returns all the data in the table. You can provide an
optional filter_expression, so that only the items matching your criteria are returned. However, the
filter is applied only after the entire table has been scanned.

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.

API Version 2012-08-10


132
Amazon DynamoDB Developer Guide
Step 4: Query and Scan Data

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 docClient = new AWS.DynamoDB.DocumentClient();

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
}
};

console.log("Scanning Movies table.");


docClient.scan(params, onScan);

function onScan(err, data) {


if (err) {
console.error("Unable to scan the table. Error JSON:", JSON.stringify(err,
null, 2));
} else {
// print all the movies
console.log("Scan succeeded.");
data.Items.forEach(function(movie) {
console.log(
movie.year + ": ",
movie.title, "- rating:", movie.info.rating);
});

// continue scanning if we have more movies, because


// scan can retrieve a maximum of 1MB of data
if (typeof data.LastEvaluatedKey != "undefined") {
console.log("Scanning for more...");
params.ExclusiveStartKey = data.LastEvaluatedKey;
docClient.scan(params, onScan);
}
}
}

API Version 2012-08-10


133
Amazon DynamoDB Developer Guide
Step 5: (Optional): Delete the Table

In the code, note the following:

• ProjectionExpression specifies the attributes you want in the scan result.


• FilterExpression specifies a condition that returns only items that satisfy the condition. All
other items are discarded.
2. To run the program, enter the following command.

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

Step 5: (Optional): Delete the Table using AWS SDK


for JavaScript
To delete the Movies table:

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 dynamodb = new AWS.DynamoDB();

var params = {
TableName : "Movies"
};

dynamodb.deleteTable(params, function(err, data) {


if (err) {
console.error("Unable to delete table. Error JSON:", JSON.stringify(err, null,
2));
} else {
console.log("Deleted table. Table description JSON:", JSON.stringify(data,
null, 2));
}
});

API Version 2012-08-10


134
Amazon DynamoDB Developer Guide
Summary

2. To run the program, enter the following command.

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.

Modifying the Code to Use the DynamoDB Service


To use the DynamoDB service, you must change the endpoint in your application. To do this, modify the
following code.

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.

Getting Started with .NET and DynamoDB


In this tutorial, you use the AWS SDK for .NET to write simple programs to perform the following
Amazon DynamoDB operations:

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

API Version 2012-08-10


135
Amazon DynamoDB Developer Guide
Tutorial Prerequisites

• Step 4: Add a Movie to the DynamoDB Table (p. 145)


• Step 5: Read and Display a Record from the DynamoDB Table (p. 146)
• Step 6: Update the New Movie Record in the DynamoDB Table (p. 147)
• Step 7: Conditionally Delete (p. 150)
• Step 8: Query a DynamoDB Table with .NET (p. 152)
• Step 9: Scan the Movies Table with .NET (p. 155)
• Step 10: Delete the Movies Table with .NET (p. 156)

.NET and DynamoDB Tutorial Prerequisites


The Microsoft .NET and DynamoDB Tutorial (p. 135) describes how to use the AWS SDK for .NET to
create simple programs for performing Amazon DynamoDB operations.

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. Download a .zip archive containing the solution from DynamoDB_intro.zip.


2. Save the archive to a convenient place on your computer, and extract (unzip) the files in it.
3. In Visual Studio, press Ctrl+Shift+O, or choose Open on the File menu and choose Project/
Solution.
4. Navigate to DynamoDB_intro.sln in the DynamoDB_intro directory that you unzipped, and
choose Open.
• Build the DynamoDB_intro solution, and then open the 00_Main.cs file 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.

API Version 2012-08-10


136
Amazon DynamoDB Developer Guide
Step 1: Create a Client

Installing the External Dependencies of the DynamoDB_intro


Solution
The DynamoDB_intro solution already has the Amazon DynamoDB SDK installed in it. It also has the
open-source Newtonsoft Json.NET library for deserializing JSON data, licensed under the MIT License
(MIT) (see https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md).

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.

PM> Install-Package AWSSDK.DynamoDBv2

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.

PM> Install-Package Newtonsoft.Json

Next Step
Step 1: Create a DynamoDB Client (p. 137)

Step 1: Create a DynamoDB Client


The first step in the Microsoft .NET and DynamoDB Tutorial (p. 135) is to create a client that gives you
access to the Amazon DynamoDB API. The Main function in DynamoDB_intro does this by calling a
createClient function implemented in the 01_CreateClient.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/
*
* 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

API Version 2012-08-10


137
Amazon DynamoDB Developer Guide
Step 1: Create a Client

* 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);
}

// If DynamoDB-Local does seem to be running, so create a client


Console.WriteLine( " -- Setting up a DynamoDB-Local client (DynamoDB Local seems
to be running)" );
AmazonDynamoDBConfig ddbConfig = new AmazonDynamoDBConfig();
ddbConfig.ServiceURL = "http://localhost:8000";
try { client = new AmazonDynamoDBClient( ddbConfig ); }
catch( Exception ex )
{
Console.WriteLine( " FAILED to create a DynamoDBLocal client; " +
ex.Message );
operationFailed = true;
return false;
}
}

else
{
try { client = new AmazonDynamoDBClient( ); }
catch( Exception ex )
{

API Version 2012-08-10


138
Amazon DynamoDB Developer Guide
Step 2: Create a Table

Console.WriteLine( " FAILED to create a DynamoDB client; " + ex.Message );


operationFailed = true;
}
}
operationSucceeded = true;
return true;
}
}
}

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)

Step 2: Create a DynamoDB Table Using the Low-


Level API
The document model in the AWS SDK for .NET doesn't provide for creating tables, so you have to use the
low-level APIs. For more information, see Working with DynamoDB Tables in .NET (p. 368).

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:

• year – The partition key. The AttributeType is N for number.


Note
Because "year" is a reserved word in DynamoDB, you need to create an alias for it (such as
#yr) using an ExpressionAttributeNames object when referring to it in a low-level
expression.
• title – The sort key. The AttributeType is S for string.

The Main function in DynamoDB_intro does this by waiting on an asynchronous


CreatingTable_async function implemented in the 02_CreatingTable.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/
*
* 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;

API Version 2012-08-10


139
Amazon DynamoDB Developer Guide
Step 2: Create a Table

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

// If the table exists, get its description


try
{
descResponse = await
Ddb_Intro.client.DescribeTableAsync(Ddb_Intro.movies_table_name);
operationSucceeded = true;
}
catch (Exception ex)
{
Console.WriteLine(" However, its description is not available ({0})",
ex.Message);
Ddb_Intro.moviesTableDescription = null;
operationFailed = true;
return ( true );
}
Ddb_Intro.moviesTableDescription = descResponse.Table;
return ( true );
}
return ( false );

API Version 2012-08-10


140
Amazon DynamoDB Developer Guide
Step 2: Create a Table

/*--------------------------------------------------------------------------
* 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;

// Build the 'CreateTableRequest' structure for the new table


request = new CreateTableRequest
{
TableName = table_name,
AttributeDefinitions = table_attributes,
KeySchema = table_key_schema,
// Provisioned-throughput settings are always required,
// although the local test version of DynamoDB ignores them.
ProvisionedThroughput = provisioned_throughput
};

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 );
}

// Report the status of the new table...


Console.WriteLine( " Status of the new table: '{0}'.",
response.TableDescription.TableStatus );
Ddb_Intro.moviesTableDescription = response.TableDescription;
return ( true );
}
}
}

The CreatingTable_async function starts by waiting on an asynchronous


checkingTableExistence_async function to determine whether a table named "Movies" already
exists. If the table exists, checkingTableExistence_async retrieves the TableDescription for the
existing Table.

If the table doesn't already exist, CreatingTable_async waits on CreateNewTable_async to create


the Movies table using the DynamoDB client API CreateTableAsync.

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

API Version 2012-08-10


141
Amazon DynamoDB Developer Guide
Step 3: Load Data

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)

Step 3: Load Sample Data into the DynamoDB Table


In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you populate the new Movies table
in Amazon DynamoDB with sample data from the Internet Movie Database (IMDb). This data is stored in
JSON format in a local text file named moviedata.json.

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

API Version 2012-08-10


142
Amazon DynamoDB Developer Guide
Step 3: Load Data

* 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.IO;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.DocumentModel;

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;

movieArray = await ReadJsonMovieFile_async( filePath );


if( movieArray != null )
await LoadJsonMovieData_async( table, movieArray );
}

/*--------------------------------------------------------------------------
* ReadJsonMovieFile_async
*--------------------------------------------------------------------------*/
public static async Task<JArray> ReadJsonMovieFile_async( string JsonMovieFilePath )
{
StreamReader sr = null;
JsonTextReader jtr = null;
JArray movieArray = null;

Console.WriteLine( " -- Reading the movies data from a JSON file..." );


operationSucceeded = false;
operationFailed = false;
try
{
sr = new StreamReader( JsonMovieFilePath );
jtr = new JsonTextReader( sr );
movieArray = (JArray) await JToken.ReadFromAsync( jtr );
operationSucceeded = true;
}
catch( Exception ex )
{
Console.WriteLine( " ERROR: could not read the file!\n Reason: {0}.",
ex.Message );
operationFailed = true;
}
finally
{
if( jtr != null )
jtr.Close( );
if( sr != null )
sr.Close( );
}
if( operationSucceeded )
{
Console.WriteLine( " -- Succeeded in reading the JSON file!" );
return ( movieArray );
}

API Version 2012-08-10


143
Amazon DynamoDB Developer Guide
Step 3: Load Data

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!" );
}
}
}

LoadingData_async begins by waiting on ReadJsonMovieFile_async. This function reads the


moviedata.json file using the open-source Newtonsoft Json.NET library, which is licensed under the
MIT License.

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)

API Version 2012-08-10


144
Amazon DynamoDB Developer Guide
Step 4: Add a Movie

Step 4: Add a Movie to the DynamoDB Table


In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you add a new movie record to
the Movies table in Amazon DynamoDB. The Main function in DynamoDB_intro starts by creating
a DynamoDB document model Document and then waits on WritingNewMovie_async, which is
implemented in the 04_WritingNewItem.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/
*
* 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;

int year = (int) newItem["year"];


string name = newItem["title"];

if( await ReadingMovie_async( year, name, false ) )


Console.WriteLine( " The {0} movie \"{1}\" is already in the Movies table...\n" +
" -- No need to add it again... its info is as follows:\n{2}",
year, name, movie_record.ToJsonPretty( ) );
else
{
try
{
Task<Document> writeNew = moviesTable.PutItemAsync(newItem, token);
Console.WriteLine(" -- Writing a new movie to the Movies table...");
await writeNew;
Console.WriteLine(" -- Wrote the item successfully!");
operationSucceeded = true;
}
catch (Exception ex)
{
Console.WriteLine(" FAILED to write the new movie, because:\n {0}.",
ex.Message);
operationFailed = true;
}
}
}
}

API Version 2012-08-10


145
Amazon DynamoDB Developer Guide
Step 5: Read a Movie

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.

For More Information


• To learn more about reading and writing data in DynamoDB tables, see Working with Items and
Attributes (p. 375).
• For more information about the DynamoDB document model API, see .NET: Document
Model (p. 276).
• For more information about asynchronous methods, see AWS Asynchronous APIs for .NET.

Next Step
Step 5: Read and Display a Record from the DynamoDB Table (p. 146)

Step 5: Read and Display a Record from the


DynamoDB Table
In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you retrieve and display the new
movie record that you added in Step 4 (p. 145). The Main function in DynamoDB_intro does this by
waiting on ReadingMovie_async, which is implemented in the 05_ReadingItem.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/
*
* 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

API Version 2012-08-10


146
Amazon DynamoDB Developer Guide
Step 6: Update the Movie

{
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 );
}
}

ReadingMovie_async in turn waits on the DynamoDB Table.GetItemAsyn method to retrieve the


new movie record as a Document. ReadingMovie_async then displays the movie as JSON text using
the Document.ToJsonPretty method.

For More Information


• To learn more about reading and writing data in DynamoDB tables, see Working with Items and
Attributes (p. 375).
• For more information about the DynamoDB document model API, see .NET: Document
Model (p. 276).
• For more information about asynchronous methods, see AWS Asynchronous APIs for .NET.

Next Step
Step 6: Update the New Movie Record in the DynamoDB Table (p. 147)

Step 6: Update the New Movie Record in the


DynamoDB Table
In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you update the new movie record in
several different ways.

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)

API Version 2012-08-10


147
Amazon DynamoDB Developer Guide
Step 6: Update the Movie

• Next Step (p. 150)

Change Plot and Rating, and Add Actors


The Main function in DynamoDB_intro changes the plot and rating of the movie record that you added
in Step 4 (p. 145), and it also adds a list of actors to it. The document model in the AWS SDK for .NET
doesn't support updating nested attributes such as the items under the info attribute. Because of this,
Main uses the low-level client API rather than a document-model Table method.

It starts by creating a low-level UpdateItemRequest to make this change.

UpdateItemRequest updateRequest = new UpdateItemRequest()


{
TableName = movies_table_name,
Key = new Dictionary<string, AttributeValue>
{
{ partition_key_name, new AttributeValue { N = "2018" } },
{ sort_key_name, new AttributeValue { S = "The Big New Movie" } }
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":r", new AttributeValue { N = "5.5" } },
{ ":p", new AttributeValue { S = "Everything happens all at once!" } },
{ ":a", new AttributeValue { L = new List<AttributeValue>
{ new AttributeValue { S ="Larry" },
new AttributeValue { S = "Moe" },
new AttributeValue { S = "Curly" } }
}
}
},
UpdateExpression = "SET info.rating = :r, info.plot = :p, info.actors = :a",
ReturnValues = "NONE"
};

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.

The UpdatingMovie_async is implemented in the 06_UpdatingItem.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/
*
* 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;

API Version 2012-08-10


148
Amazon DynamoDB Developer Guide
Step 6: Update the Movie

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 );
}
}
}

UpdatingMovie_async waits on the low-level DynamoDB Client.UpdateItemAsync method


to update the movie record. If the update is successful, and if the report parameter is true,
UpdatingMovie_async displays the updated movie record.

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.

Increment the Movie Rating Atomically


DynamoDB supports the atomic update of counters, where you use a low-level update method to
increment or decrement the value of an existing attribute without interference from other write
requests. (All write requests in DynamoDB are applied in the order in which they are received.)

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.

API Version 2012-08-10


149
Amazon DynamoDB Developer Guide
Step 7: Delete an Item with Conditions

updateRequest.ExpressionAttributeValues = new Dictionary<string, AttributeValue>


{
{ ":inc", new AttributeValue { N = "1" } }
};
updateRequest.UpdateExpression = "SET info.rating = info.rating + :inc";

Then, once again, it waits on UpdatingMovie_async to make the change.

Try to Update Using a Condition That Fails


You can also add a condition to an update request, so that if the condition is not met, the update does
not occur.

To demonstrate this, the Main function makes the following changes to the UpdateItemRequest that
it just used to increment the movie rating.

updateRequest.ExpressionAttributeValues.Add( ":n", new AttributeValue { N = "3" } );


updateRequest.ConditionExpression = "size(info.actors) > :n";

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.

For More Information


• To learn more about reading and writing data in DynamoDB tables, see Working with Items and
Attributes (p. 375).
• For more information about the DynamoDB document model API, see .NET: Document
Model (p. 276).
• For more information about asynchronous methods, see AWS Asynchronous APIs for .NET.

Next Step
Step 7: Conditionally Delete (p. 150)

Step 7: Conditionally Delete


In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you try to delete a movie record
with a condition that is not met, and the deletion fails. Then, when the condition is changed so that it is
met, the deletion succeeds.

The Main function in DynamoDB_intro starts by creating a condition as follows.

Expression condition = new Expression();


condition.ExpressionAttributeValues[":val"] = 5.0;
condition.ExpressionStatement = "info.rating <= :val";

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.

/**

API Version 2012-08-10


150
Amazon DynamoDB Developer Guide
Step 7: Delete an Item with Conditions

* 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
{

/*--------------------------------------------------------------------------
* 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 );
}
}

DeletingItem_async in turn includes the condition Expression in a


DeleteItemOperationConfig object that it passes to the DynamoDB Table.DeleteItemAsync
method when it waits on it.

Because the movie's rating is 6.5, which is higher than 5.0, the condition is not met, and the deletion
fails.

API Version 2012-08-10


151
Amazon DynamoDB Developer Guide
Step 8: Query a Table

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)

Step 8: Query a DynamoDB Table with .NET


In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you query the Movies table in three
different ways.

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)

Use a Simple Document Model Search to Query for 1985 Movies


To set up a simple document-model query, the Main function in DynamoDB_intro creates a Search
object by calling the Table.Query API with 1985 as the partition key (also known as the hash key), and
an empty filter Expression.

try { search = moviesTable.Query( 1985, new Expression( ) ); }

It then waits on SearchListing_async, which is implemented in 08_Querying.cs to retrieve and


display the query results.

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

API Version 2012-08-10


152
Amazon DynamoDB Developer Guide
Step 8: Query a Table

*--------------------------------------------------------------------------*/
public static async Task<bool> SearchListing_async( Search search )
{
int i = 0;
List<Document> docList = new List<Document>( );

Console.WriteLine( " Here are the movies retrieved:\n" +


"
--------------------------------------------------------------------------" );
Task<List<Document>> getNextBatch;
operationSucceeded = false;
operationFailed = false;

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 );
}

foreach( Document doc in docList )


{
i++;
showMovieDocShort( doc );
}
} while( !search.IsDone );
Console.WriteLine( " -- Retrieved {0} movies.", i );
operationSucceeded = true;
return ( true );
}

/*--------------------------------------------------------------------------
* 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( ) )
{

API Version 2012-08-10


153
Amazon DynamoDB Developer Guide
Step 8: Query a Table

operationFailed = true;
return ( false );
}
Console.WriteLine( " Here are the movies retrieved:" +
"
--------------------------------------------------------------------------" );
foreach( Dictionary<string, AttributeValue> item in qResponse.Items )
showMovieAttrsShort( item );

Console.WriteLine( " -- Retrieved {0} movies.", qResponse.Items.Count );


operationSucceeded = true;
return ( true );
}
}

Use a QueryOperationConfig to Create a More Complex Query


Search
To query for 1992 movies with titles from "B..." to "Hzz...", the Main function creates a
QueryOperationConfig object with a QueryFilter and various other fields.

QueryOperationConfig config = new QueryOperationConfig( );


config.Filter = new QueryFilter( );
config.Filter.AddCondition( "year", QueryOperator.Equal, new DynamoDBEntry[ ]
{ 1992 } );
config.Filter.AddCondition( "title", QueryOperator.Between, new DynamoDBEntry[ ]
{ "B", "Hzz" } );
config.AttributesToGet = new List<string> { "year", "title", "info" };
config.Select = SelectValues.SpecificAttributes;

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.

Use a Low-Level Query to Find 1992 Movies with Titles Between


'M...' and 'Tzz...'
To use a low-level query to retrieve 1992 movies with titles from "M..." to "Tzz...", the Main function
creates a QueryRequest object.

QueryRequest qRequest= new QueryRequest


{
TableName = "Movies",
ExpressionAttributeNames = new Dictionary<string, string>
{
{ "#yr", "year" }
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":qYr", new AttributeValue { N = "1992" } },
{ ":tSt", new AttributeValue { S = "M" } },
{ ":tEn", new AttributeValue { S = "Tzz" } }
},
KeyConditionExpression = "#yr = :qYr and title between :tSt and :tEn",
ProjectionExpression = "#yr, title, info.actors[0], info.genres,
info.running_time_secs"
};

API Version 2012-08-10


154
Amazon DynamoDB Developer Guide
Step 9: Scan a Table

It then waits on the ClientQuerying_async function implemented in the 08_Querying.cs


file. ClientQuerying_async waits in turn on the low-level DynamoDB method
AmazonDynamoDBClient.QueryAsync to retrieve the query results.
Note
Because "year" is a reserved word in DynamoDB, you need to create an alias for it (here #yr)
using ExpressionAttributeNames in order to use it in a low-level expression.

Next Step
Step 9: Scan the Movies Table with .NET (p. 155)

Step 9: Scan the Movies Table with .NET


In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you scan the Movies table in two
different ways: by using a document model scan and a low-level scan.

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)

Use a Document Model Search to Scan for 1950s Movies


To set up a document model scan for 1950s movies, the Main function in DynamoDB_intro creates a
ScanOperationConfig object with a ScanFilter:

ScanFilter filter = new ScanFilter( );


filter.AddCondition( "year", ScanOperator.Between, new DynamoDBEntry[ ] { 1950,
1959 } );
ScanOperationConfig scanConfig = new ScanOperationConfig
{
AttributesToGet = new List<string> { "year, title, info" },
Filter = filter
};

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.

Use a Low-Level Scan to Retrieve 1960s Movies


To set up a low-level scan for 1960s movies, the Main function in DynamoDB_intro creates a
ScanRequest object with various fields.

ScanRequest sRequest = new ScanRequest


{
TableName = "Movies",
ExpressionAttributeNames = new Dictionary<string, string>
{
{ "#yr", "year" }
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":y_a", new AttributeValue { N = "1960" } },
{ ":y_z", new AttributeValue { N = "1969" } },

API Version 2012-08-10


155
Amazon DynamoDB Developer Guide
Step 10: Delete the Table

},
FilterExpression = "#yr between :y_a and :y_z",
ProjectionExpression = "#yr, title, info.actors[0], info.directors,
info.running_time_secs"
};

It then waits on the ClientScanning_async function implemented in the 09_Scanninging.cs


file. ClientScanning_async waits in turn on the low-level DynamoDB method
AmazonDynamoDBClient.ScanAsync to retrieve the query results.
Note
Because "year" is a reserved word in DynamoDB, you must create an alias for it (here #yr) using
ExpressionAttributeNames in order to use it in a low-level expression.

Next Step
Step 10: Delete the Movies Table with .NET (p. 156)

Step 10: Delete the Movies Table with .NET


In this step of the Microsoft .NET and DynamoDB Tutorial (p. 135), you delete the Movies table in
Amazon DynamoDB.

The Main function in DynamoDB_intro waits on DeletingTable_async, which is implemented in the


10_DeletingTable.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/
*
* 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;

Console.WriteLine( " -- Trying to delete the table named \"{0}\"...", tableName );


pause( );
Task tblDelete = client.DeleteTableAsync( tableName );
try
{
await tblDelete;
}

API Version 2012-08-10


156
Amazon DynamoDB Developer Guide
PHP and DynamoDB

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 );
}
}

DeletingTable_async waits on the low-level DynamoDB method


AmazonDynamoDBClient.DeleteTableAsync to delete the table.

For More Information


• To learn more about reading and writing data in DynamoDB tables, see Working with Items and
Attributes (p. 375).
• For more information about the DynamoDB document model API, see .NET: Document
Model (p. 276).
• For more information about asynchronous methods, see AWS Asynchronous APIs for .NET.

PHP and DynamoDB


In this tutorial, you use the AWS SDK for PHP to write simple programs to perform the following Amazon
DynamoDB operations:

• 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.

API Version 2012-08-10


157
Amazon DynamoDB Developer Guide
Step 1: Create a Table

Step 1: Create a Table


In this step, you create a table named Movies. The primary key for the table is composed of the
following two attributes:

• year – The partition key. The AttributeType is N for number.


• title – The sort key. The AttributeType is S for string.

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$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'
],

],

API Version 2012-08-10


158
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

'ProvisionedThroughput' => [
'ReadCapacityUnits' => 10,
'WriteCapacityUnits' => 10
]
];

try {
$result = $dynamodb->createTable($params);
echo 'Created table. Status: ' .
$result['TableDescription']['TableStatus'] ."\n";

} catch (DynamoDbException $e) {


echo "Unable to create table:\n";
echo $e->getMessage() . "\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).

Step 2: Load Sample Data


In this step, you populate the Movies table with sample data.

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" : { ... }
},

...

API Version 2012-08-10


159
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

In the JSON data, note the following:

• 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.

The following is an example of movie data.

{
"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.1: Download the Sample Data File


1. Download the sample data archive: moviedata.zip
2. Extract the data file (moviedata.json) from the archive.
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.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

API Version 2012-08-10


160
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

*
* 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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();

$tableName = 'Movies';

$movies = json_decode(file_get_contents('moviedata.json'), true);

foreach ($movies as $movie) {

$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.

API Version 2012-08-10


161
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

php MoviesLoadData.php

Step 3: Create, Read, Update, and Delete an Item


In this step, you perform read and write operations on an item in the Movies table.

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)

Step 3.1: Create a New Item


In this step, you add a new item to the Movies table.

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();

$tableName = 'Movies';

$year = 2015;
$title = 'The Big New Movie';

API Version 2012-08-10


162
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

$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";

} catch (DynamoDbException $e) {


echo "Unable to add item:\n";
echo $e->getMessage() . "\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

Step 3.2: Read an Item


In the previous program, you added the following item to the table.

{
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.
*

API Version 2012-08-10


163
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

* 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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$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"]);

} catch (DynamoDbException $e) {


echo "Unable to get item:\n";
echo $e->getMessage() . "\n";
}

2. To run the program, enter the following command.

php MoviesItemOps02.php

API Version 2012-08-10


164
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

Step 3.3: Update an Item


You can use the updateItem method to modify an existing item. You can update values of existing
attributes, add new attributes, or remove attributes.

In this example, you perform the following updates:

• Change the value of the existing attributes (rating, plot).


• Add a new list attribute (actors) to the existing info map.

The following shows the existing item.

{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}

The item is updated as follows.

{
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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',

API Version 2012-08-10


165
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

'version' => 'latest'


]);

$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']);

} catch (DynamoDbException $e) {


echo "Unable to update item:\n";
echo $e->getMessage() . "\n";
}

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

API Version 2012-08-10


166
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

Step 3.4: Increment an Atomic Counter


DynamoDB supports atomic counters, which use the updateItem method to increment or decrement
the value of an existing attribute without interfering with other write requests. (All write requests are
applied in the order in which they are received.)

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$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',

API Version 2012-08-10


167
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

'ExpressionAttributeValues'=> $eav,
'ReturnValues' => 'UPDATED_NEW'
];

try {
$result = $dynamodb->updateItem($params);
echo "Updated item. ReturnValues are:\n";
print_r($result['Attributes']);

} catch (DynamoDbException $e) {


echo "Unable to update item:\n";
echo $e->getMessage() . "\n";
}

2. To run the program, enter the following command.

php MoviesItemOps04.php

Step 3.5: Update an Item (Conditionally)


The following program shows how to use UpdateItem with a condition. If the condition evaluates to
true, the update succeeds; otherwise, the update is not performed.

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();

$tableName = 'Movies';

API Version 2012-08-10


168
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

$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']);

} catch (DynamoDbException $e) {


echo "Unable to update item:\n";
echo $e->getMessage() . "\n";
}

2. To run the program, enter the following command.

php MoviesItemOps05.php

The program should fail with the following message.

The conditional request failed

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.

ConditionExpression="size(info.actors) >= :num",

The condition is now greater than or equal to 3 instead of greater than 3.


4. Run the program again. The UpdateItem operation should now succeed.

Step 3.6: Delete an Item


You can use the deleteItem method to delete one item by specifying its primary key. You can
optionally provide a ConditionExpression to prevent the item from being deleted if the condition is
not met.
API Version 2012-08-10
169
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$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";

} catch (DynamoDbException $e) {

API Version 2012-08-10


170
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

echo "Unable to delete item:\n";


echo $e->getMessage() . "\n";
}

2. To run the program, enter the following command.

php MoviesItemOps06.php

The program should fail with the following message.

The conditional request failed

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.

Step 4: Query and Scan the Data


You can use the query method to retrieve data from a table. You must specify a partition key value. The
sort key is optional.

The primary key for the Movies table is composed of the following:

• year – The partition key. The attribute type is number. 


• title – The sort key. The attribute type is string.

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)

Step 4.1: Query - All Movies Released in a Year


The program included in this step retrieves all movies released in the year 1985.

1. Copy the following program and paste it into a file named MoviesQuery01.php.

API Version 2012-08-10


171
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

/**
* 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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();

$tableName = 'Movies';

$eav = $marshaler->marshalJson('
{
":yyyy": 1985
}
');

$params = [
'TableName' => $tableName,
'KeyConditionExpression' => '#yr = :yyyy',
'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
'ExpressionAttributeValues'=> $eav
];

echo "Querying for movies from 1985.\n";

try {
$result = $dynamodb->query($params);

echo "Query succeeded.\n";

foreach ($result['Items'] as $movie) {


echo $marshaler->unmarshalValue($movie['year']) . ': ' .
$marshaler->unmarshalValue($movie['title']) . "\n";
}

} catch (DynamoDbException $e) {


echo "Unable to query:\n";
echo $e->getMessage() . "\n";
}

API Version 2012-08-10


172
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

Note

• ExpressionAttributeNames provides name substitution. We use this because year


is a reserved word in DynamoDB—you can't use it directly in any expression, including
KeyConditionExpression. You can use the expression attribute name #yr to address
this.
• ExpressionAttributeValues provides value substitution. You use this because you
can't use literals in any expression, including KeyConditionExpression. You can use
the expression attribute value :yyyy to address this.
2. To run the program, enter the following command:

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

Step 4.2: Query - All Movies Released in a Year with Certain


Titles
The program included in this step retrieves all movies released in year 1992 with title beginning with
the letter "A" through the letter "L".

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();

API Version 2012-08-10


173
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

$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);

echo "Query succeeded.\n";

foreach ($result['Items'] as $i) {


$movie = $marshaler->unmarshalItem($i);
print $movie['year'] . ': ' . $movie['title'] . ' ... ';

foreach ($movie['info']['genres'] as $gen) {


print $gen . ' ';
}

echo ' ... ' . $movie['info']['actors'][0] . "\n";


}

} catch (DynamoDbException $e) {


echo "Unable to query:\n";
echo $e->getMessage() . "\n";
}

2. To run the program, enter the following command.

php MoviesQuery02.php

Step 4.3: Scan


The scan method reads every item in the entire table, and returns all of the data in the table. You can
provide an optional filter_expression so that only the items matching your criteria are returned.
However, the filter is applied only after the entire table has been scanned.

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.

API Version 2012-08-10


174
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

/**
* 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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

$marshaler = new Marshaler();

//Expression attribute values


$eav = $marshaler->marshalJson('
{
":start_yr": 1950,
":end_yr": 1959
}
');

$params = [
'TableName' => 'Movies',
'ProjectionExpression' => '#yr, title, info.rating',
'FilterExpression' => '#yr between :start_yr and :end_yr',
'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
'ExpressionAttributeValues'=> $eav
];

echo "Scanning Movies table.\n";

try {
while (true) {
$result = $dynamodb->scan($params);

foreach ($result['Items'] as $i) {


$movie = $marshaler->unmarshalItem($i);
echo $movie['year'] . ': ' . $movie['title'];
echo ' ... ' . $movie['info']['rating']
. "\n";
}

if (isset($result['LastEvaluatedKey'])) {
$params['ExclusiveStartKey'] = $result['LastEvaluatedKey'];
} else {

API Version 2012-08-10


175
Amazon DynamoDB Developer Guide
Step 5: (Optional) Delete the Table

break;
}
}

} catch (DynamoDbException $e) {


echo "Unable to scan:\n";
echo $e->getMessage() . "\n";
}

In the code, note the following:

• ProjectionExpression specifies the attributes you want in the scan result.


• FilterExpression specifies a condition that returns only items that satisfy the condition. All
other items are discarded.
2. To run the program, enter the following command.

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

Step 5: (Optional) Delete the Table


To delete the Movies table:

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;

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

API Version 2012-08-10


176
Amazon DynamoDB Developer Guide
Summary

$params = [
'TableName' => 'Movies'
];

try {
$result = $dynamodb->deleteTable($params);
echo "Deleted table.\n";

} catch (DynamoDbException $e) {


echo "Unable to delete table:\n";
echo $e->getMessage() . "\n";
}

2. To run the program, enter the following command.

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.

Modifying the Code to Use the DynamoDB Service


To use the DynamoDB web service, you must change the endpoint in your application. To do this, find
the following lines in the code.

$sdk = new Aws\Sdk([


'endpoint' => 'http://localhost:8000',
'region' => 'us-west-2',
'version' => 'latest'
]);

Remove the endpoint parameter so that the code looks like the following.

$sdk = new Aws\Sdk([


'region' => 'us-west-2',
'version' => 'latest'
]);

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.

'region' => 'us-west-2',

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.

API Version 2012-08-10


177
Amazon DynamoDB Developer Guide
Python and DynamoDB

Getting Started Developing with Python and


DynamoDB
In this tutorial, you use the AWS SDK for Python (Boto 3) to write simple programs to perform the
following Amazon DynamoDB operations:

• 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.

Step 1: Create a Table with Python


In this step, you create a table named Movies. The primary key for the table is composed of the
following attributes:

• year – The partition key. The AttributeType is N for number.


• title – The sort key. The AttributeType is S for string.

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

API Version 2012-08-10


178
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

# specific language governing permissions and limitations under the License.


#
from __future__ import print_function # Python 2/3 compatibility
import boto3

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

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

print("Table status:", table.table_status)

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

Step 2: Load Sample Data


In this step, you populate the Movies table with sample data.

API Version 2012-08-10


179
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

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" : { ... }
},

...

In the JSON data, note the following:

• 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.

The following is an example of movie data.

{
"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"
]
}
}

API Version 2012-08-10


180
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

Step 2.1: Download the Sample Data File


1. Download the sample data archive: moviedata.zip
2. Extract the data file (moviedata.json) from the archive.
3. Copy 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.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

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

with open("moviedata.json") as json_file:


movies = json.load(json_file, parse_float = decimal.Decimal)
for movie in movies:
year = int(movie['year'])
title = movie['title']
info = movie['info']

print("Adding movie:", year, title)

table.put_item(
Item={
'year': year,
'title': title,
'info': info,
}
)

2. To run the program, enter the following command.

python MoviesLoadData.py

API Version 2012-08-10


181
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

Step 3: Create, Read, Update, and Delete an Item


with Python
In this step, you perform read and write operations on an item in the Movies table.

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)

Step 3.1: Create a New Item


In this step, you add a new item to the Movies table.

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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if abs(o) % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

title = "The Big New Movie"


year = 2015

API Version 2012-08-10


182
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

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

Step 3.2: Read an Item


In the previous program, you added the following item to the table.

{
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

API Version 2012-08-10


183
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

import json
import decimal
from boto3.dynamodb.conditions import Key, Attr
from botocore.exceptions import ClientError

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource("dynamodb", region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

title = "The Big New Movie"


year = 2015

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

2. To run the program, enter the following command.

python MoviesItemOps02.py

Step 3.3: Update an Item


You can use the update_item method to modify an existing item. You can update values of existing
attributes, add new attributes, or remove attributes.

In this example, you perform the following updates:

• Change the value of the existing attributes (rating, plot).


• Add a new list attribute (actors) to the existing info map.

The following shows the existing item.

{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}

API Version 2012-08-10


184
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

The item is updated as follows.

{
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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

title = "The Big New Movie"


year = 2015

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

API Version 2012-08-10


185
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

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

Step 3.4: Increment an Atomic Counter


DynamoDB supports atomic counters, which use the update_item method to increment or decrement
the value of an existing attribute without interfering with other write requests. (All write requests are
applied in the order in which they are received.)

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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

title = "The Big New Movie"


year = 2015

API Version 2012-08-10


186
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

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

2. To run the program, enter the following command.

python MoviesItemOps04.py

Step 3.5: Update an Item (Conditionally)


The following program shows how to use UpdateItem with a condition. If the condition evaluates to
true, the update succeeds; otherwise, the update is not performed.

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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

API Version 2012-08-10


187
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

title = "The Big New Movie"


year = 2015

# Conditional update (will fail)


print("Attempting conditional update...")

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

2. To run the program, enter the following command.

python MoviesItemOps05.py

The program should fail with the following message.

The conditional request failed

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.

ConditionExpression="size(info.actors) >= :num",

The condition is now greater than or equal to 3 instead of greater than 3.


4. Run the program again. The UpdateItem operation should now succeed.

Step 3.6: Delete an Item


You can use the delete_item method to delete one item by specifying its primary key. Optionally, you
can provide a ConditionExpression to prevent the item from being deleted if the condition is not
met.

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.
#

API Version 2012-08-10


188
Amazon DynamoDB Developer Guide
Step 3: Crud Operations

# 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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

title = "The Big New Movie"


year = 2015

print("Attempting a conditional delete...")

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

2. To run the program, enter the following command.

python MoviesItemOps06.py

The program should fail with the following message.

The conditional request failed

The program fails because the rating for this particular move is greater than 5.

API Version 2012-08-10


189
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

3. Modify the program to remove the condition in table.delete_item.

response = table.delete_item(
Key={
'year': year,
'title': title
}
)

4. Run the program. Now, the delete succeeds because you removed the condition.

Step 4: Query and Scan the Data


You can use the query method to retrieve data from a table. You must specify a partition key value. The
sort key is optional.

The primary key for the Movies table is composed of the following:

• year – The partition key. The attribute type is number. 


• title – The sort key. The attribute type is string.

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)

Step 4.1: Query - All Movies Released in a Year


The program included in this step retrieves all movies released in the year 1985.

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

API Version 2012-08-10


190
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

import json
import decimal
from boto3.dynamodb.conditions import Key, Attr

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

print("Movies from 1985")

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

Step 4.2: Query - All Movies Released in a Year with Certain


Titles
The program included in this step retrieves all movies released in year 1992 with title beginning with
the letter "A" through the letter "L".

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").

API Version 2012-08-10


191
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

# 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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

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

2. To run the program, enter the following command.

python MoviesQuery02.py

Step 4.3: Scan


The scan method reads every item in the entire table and returns all the data in the table. You can
provide an optional filter_expression so that only the items matching your criteria are returned.
However, the filter is applied only after the entire table has been scanned.

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

API Version 2012-08-10


192
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

#
# 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

# Helper class to convert a DynamoDB item to JSON.


class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
if o % 1 > 0:
return float(o)
else:
return int(o)
return super(DecimalEncoder, self).default(o)

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

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

while 'LastEvaluatedKey' in response:


response = table.scan(
ProjectionExpression=pe,
FilterExpression=fe,
ExpressionAttributeNames= ean,
ExclusiveStartKey=response['LastEvaluatedKey']
)

for i in response['Items']:
print(json.dumps(i, cls=DecimalEncoder))

In the code, note the following:

• ProjectionExpression specifies the attributes you want in the scan result.


• FilterExpression specifies a condition that returns only items that satisfy the condition. All
other items are discarded.
• The scan method returns a subset of the items each time, called a page. The LastEvaluatedKey
value in the response is then passed to the scan method via the ExclusiveStartKey
parameter. When the last page is returned, LastEvaluatedKey is not part of the response.

API Version 2012-08-10


193
Amazon DynamoDB Developer Guide
Step 5: (Optional) Delete the Table

Note

• ExpressionAttributeNames provides name substitution. We use this because year


is a reserved word in DynamoDB—you can't use it directly in any expression, including
KeyConditionExpression. You can use the expression attribute name #yr to address
this.
• ExpressionAttributeValues provides value substitution. You use this because you
can't use literals in any expression, including KeyConditionExpression. You can use
the expression attribute value :yyyy to address this.
2. To run the program, enter the following command.

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

Step 5: (Optional) Delete the Table


To delete the Movies table:

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

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://


localhost:8000")

table = dynamodb.Table('Movies')

table.delete()

2. To run the program, enter the following command.

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

API Version 2012-08-10


194
Amazon DynamoDB Developer Guide
Ruby and DynamoDB

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.

Modifying the Code to Use the DynamoDB Service


To use the DynamoDB web service, you must change the endpoint in your application. To do this, modify
the following line.

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.

Ruby and DynamoDB


In this tutorial, you use the AWS SDK for Ruby to write simple programs to perform the following
Amazon DynamoDB operations:

• 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.

API Version 2012-08-10


195
Amazon DynamoDB Developer Guide
Step 1: Create a Table

Step 1: Create a Table


In this step, you create a table named Movies in Amazon DynamoDB. The primary key for the table is
composed of the following two attributes:

• year – The partition key. The attribute_type is N for number. 


• title – The sort key. The attribute_type is S for string.

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
}
}

API Version 2012-08-10


196
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

begin
result = dynamodb.create_table(params)
puts "Created table. Status: " +
result.table_description.table_status;

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to create table:"
puts "#{error.message}"
end

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

Step 2: Load Sample Data


In this step, you populate the Movies table in Amazon DynamoDB with sample data.

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" : { ... }
},

...

In the JSON data, note the following:

• The year and title are used as the primary key attribute values for the Movies table.

API Version 2012-08-10


197
Amazon DynamoDB Developer Guide
Step 2: Load Sample Data

• 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.

The following is an example of movie data.

{
"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.1: Download the Sample Data File


1. Download the sample data archive: moviedata.zip
2. Extract the data file (moviedata.json) from the archive.
3. Copy the moviedata.json file and paste it into your current directory.

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.
#

API Version 2012-08-10


198
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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"]}"

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to add movie:"
puts "#{error.message}"
end
}

2. To run the program, enter the following command.

ruby MoviesLoadData.rb

Step 3: Create, Read, Update, and Delete an Item


In this step, you perform read and write operations on an item in the Movies table in Amazon
DynamoDB.

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)

Step 3.1: Create a New Item


In this step, you add a new item to the table.

1. Copy the following program and paste it into a file named MoviesItemOps01.rb.

API Version 2012-08-10


199
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

#
# 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}"

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to add item:"
puts "#{error.message}"
end

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

Step 3.2: Read an Item


In the previous program, you added the following item to the table.

API Version 2012-08-10


200
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

{
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"]

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to read item:"
puts "#{error.message}"
end

API Version 2012-08-10


201
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

2. To run the program, enter the following command.

ruby MoviesItemOps02.rb

Step 3.3: Update an Item


You can use the update_item method to modify an existing item. You can update values of existing
attributes, add new attributes, or remove attributes.

In this example, you perform the following updates:

• Change the value of the existing attributes (rating, plot).


• Add a new list attribute (actors) to the existing info map.

The following shows the existing item.

{
year: 2015,
title: "The Big New Movie",
info: {
plot: "Nothing happens at all.",
rating: 0
}
}

The item is updated as follows.

{
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"

API Version 2012-08-10


202
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

})

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}"

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to add item:"
puts "#{error.message}"
end

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

Step 3.4: Increment an Atomic Counter


DynamoDB supports atomic counters, which use the update_item method to increment or decrement
the value of an existing attribute without interfering with other write requests. (All write requests are
applied in the order in which they are received.)

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

API Version 2012-08-10


203
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

#
# 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

2. To run the program, enter the following command.

ruby MoviesItemOps04.rb

Step 3.5: Update an Item (Conditionally)


The following program shows how to use update_item with a condition. If the condition evaluates to
true, the update succeeds; otherwise, the update is not performed.

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.

API Version 2012-08-10


204
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

#
# 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

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to update item:"
puts "#{error.message}"
end

2. To run the program, enter the following command.

ruby MoviesItemOps05.rb

The program should fail with the following message.

The conditional request failed

API Version 2012-08-10


205
Amazon DynamoDB Developer Guide
Step 3: Create, Read, Update, and Delete an Item

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.

condition_expression: "size(info.actors) >= :num",

The condition is now greater than or equal to 3 instead of greater than 3.


4. Run the program again. The update_item method should now succeed.

Step 3.6: Delete an Item


You can use the delete_item method to delete one item by specifying its primary key. You can
optionally provide a condition_expression to prevent the item from being deleted if the condition is
not met.

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
}
}

API Version 2012-08-10


206
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

begin
dynamodb.delete_item(params)
puts "Deleted item."

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to update item:"
puts "#{error.message}"
end

2. To run the program, enter the following command.

ruby MoviesItemOps06.rb

The program should fail with the following message.

The conditional request failed

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.

Step 4: Query and Scan the Data


You can use the query method to retrieve data from a table. You must specify a partition key value. The
sort key is optional.

The primary key for the Movies table is composed of the following:

• year – The partition key. The attribute type is number. 


• title – The sort key. The attribute type is string.

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)

Step 4.1: Query - All Movies Released in a Year


The following program retrieves all movies released in the year 1985.

API Version 2012-08-10


207
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

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
}
}

puts "Querying for movies from 1985.";

begin
result = dynamodb.query(params)
puts "Query succeeded."

result.items.each{|movie|
puts "#{movie["year"].to_i} #{movie["title"]}"
}

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to query table:"
puts "#{error.message}"
end

Note

• expression_attribute_names provides name substitution. We use this because year


is a reserved word in Amazon DynamoDB. You can't use it directly in any expression,
including KeyConditionExpression. You can use the expression attribute name #yr to
address this.
• expression_attribute_values provides value substitution. You use this because you
can't use literals in any expression, including key_condition_expression. You can use
the expression attribute value :yyyy to address this.

API Version 2012-08-10


208
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

2. To run the program, enter the following command.

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

Step 4.2: Query - All Movies Released in a Year with Certain


Titles
The following program retrieves all movies released in year 1992 with a title beginning with the
letter "A" through the letter "L".

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";

API Version 2012-08-10


209
Amazon DynamoDB Developer Guide
Step 4: Query and Scan the Data

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 + " "
}

print " ... #{movie["info"]["actors"][0]}\n"


}

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to query table:"
puts "#{error.message}"
end

2. To run the program, enter the following command.

ruby MoviesQuery02.rb

Step 4.3: Scan


The scan method reads every item in the entire table and returns all the data in the table. You can
provide an optional filter_expression so that only the items matching your criteria are returned.
However, note that the filter is only applied after the entire table has been scanned.

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,

API Version 2012-08-10


210
Amazon DynamoDB Developer Guide
Step 5: (Optional) Delete the Table

projection_expression: "#yr, title, info.rating",


filter_expression: "#yr between :start_yr and :end_yr",
expression_attribute_names: {"#yr"=> "year"},
expression_attribute_values: {
":start_yr" => 1950,
":end_yr" => 1959
}
}

puts "Scanning Movies table."

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?

puts "Scanning for more..."


params[:exclusive_start_key] = result.last_evaluated_key
end

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to scan:"
puts "#{error.message}"
end

In the code, note the following:

• projection_expression specifies the attributes you want in the scan result.


• filter_expression specifies a condition that returns only items that satisfy the condition. All
other items are discarded.
2. To run the program, enter the following command.

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

Step 5: (Optional) Delete the Table


Follow these steps to delete the Movies table.

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/

API Version 2012-08-10


211
Amazon DynamoDB Developer Guide
Summary

#
# 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."

rescue Aws::DynamoDB::Errors::ServiceError => error


puts "Unable to delete table:"
puts "#{error.message}"
end

2. To run the program, enter the following command.

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.

Modifying the Code to Use the DynamoDB Service


To use the DynamoDB service, you must change the endpoint in your application. To do this, find the
following lines in the code.

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.

API Version 2012-08-10


212
Amazon DynamoDB Developer Guide
Summary

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.

API Version 2012-08-10


213
Amazon DynamoDB Developer Guide
Overview of AWS SDK Support for DynamoDB

Programming with DynamoDB and


the AWS SDKs
This section covers developer-related topics. If you want to run code examples instead, see Running the
Code Examples in This Developer Guide (p. 325).
Note
In December 2017, AWS began the process of migrating all Amazon DynamoDB endpoints
to use secure certificates issued by Amazon Trust Services (ATS). For more information, see
Troubleshooting SSL/TLS connection establishment issues (p. 970).

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)

Overview of AWS SDK Support for DynamoDB


The following diagram provides a high-level overview of Amazon DynamoDB application programming
using the AWS SDKs.

API Version 2012-08-10


214
Amazon DynamoDB Developer Guide
Overview of AWS SDK Support for DynamoDB

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:

• Formatting HTTP(S) requests and serializing request parameters.


• Generating a cryptographic signature for each request.
• Forwarding requests to a DynamoDB endpoint and receiving responses from DynamoDB.

API Version 2012-08-10


215
Amazon DynamoDB Developer Guide
Programmatic Interfaces

• Extracting the results from those responses.


• Implementing basic retry logic in case of errors.

You do not need to write code for any of these tasks.


Note
For more information about AWS SDKs, including installation instructions and documentation,
see Tools for Amazon Web Services.

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

API Version 2012-08-10


216
Amazon DynamoDB Developer Guide
Low-Level Interfaces

• Low-Level Interfaces (p. 217)


• Document Interfaces (p. 218)
• Object Persistence Interface (p. 218)

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.

The com.amazonaws.services.dynamodbv2.AmazonDynamoDB class implements the DynamoDB


low-level interface.

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;

public class MusicLowLevelDemo {

public static void main(String[] args) {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

HashMap<String, AttributeValue> key = new HashMap<String, AttributeValue>();


key.put("Artist", new AttributeValue().withS("No One You Know"));
key.put("SongTitle", new AttributeValue().withS("Call Me Today"));

GetItemRequest request = new GetItemRequest()


.withTableName("Music")
.withKey(key);

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

API Version 2012-08-10


217
Amazon DynamoDB Developer Guide
Document Interfaces

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.

The com.amazonaws.services.dynamodbv2.document.DynamoDB class implements the


DynamoDB document interface. Note how DynamoDB acts as a wrapper around the low-level client
(AmazonDynamoDB).

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;

public class MusicDocumentDemo {

public static void main(String[] args) {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB docClient = new DynamoDB(client);

Table table = docClient.getTable("Music");


GetItemOutcome outcome = table.getItemOutcome(
"Artist", "No One You Know",
"SongTitle", "Call Me Today");

int year = outcome.getItem().getInt("Year");


System.out.println("The song was released in " + year);

}
}

Object Persistence Interface


Some AWS SDKs provide an object persistence interface where you do not directly perform data plane
operations. Instead, you create objects that represent items in Amazon DynamoDB tables and indexes,
and interact only with those objects. This allows you to write object-centric code, rather than database-
centric code.
Note
Object persistence interfaces are available in the AWS SDKs for Java and .NET. For more
information, see Higher-Level Programming Interfaces for DynamoDB (p. 229).

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;

API Version 2012-08-10


218
Amazon DynamoDB Developer Guide
Object Persistence Interface

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.

The com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper class implements


the DynamoDB object persistence interface. Note how DynamoDBMapper acts as a wrapper around the
low-level client (AmazonDynamoDB).

package com.amazonaws.codesamples;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;

public class MusicMapperDemo {

public static void main(String[] args) {

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

DynamoDBMapper mapper = new DynamoDBMapper(client);

MusicItem keySchema = new MusicItem();


keySchema.setArtist("No One You Know");
keySchema.setSongTitle("Call Me Today");

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");
}

API Version 2012-08-10


219
Amazon DynamoDB Developer Guide
Low-Level API

} catch (Exception e) {
System.err.println("Unable to retrieve data: ");
System.err.println(e.getMessage());
}

DynamoDB Low-Level API


Topics
• Request Format (p. 221)
• Response Format (p. 222)
• Data Type Descriptors (p. 222)
• Numeric Data (p. 223)
• Binary Data (p. 223)

API Version 2012-08-10


220
Amazon DynamoDB Developer Guide
Request Format

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"}
}
}

Note the following about this request:

• 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.

API Version 2012-08-10


221
Amazon DynamoDB Developer Guide
Response Format

• 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).

Data Type Descriptors


The low-level DynamoDB API protocol requires each attribute to be accompanied by a data type
descriptor. Data type descriptors are tokens that tell DynamoDB how to interpret each attribute.

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

API Version 2012-08-10


222
Amazon DynamoDB Developer Guide
Numeric Data

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

The following is a complete list of DynamoDB data type descriptors:

• 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.

Error Handling with DynamoDB


This section describes runtime errors and how to handle them. It also describes error messages and codes
that are specific to Amazon DynamoDB.

Topics

API Version 2012-08-10


223
Amazon DynamoDB Developer Guide
Error Components

• Error Components (p. 224)


• Error Messages and Codes (p. 224)
• Error Handling in Your Application (p. 227)
• Error Retries and Exponential Backoff (p. 228)
• Batch Operations and Error Handling (p. 228)

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:

• An HTTP status code (such as 400).


• An exception name (such as ResourceNotFoundException).
• An error message (such as Requested resource not found: Table: tablename not found).

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.

HTTP/1.1 400 Bad Request


x-amzn-RequestId: LDM6CJP8RMQ1FHKSC1RBVJFPNVV4KQNSO5AEMF66Q9ASUAAJG
Content-Type: application/x-amz-json-1.0
Content-Length: 240
Date: Thu, 15 Mar 2012 23:56:23 GMT

{"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException",
"message":"Requested resource not found: Table: tablename not found"}

Error Messages and Codes


The following is a list of exceptions returned by DynamoDB, grouped by HTTP status code. If OK to retry?
is Yes, you can submit the same request again. If OK to retry? is No, you need to fix the problem on the
client side before you submit a new request.

HTTP Status Code 400


An HTTP 400 status code indicates a problem with your request, such as authentication failure, missing
required parameters, or exceeding a table's provisioned throughput. You have to fix the issue in your
application before submitting the request again.

AccessDeniedException

Message: Access denied.

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

API Version 2012-08-10


224
Amazon DynamoDB Developer Guide
Error Messages and Codes

ConditionalCheckFailedException

Message: The conditional request failed.

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

Message: The request signature does not conform to AWS standards.

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

Message: Collection size exceeded.

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

Message: Too many operations for a given subscriber.

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

API Version 2012-08-10


225
Amazon DynamoDB Developer Guide
Error Messages and Codes

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.

Example: Rate of on-demand requests exceeds the allowed account throughput.

OK to retry? Yes

ResourceInUseException

Message: The resource which you are attempting to change is in use.

Example: You tried to re-create an existing table, or delete a table currently in the CREATING state.

OK to retry? No

ResourceNotFoundException

Message: Requested resource not found.

Example: The table that is being requested does not exist, or is too early in the CREATING state.

OK to retry? No

ThrottlingException

Message: Rate of requests exceeds the allowed throughput.

This exception might be returned if you perform any of the following operations too rapidly:
CreateTable, UpdateTable, DeleteTable.

OK to retry? Yes

UnrecognizedClientException

Message: The Access Key ID or security token is invalid.

The request signature is incorrect. The most likely cause is an invalid AWS access key ID or secret key.

OK to retry? Yes

ValidationException

Message: Varies, depending upon the specific error(s) encountered

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

HTTP Status Code 5xx


An HTTP 5xx status code indicates a problem that must be resolved by AWS. This might be a transient
error, in which case you can retry your request until it succeeds. Otherwise, go to the AWS Service Health
Dashboard to see if there are any operational issues with the service.

API Version 2012-08-10


226
Amazon DynamoDB Developer Guide
Error Handling in Your Application

Internal Server Error (HTTP 500)

DynamoDB could not process your request.

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.

Service Unavailable (HTTP 503)

DynamoDB is currently unavailable. (This should be a temporary state.)

OK to retry? Yes

Error Handling in Your Application


For your application to run smoothly, you need to add logic to catch and respond to errors. Typical
approaches include using try-catch blocks or if-then statements.

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

Table table = dynamoDB.getTable("Movies");

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");
}

} catch (AmazonServiceException ase) {


System.err.println("Could not complete operation");
System.err.println("Error Message: " + ase.getMessage());
System.err.println("HTTP Status: " + ase.getStatusCode());
System.err.println("AWS Error Code: " + ase.getErrorCode());
System.err.println("Error Type: " + ase.getErrorType());
System.err.println("Request ID: " + ase.getRequestId());

} catch (AmazonClientException ace) {


System.err.println("Internal error occurred communicating with DynamoDB");
System.out.println("Error Message: " + ace.getMessage());
}

In this code example, the try-catch construct handles two different kinds of exceptions:

• AmazonServiceException—Thrown if the client request was correctly transmitted to DynamoDB,


but DynamoDB could not process the request and returned an error response instead.
• AmazonClientException—Thrown if the client could not get a response from a service, or if the
client could not parse the response from a service.

API Version 2012-08-10


227
Amazon DynamoDB Developer Guide
Error Retries and Exponential Backoff

Error Retries and Exponential Backoff


Numerous components on a network, such as DNS servers, switches, load balancers, and others, can
generate errors anywhere in the life of a given request. The usual technique for dealing with these error
responses in a networked environment is to implement retries in the client application. This technique
increases the reliability of the application.

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.

Batch Operations and Error Handling


The DynamoDB low-level API supports batch operations for reads and writes. BatchGetItem reads
items from one or more tables, and BatchWriteItem puts or deletes items in one or more tables. These
batch operations are implemented as wrappers around other non-batch DynamoDB operations. In other
words, BatchGetItem invokes GetItem once for each item in the batch. Similarly,BatchWriteItem
invokes DeleteItem or PutItem, as appropriate, for each item in the batch.

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

API Version 2012-08-10


228
Amazon DynamoDB Developer Guide
Higher-Level Programming Interfaces for DynamoDB

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.

Higher-Level Programming Interfaces for


DynamoDB
The AWS SDKs provide applications with low-level interfaces for working with Amazon DynamoDB.
These client-side classes and methods correspond directly to the low-level DynamoDB API. However,
many developers experience a sense of disconnect, or impedance mismatch, when they need to map
complex data types to items in a database table. With a low-level database interface, developers must
write methods for reading or writing object data to database tables, and vice versa. The amount of extra
code required for each combination of object type and database table can seem overwhelming.

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

• Java: DynamoDBMapper (p. 229)

.NET

• .NET: Document Model (p. 276)


• .NET: Object Persistence Model (p. 297)

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

API Version 2012-08-10


229
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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 {

private Integer id;


private String title;
private String ISBN;
private Set<String> bookAuthors;
private String someProp;

@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.

API Version 2012-08-10


230
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

DynamoDBMapper mapper = new DynamoDBMapper(client);

CatalogItem item = new CatalogItem();


item.setId(102);
item.setTitle("Book 102 Title");
item.setISBN("222-2222222222");
item.setBookAuthors(new HashSet<String>(Arrays.asList("Author 1", "Author 2")));
item.setSomeProp("Test");

mapper.save(item);

The following code example shows how to retrieve the item and access some of its attributes.

CatalogItem partitionKey = new CatalogItem();

partitionKey.setId(102);
DynamoDBQueryExpression<CatalogItem> queryExpression = new
DynamoDBQueryExpression<CatalogItem>()
.withHashKeyValues(partitionKey);

List<CatalogItem> itemList = mapper.query(CatalogItem.class, queryExpression);

for (int i = 0; i < itemList.size(); i++) {


System.out.println(itemList.get(i).getTitle());
System.out.println(itemList.get(i).getBookAuthors());
}

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.

Supported Data Types


This section describes the supported primitive Java data types, collections, and arbitrary data types in
Amazon DynamoDB.

API Version 2012-08-10


231
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

Java type DynamoDB type

All number types N (number type)

Strings S (string type)

Boolean BOOL (Boolean type), 0 or 1.

ByteBuffer B (binary type)

Date S (string type). The Date values are stored as


ISO-8601 formatted strings.

Set collection types SS (string set) type, NS (number set) type, or BS


(binary set) type.

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

Java Annotations for DynamoDB


This section describes the annotations that are available for mapping your classes and properties to
tables and attributes in Amazon DynamoDB.

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)

API Version 2012-08-10


232
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

• DynamoDBDocument (p. 234)


• DynamoDBHashKey (p. 235)
• DynamoDBIgnore (p. 235)
• DynamoDBIndexHashKey (p. 235)
• DynamoDBIndexRangeKey (p. 235)
• DynamoDBRangeKey (p. 235)
• DynamoDBTable (p. 236)
• DynamoDBTypeConverted (p. 236)
• DynamoDBTyped (p. 236)
• DynamoDBVersionAttribute (p. 237)

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.

The following example demonstrates using 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; }

public static void saveItem() {


AutoGeneratedKeys obj = new AutoGeneratedKeys();
obj.setPayload("abc123");

// id field is null at this point


DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
mapper.save(obj);

System.out.println("Object was saved with id " + obj.getId());


}
}

API Version 2012-08-10


233
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

public class ProductCatalogItem {

private Integer id; //partition key


private Pictures pictures;
/* ...other attributes omitted... */

@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;}

// Additional properties go here.

@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.

ProductCatalogItem item = new ProductCatalogItem();

Pictures pix = new Pictures();


pix.setFrontView("http://example.com/products/123_front.jpg");
pix.setRearView("http://example.com/products/123_rear.jpg");
pix.setSideView("http://example.com/products/123_left_side.jpg");
item.setPictures(pix);

item.setId(123);

mapper.save(item);

The resulting ProductCatalog item would look like the following (in JSON format).

{
"Id" : 123
"Pictures" : {

API Version 2012-08-10


234
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

"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.

API Version 2012-08-10


235
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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; }

// Additional properties go here.


}

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.

API Version 2012-08-10


236
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

API Version 2012-08-10


237
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

mapper.save(obj, new DynamoDBMapperConfig(DynamoDBMapperConfig.SaveBehavior.CLOBBER));

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.

CatalogItem item = mapper.load(CatalogItem.class, item.getId(),


new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT));

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.

Reply ( Id, ReplyDateTime, ... )

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

String forumName = "&DDB;";


String forumSubject = "&DDB; Thread 1";
String partitionKey = forumName + "#" + forumSubject;

long twoWeeksAgoMilli = (new Date()).getTime() - (14L*24L*60L*60L*1000L);


Date twoWeeksAgo = new Date();
twoWeeksAgo.setTime(twoWeeksAgoMilli);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String twoWeeksAgoStr = df.format(twoWeeksAgo);

API Version 2012-08-10


238
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();


eav.put(":v1", new AttributeValue().withS(partitionKey));
eav.put(":v2",new AttributeValue().withS(twoWeeksAgoStr.toString()));

DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>()


.withKeyConditionExpression("Id = :v1 and ReplyDateTime > :v2")
.withExpressionAttributeValues(eav);

List<Reply> latestReplies = mapper.query(Reply.class, queryExpression);

The query returns a collection of Reply objects.

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; }

// Additional properties go here.


}

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

HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>();


eav.put(":v1", new AttributeValue().withS("User A"));
eav.put(":v2", new AttributeValue().withS("DynamoDB"));

DynamoDBQueryExpression<PostedByMessage> queryExpression = new


DynamoDBQueryExpression<PostedByMessage>()
.withIndexName("PostedBy-Message-Index")
.withConsistentRead(false)
.withKeyConditionExpression("PostedBy = :v1 and begins_with(Message, :v2)")
.withExpressionAttributeValues(eav);

List<PostedByMessage> iList = mapper.query(PostedByMessage.class, queryExpression);

API Version 2012-08-10


239
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

The query returns a collection of PostedByMessage objects.

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.

Reply ( Id, ReplyDateTime, ... )

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

HashMap<String, AttributeValue> eav = new HashMap<String, AttributeValue>();


eav.put(":v1", new AttributeValue().withS("2015"));

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()


.withFilterExpression("begins_with(ReplyDateTime,:v1)")
.withExpressionAttributeValues(eav);

List<Reply> replies = mapper.scan(Reply.class, scanExpression);

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.

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()


.withIndexName("PostedBy-Message-Index")
.withConsistentRead(false);

List<PostedByMessage> iList = mapper.scan(PostedByMessage.class, scanExpression);


Iterator<PostedByMessage> indexItems = iList.iterator();

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.

API Version 2012-08-10


240
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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;

Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();


eav.put(":n", new AttributeValue().withN("100"));

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()


.withFilterExpression("Price <= :n")
.withExpressionAttributeValues(eav);

List<Product> scanResult = mapper.parallelScan(Product.class, scanExpression,


numberOfThreads);

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.

Book book1 = new Book();


book1.id = 901;
book1.productCategory = "Book";
book1.title = "Book 901 Title";

Book book2 = new Book();


book2.id = 902;
book2.productCategory = "Book";
book2.title = "Book 902 Title";

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.

ArrayList<Object> itemsToGet = new ArrayList<Object>();

ForumItem forumItem = new ForumItem();


forumItem.setForumName("Amazon DynamoDB");
itemsToGet.add(forumItem);

ThreadItem threadItem = new ThreadItem();


threadItem.setForumName("Amazon DynamoDB");
threadItem.setSubject("Amazon DynamoDB thread 1 message text");
itemsToGet.add(threadItem);

Map<String, List<Object>> items = mapper.batchLoad(itemsToGet);

API Version 2012-08-10


241
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

Book book1 = mapper.load(Book.class, 901);


Book book2 = mapper.load(Book.class, 902);
mapper.batchDelete(Arrays.asList(book1, book2));

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.

// Create a Forum item to save


Forum forumItem = new Forum();
forumItem.name = "Test BatchWrite Forum";

// Create a Thread item to save


Thread threadItem = new Thread();
threadItem.forumName = "AmazonDynamoDB";
threadItem.subject = "My sample question";

// Load a ProductCatalog item to delete


Book book3 = mapper.load(Book.class, 903);

List<Object> objectsToWrite = Arrays.asList(forumItem, threadItem);


List<Book> objectsToDelete = Arrays.asList(book3);

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 a list of transaction-specific exceptions, see TransactWriteItems errors.

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.

Thread s3ForumThread = new Thread();


s3ForumThread.forumName = "S3 Forum";
s3ForumThread.subject = "Sample Subject 1";
s3ForumThread.message = "Sample Question 1";

Forum s3Forum = new Forum();


s3Forum.name = "S3 Forum";

API Version 2012-08-10


242
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

s3Forum.category = "Amazon Web Services";


s3Forum.threads = 1;

TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();


transactionWriteRequest.addPut(s3Forum);
transactionWriteRequest.addPut(s3ForumThread);
mapper.transactionWrite(transactionWriteRequest);

transactionLoad
Loads objects from one or more tables using one call to the AmazonDynamoDB.transactGetItems
method.

For a list of transaction-specific exceptions, see TransactGetItems errors.

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.

Forum dynamodbForum = new Forum();


dynamodbForum.name = "DynamoDB Forum";
Thread dynamodbForumThread = new Thread();
dynamodbForumThread.forumName = "DynamoDB Forum";

TransactionLoadRequest transactionLoadRequest = new TransactionLoadRequest();


transactionLoadRequest.addLoad(dynamodbForum);
transactionLoadRequest.addLoad(dynamodbForumThread);
mapper.transactionLoad(transactionLoadRequest);

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 {

...

public S3Link productImage;

....

@DynamoDBAttribute(attributeName = "ProductImage")
public S3Link getProductImage() {
return productImage;
}

API Version 2012-08-10


243
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

public void setProductImage(S3Link productImage) {


this.productImage = 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.

CatalogItem item = new CatalogItem();

item.id = 150;
item.title = "Book 150 Title";

String myS3Bucket = "myS3bucket";


String myS3Key = "productImages/book_150_cover.jpg";
item.setProductImage(mapper.createS3Link(myS3Bucket, myS3Key));

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.

Optional Configuration Settings for DynamoDBMapper


When you create an instance of DynamoDBMapper, it has certain default behaviors; you can override
these defaults by using the DynamoDBMapperConfig class.

The following code snippet creates a DynamoDBMapper with custom settings:

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder()


.withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.CLOBBER)
.withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT)
.withTableNameOverride(null)

.withPaginationLoadingStrategy(DynamoDBMapperConfig.PaginationLoadingStrategy.EAGER_LOADING)
.build();

DynamoDBMapper mapper = new DynamoDBMapper(client, mapperConfig, cp);

For more information, see DynamoDBMapperConfig in the AWS SDK for Java API Reference.

You can use the following arguments for an instance of DynamoDBMapperConfig:

• A DynamoDBMapperConfig.ConsistentReads enumeration value:


• EVENTUAL—the mapper instance uses an eventually consistent read request.
• CONSISTENT—the mapper instance uses a strongly consistent read request. You can use this
optional setting with load, query, or scan operations. Strongly consistent reads have implications
for performance and billing; see the DynamoDB product detail page for more information.

API Version 2012-08-10


244
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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.

Example: CRUD Operations


The following Java code example declares a CatalogItem class that has Id, Title, ISBN, and Authors
properties. It uses the annotations to map these properties to the ProductCatalog table in DynamoDB.
The example then uses the DynamoDBMapper to save a book object, retrieve it, update it, and then
delete the book item.
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).

/**
* 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.

API Version 2012-08-10


245
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

*/

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;

public class DynamoDBMapperCRUDExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

public static void main(String[] args) throws IOException {


testCRUDOperations();
System.out.println("Example complete!");
}

@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;
}

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;
}

API Version 2012-08-10


246
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

public void setBookAuthors(Set<String> bookAuthors) {


this.bookAuthors = bookAuthors;
}

@Override
public String toString() {
return "Book [ISBN=" + ISBN + ", bookAuthors=" + bookAuthors + ", id=" + id +
", title=" + title + "]";
}
}

private static void testCRUDOperations() {

CatalogItem item = new CatalogItem();


item.setId(601);
item.setTitle("Book 601");
item.setISBN("611-1111111111");
item.setBookAuthors(new HashSet<String>(Arrays.asList("Author1", "Author2")));

// Save the item (book).


DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(item);

// Retrieve the item.


CatalogItem itemRetrieved = mapper.load(CatalogItem.class, 601);
System.out.println("Item retrieved:");
System.out.println(itemRetrieved);

// Update the item.


itemRetrieved.setISBN("622-2222222222");
itemRetrieved.setBookAuthors(new HashSet<String>(Arrays.asList("Author1",
"Author3")));
mapper.save(itemRetrieved);
System.out.println("Item updated:");
System.out.println(itemRetrieved);

// Retrieve the updated item.


DynamoDBMapperConfig config = DynamoDBMapperConfig.builder()
.withConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT)
.build();
CatalogItem updatedItem = mapper.load(CatalogItem.class, 601, config);
System.out.println("Retrieved the previously updated item:");
System.out.println(updatedItem);

// Delete the item.


mapper.delete(updatedItem);

// Try to retrieve deleted item.


CatalogItem deletedItem = mapper.load(CatalogItem.class, updatedItem.getId(),
config);
if (deletedItem == null) {
System.out.println("Done - Sample item is deleted.");
}
}
}

Example: Batch Write Operations


The following Java code example declares Book, Forum, Thread, and Reply classes and maps them to
the Amazon DynamoDB tables using the DynamoDBMapper class.

The code illustrates the following batch write operations:

API Version 2012-08-10


247
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

• batchSave to put book items in the ProductCatalog table.


• batchDelete to delete items from the ProductCatalog table.
• batchWrite to put and delete items from the Forum and the Thread tables.

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;

public class DynamoDBMapperBatchWriteExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-
dd'T'HH:mm:ss.SSS'Z'");

public static void main(String[] args) throws Exception {


try {

DynamoDBMapper mapper = new DynamoDBMapper(client);

testBatchSave(mapper);
testBatchDelete(mapper);
testBatchWrite(mapper);

System.out.println("Example complete!");

}
catch (Throwable t) {

API Version 2012-08-10


248
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

System.err.println("Error running the DynamoDBMapperBatchWriteExample: " + t);


t.printStackTrace();
}
}

private static void testBatchSave(DynamoDBMapper mapper) {

Book book1 = new Book();


book1.id = 901;
book1.inPublication = true;
book1.ISBN = "902-11-11-1111";
book1.pageCount = 100;
book1.price = 10;
book1.productCategory = "Book";
book1.title = "My book created in batch write";

Book book2 = new Book();


book2.id = 902;
book2.inPublication = true;
book2.ISBN = "902-11-12-1111";
book2.pageCount = 200;
book2.price = 20;
book2.productCategory = "Book";
book2.title = "My second book created in batch write";

Book book3 = new Book();


book3.id = 903;
book3.inPublication = false;
book3.ISBN = "902-11-13-1111";
book3.pageCount = 300;
book3.price = 25;
book3.productCategory = "Book";
book3.title = "My third book created in batch write";

System.out.println("Adding three books to ProductCatalog table.");


mapper.batchSave(Arrays.asList(book1, book2, book3));
}

private static void testBatchDelete(DynamoDBMapper mapper) {

Book book1 = mapper.load(Book.class, 901);


Book book2 = mapper.load(Book.class, 902);
System.out.println("Deleting two books from the ProductCatalog table.");
mapper.batchDelete(Arrays.asList(book1, book2));
}

private static void testBatchWrite(DynamoDBMapper mapper) {

// Create Forum item to save


Forum forumItem = new Forum();
forumItem.name = "Test BatchWrite Forum";
forumItem.threads = 0;
forumItem.category = "Amazon Web Services";

// Create Thread item to save


Thread threadItem = new Thread();
threadItem.forumName = "AmazonDynamoDB";
threadItem.subject = "My sample question";
threadItem.message = "BatchWrite message";
List<String> tags = new ArrayList<String>();
tags.add("batch operations");
tags.add("write");
threadItem.tags = new HashSet<String>(tags);

// Load ProductCatalog item to delete


Book book3 = mapper.load(Book.class, 903);

API Version 2012-08-10


249
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

List<Object> objectsToWrite = Arrays.asList(forumItem, threadItem);


List<Book> objectsToDelete = Arrays.asList(book3);

DynamoDBMapperConfig config = DynamoDBMapperConfig.builder()


.withSaveBehavior(DynamoDBMapperConfig.SaveBehavior.CLOBBER)
.build();

mapper.batchWrite(objectsToWrite, objectsToDelete, config);


}

@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;
}

public void setId(int 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 = "Price")
public int getPrice() {
return price;
}

public void setPrice(int price) {


this.price = price;
}

@DynamoDBAttribute(attributeName = "PageCount")
public int getPageCount() {
return pageCount;
}

public void setPageCount(int pageCount) {


this.pageCount = pageCount;
}

API Version 2012-08-10


250
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

@DynamoDBAttribute(attributeName = "ProductCategory")
public String getProductCategory() {
return productCategory;
}

public void setProductCategory(String productCategory) {


this.productCategory = productCategory;
}

@DynamoDBAttribute(attributeName = "InPublication")
public boolean getInPublication() {
return inPublication;
}

public void setInPublication(boolean inPublication) {


this.inPublication = 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;
}

public void setId(String id) {


this.id = id;
}

// Sort key
@DynamoDBRangeKey(attributeName = "ReplyDateTime")
public String getReplyDateTime() {
return replyDateTime;
}

public void setReplyDateTime(String replyDateTime) {


this.replyDateTime = replyDateTime;
}

@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}

public void setMessage(String message) {


this.message = message;
}

@DynamoDBAttribute(attributeName = "PostedBy")
public String getPostedBy() {

API Version 2012-08-10


251
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

return postedBy;
}

public void setPostedBy(String postedBy) {


this.postedBy = 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;
}

public void setForumName(String forumName) {


this.forumName = forumName;
}

// Sort key
@DynamoDBRangeKey(attributeName = "Subject")
public String getSubject() {
return subject;
}

public void setSubject(String subject) {


this.subject = subject;
}

@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}

public void setMessage(String message) {


this.message = message;
}

@DynamoDBAttribute(attributeName = "LastPostedDateTime")
public String getLastPostedDateTime() {
return lastPostedDateTime;
}

public void setLastPostedDateTime(String lastPostedDateTime) {


this.lastPostedDateTime = lastPostedDateTime;
}

@DynamoDBAttribute(attributeName = "LastPostedBy")
public String getLastPostedBy() {
return lastPostedBy;
}

public void setLastPostedBy(String lastPostedBy) {


this.lastPostedBy = lastPostedBy;
}

API Version 2012-08-10


252
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

@DynamoDBAttribute(attributeName = "Tags")
public Set<String> getTags() {
return tags;
}

public void setTags(Set<String> tags) {


this.tags = tags;
}

@DynamoDBAttribute(attributeName = "Answered")
public int getAnswered() {
return answered;
}

public void setAnswered(int answered) {


this.answered = answered;
}

@DynamoDBAttribute(attributeName = "Views")
public int getViews() {
return views;
}

public void setViews(int views) {


this.views = views;
}

@DynamoDBAttribute(attributeName = "Replies")
public int getReplies() {
return replies;
}

public void setReplies(int replies) {


this.replies = 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;
}

public void setName(String name) {


this.name = name;
}

@DynamoDBAttribute(attributeName = "Category")
public String getCategory() {
return category;
}

public void setCategory(String category) {


this.category = category;
}

@DynamoDBAttribute(attributeName = "Threads")
public int getThreads() {

API Version 2012-08-10


253
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

return threads;
}

public void setThreads(int threads) {


this.threads = threads;
}
}
}

Example: Query and Scan


The Java example in this section defines the following classes and maps them to the tables in Amazon
DynamoDB. For more information about creating sample tables, see Creating Tables and Loading Data
for Code Examples in DynamoDB (p. 326).

• The Book class maps to ProductCatalog table


• The Forum, Thread, and Reply classes map to tables of the same name.

The example then executes the follow query and scan operations using a DynamoDBMapper instance.

• Get a book by Id.

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/

API Version 2012-08-10


254
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

*
* 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;

public class DynamoDBMapperQueryScanExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

public static void main(String[] args) throws Exception {


try {

DynamoDBMapper mapper = new DynamoDBMapper(client);

// Get a book - Id=101


GetBook(mapper, 101);
// Sample forum and thread to test queries.
String forumName = "Amazon DynamoDB";
String threadSubject = "DynamoDB Thread 1";
// Sample queries.
FindRepliesInLast15Days(mapper, forumName, threadSubject);
FindRepliesPostedWithinTimePeriod(mapper, forumName, threadSubject);

// 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();
}
}

private static void GetBook(DynamoDBMapper mapper, int id) throws Exception {


System.out.println("GetBook: Get book Id='101' ");

API Version 2012-08-10


255
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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

private static void FindRepliesInLast15Days(DynamoDBMapper mapper, String forumName,


String threadSubject)
throws Exception {
System.out.println("FindRepliesInLast15Days: Replies within last 15 days.");

String partitionKey = forumName + "#" + threadSubject;

long twoWeeksAgoMilli = (new Date()).getTime() - (15L * 24L * 60L * 60L * 1000L);


Date twoWeeksAgo = new Date();
twoWeeksAgo.setTime(twoWeeksAgoMilli);
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-
dd'T'HH:mm:ss.SSS'Z'");
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String twoWeeksAgoStr = dateFormatter.format(twoWeeksAgo);

Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();


eav.put(":val1", new AttributeValue().withS(partitionKey));
eav.put(":val2", new AttributeValue().withS(twoWeeksAgoStr.toString()));

DynamoDBQueryExpression<Reply> queryExpression = new


DynamoDBQueryExpression<Reply>()
.withKeyConditionExpression("Id = :val1 and ReplyDateTime
> :val2").withExpressionAttributeValues(eav);

List<Reply> latestReplies = mapper.query(Reply.class, queryExpression);

for (Reply reply : latestReplies) {


System.out.format("Id=%s, Message=%s, PostedBy=%s %n, ReplyDateTime=%s %n",
reply.getId(),
reply.getMessage(), reply.getPostedBy(), reply.getReplyDateTime());
}
}

private static void FindRepliesPostedWithinTimePeriod(DynamoDBMapper mapper, String


forumName, String threadSubject)
throws Exception {
String partitionKey = forumName + "#" + threadSubject;

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

Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();

API Version 2012-08-10


256
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

eav.put(":val1", new AttributeValue().withS(partitionKey));


eav.put(":val2", new AttributeValue().withS(startDate));
eav.put(":val3", new AttributeValue().withS(endDate));

DynamoDBQueryExpression<Reply> queryExpression = new


DynamoDBQueryExpression<Reply>()
.withKeyConditionExpression("Id = :val1 and ReplyDateTime between :val2
and :val3")
.withExpressionAttributeValues(eav);

List<Reply> betweenReplies = mapper.query(Reply.class, queryExpression);

for (Reply reply : betweenReplies) {


System.out.format("Id=%s, Message=%s, PostedBy=%s %n, PostedDateTime=%s %n",
reply.getId(),
reply.getMessage(), reply.getPostedBy(), reply.getReplyDateTime());
}

private static void FindBooksPricedLessThanSpecifiedValue(DynamoDBMapper mapper, String


value) throws Exception {

System.out.println("FindBooksPricedLessThanSpecifiedValue: Scan ProductCatalog.");

Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();


eav.put(":val1", new AttributeValue().withN(value));
eav.put(":val2", new AttributeValue().withS("Book"));

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()


.withFilterExpression("Price < :val1 and ProductCategory
= :val2").withExpressionAttributeValues(eav);

List<Book> scanResult = mapper.scan(Book.class, scanExpression);

for (Book book : scanResult) {


System.out.println(book);
}
}

private static void FindBicyclesOfSpecificTypeWithMultipleThreads(DynamoDBMapper


mapper, int numberOfThreads,
String bicycleType) throws Exception {

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

DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()


.withFilterExpression("ProductCategory = :val1 and BicycleType
= :val2").withExpressionAttributeValues(eav);

List<Bicycle> scanResult = mapper.parallelScan(Bicycle.class, scanExpression,


numberOfThreads);
for (Bicycle bicycle : scanResult) {
System.out.println(bicycle);
}
}

@DynamoDBTable(tableName = "ProductCatalog")
public static class Book {
private int id;
private String title;
private String ISBN;

API Version 2012-08-10


257
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

private int price;


private int pageCount;
private String productCategory;
private boolean inPublication;

@DynamoDBHashKey(attributeName = "Id")
public int getId() {
return id;
}

public void setId(int 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 = "Price")
public int getPrice() {
return price;
}

public void setPrice(int price) {


this.price = price;
}

@DynamoDBAttribute(attributeName = "PageCount")
public int getPageCount() {
return pageCount;
}

public void setPageCount(int pageCount) {


this.pageCount = pageCount;
}

@DynamoDBAttribute(attributeName = "ProductCategory")
public String getProductCategory() {
return productCategory;
}

public void setProductCategory(String productCategory) {


this.productCategory = productCategory;
}

@DynamoDBAttribute(attributeName = "InPublication")
public boolean getInPublication() {
return inPublication;
}

public void setInPublication(boolean inPublication) {


this.inPublication = inPublication;

API Version 2012-08-10


258
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

@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;
}

public void setId(int id) {


this.id = id;
}

@DynamoDBAttribute(attributeName = "Title")
public String getTitle() {
return title;
}

public void setTitle(String title) {


this.title = title;
}

@DynamoDBAttribute(attributeName = "Description")
public String getDescription() {
return description;
}

public void setDescription(String description) {


this.description = description;
}

@DynamoDBAttribute(attributeName = "BicycleType")
public String getBicycleType() {
return bicycleType;
}

public void setBicycleType(String bicycleType) {


this.bicycleType = bicycleType;
}

@DynamoDBAttribute(attributeName = "Brand")
public String getBrand() {
return brand;
}

public void setBrand(String brand) {


this.brand = brand;
}

API Version 2012-08-10


259
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

@DynamoDBAttribute(attributeName = "Price")
public int getPrice() {
return price;
}

public void setPrice(int price) {


this.price = price;
}

@DynamoDBAttribute(attributeName = "Color")
public List<String> getColor() {
return color;
}

public void setColor(List<String> color) {


this.color = color;
}

@DynamoDBAttribute(attributeName = "ProductCategory")
public String getProductCategory() {
return productCategory;
}

public void setProductCategory(String productCategory) {


this.productCategory = 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;
}

public void setId(String id) {


this.id = id;
}

// Range key
@DynamoDBRangeKey(attributeName = "ReplyDateTime")
public String getReplyDateTime() {
return replyDateTime;
}

public void setReplyDateTime(String replyDateTime) {


this.replyDateTime = replyDateTime;
}

@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {

API Version 2012-08-10


260
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

return message;
}

public void setMessage(String message) {


this.message = message;
}

@DynamoDBAttribute(attributeName = "PostedBy")
public String getPostedBy() {
return postedBy;
}

public void setPostedBy(String postedBy) {


this.postedBy = 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;
}

public void setForumName(String forumName) {


this.forumName = forumName;
}

// Range key
@DynamoDBRangeKey(attributeName = "Subject")
public String getSubject() {
return subject;
}

public void setSubject(String subject) {


this.subject = subject;
}

@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}

public void setMessage(String message) {


this.message = message;
}

@DynamoDBAttribute(attributeName = "LastPostedDateTime")
public String getLastPostedDateTime() {
return lastPostedDateTime;
}

public void setLastPostedDateTime(String lastPostedDateTime) {


this.lastPostedDateTime = lastPostedDateTime;
}

API Version 2012-08-10


261
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

@DynamoDBAttribute(attributeName = "LastPostedBy")
public String getLastPostedBy() {
return lastPostedBy;
}

public void setLastPostedBy(String lastPostedBy) {


this.lastPostedBy = lastPostedBy;
}

@DynamoDBAttribute(attributeName = "Tags")
public Set<String> getTags() {
return tags;
}

public void setTags(Set<String> tags) {


this.tags = tags;
}

@DynamoDBAttribute(attributeName = "Answered")
public int getAnswered() {
return answered;
}

public void setAnswered(int answered) {


this.answered = answered;
}

@DynamoDBAttribute(attributeName = "Views")
public int getViews() {
return views;
}

public void setViews(int views) {


this.views = views;
}

@DynamoDBAttribute(attributeName = "Replies")
public int getReplies() {
return replies;
}

public void setReplies(int replies) {


this.replies = 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;
}

public void setName(String name) {


this.name = name;
}

@DynamoDBAttribute(attributeName = "Category")
public String getCategory() {
return category;

API Version 2012-08-10


262
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

public void setCategory(String category) {


this.category = category;
}

@DynamoDBAttribute(attributeName = "Threads")
public int getThreads() {
return threads;
}

public void setThreads(int threads) {


this.threads = threads;
}
}
}

Example: Transaction Operations


The following Java code example declares a Forum and a Thread class and maps them to the
DynamoDB tables using the DynamoDBMapper class.

The code illustrates the following transactional operations:

• 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;

API Version 2012-08-10


263
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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;

public class DynamoDBMapperTransactionExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDBMapper mapper;

public static void main(String[] args) throws Exception {


try {

mapper = new DynamoDBMapper(client);

testPutAndUpdateInTransactionWrite();
testPutWithConditionalUpdateInTransactionWrite();
testPutWithConditionCheckInTransactionWrite();
testMixedOperationsInTransactionWrite();
testTransactionLoadWithSave();
testTransactionLoadWithTransactionWrite();
System.out.println("Example complete");

}
catch (Throwable t) {
System.err.println("Error running the DynamoDBMapperTransactionWriteExample: "
+ t);
t.printStackTrace();
}
}

private static void testTransactionLoadWithSave() {


// Create new Forum item for DynamoDB using save
Forum dynamodbForum = new Forum();
dynamodbForum.name = "DynamoDB Forum";
dynamodbForum.category = "Amazon Web Services";
dynamodbForum.threads = 0;
mapper.save(dynamodbForum);

// Add a thread to DynamoDB Forum


Thread dynamodbForumThread = new Thread();
dynamodbForumThread.forumName = "DynamoDB Forum";
dynamodbForumThread.subject = "Sample Subject 1";
dynamodbForumThread.message = "Sample Question 1";
mapper.save(dynamodbForumThread);

// Update DynamoDB Forum to reflect updated thread count


dynamodbForum.threads = 1;
mapper.save(dynamodbForum);

// Read DynamoDB Forum item and Thread item at the same time in a serializable
manner
TransactionLoadRequest transactionLoadRequest = new TransactionLoadRequest();

// Read entire item for DynamoDB Forum


transactionLoadRequest.addLoad(dynamodbForum);

// Only read subject and message attributes from Thread item


DynamoDBTransactionLoadExpression loadExpressionForThread = new
DynamoDBTransactionLoadExpression()

.withProjectionExpression("Subject, Message");

API Version 2012-08-10


264
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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);
}

private static void testTransactionLoadWithTransactionWrite() {


// Create new Forum item for DynamoDB using save
Forum dynamodbForum = new Forum();
dynamodbForum.name = "DynamoDB New Forum";
dynamodbForum.category = "Amazon Web Services";
dynamodbForum.threads = 0;
mapper.save(dynamodbForum);

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

// Read entire item for DynamoDB Forum


transactionLoadRequest.addLoad(dynamodbForum);

// Only read subject and message attributes from Thread item


DynamoDBTransactionLoadExpression loadExpressionForThread = new
DynamoDBTransactionLoadExpression()

.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);
}

private static void testPutAndUpdateInTransactionWrite() {


// Create new Forum item for S3 using save
Forum s3Forum = new Forum();
s3Forum.name = "S3 Forum";
s3Forum.category = "Core Amazon Web Services";
s3Forum.threads = 0;

API Version 2012-08-10


265
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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);
}

private static void testPutWithConditionalUpdateInTransactionWrite() {


// Create new Thread item for DynamoDB forum and update thread count in DynamoDB
forum
// if the DynamoDB Forum exists
Thread dynamodbForumThread = new Thread();
dynamodbForumThread.forumName = "DynamoDB Forum";
dynamodbForumThread.subject = "Sample Subject 1";
dynamodbForumThread.message = "Sample Question 1";

Forum dynamodbForum = new Forum();


dynamodbForum.name = "DynamoDB Forum";
dynamodbForum.category = "Amazon Web Services";
dynamodbForum.threads = 1;

DynamoDBTransactionWriteExpression transactionWriteExpression = new


DynamoDBTransactionWriteExpression()

.withConditionExpression("attribute_exists(Category)");

TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();


transactionWriteRequest.addPut(dynamodbForumThread);
transactionWriteRequest.addUpdate(dynamodbForum, transactionWriteExpression);
executeTransactionWrite(transactionWriteRequest);
}

private static void testPutWithConditionCheckInTransactionWrite() {


// Create new Thread item for DynamoDB forum and update thread count in DynamoDB
forum if a thread already exists
Thread dynamodbForumThread2 = new Thread();
dynamodbForumThread2.forumName = "DynamoDB Forum";
dynamodbForumThread2.subject = "Sample Subject 2";
dynamodbForumThread2.message = "Sample Question 2";

Thread dynamodbForumThread1 = new Thread();


dynamodbForumThread1.forumName = "DynamoDB Forum";
dynamodbForumThread1.subject = "Sample Subject 1";
DynamoDBTransactionWriteExpression conditionExpressionForConditionCheck = new
DynamoDBTransactionWriteExpression()

.withConditionExpression("attribute_exists(Subject)");

Forum dynamodbForum = new Forum();


dynamodbForum.name = "DynamoDB Forum";
dynamodbForum.category = "Amazon Web Services";
dynamodbForum.threads = 2;

TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();


transactionWriteRequest.addPut(dynamodbForumThread2);
transactionWriteRequest.addConditionCheck(dynamodbForumThread1,
conditionExpressionForConditionCheck);
transactionWriteRequest.addUpdate(dynamodbForum);

API Version 2012-08-10


266
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

executeTransactionWrite(transactionWriteRequest);
}

private static void testMixedOperationsInTransactionWrite() {


// Create new Thread item for S3 forum and delete "Sample Subject 1" Thread from
DynamoDB forum if
// "Sample Subject 2" Thread exists in DynamoDB forum
Thread s3ForumThread = new Thread();
s3ForumThread.forumName = "S3 Forum";
s3ForumThread.subject = "Sample Subject 1";
s3ForumThread.message = "Sample Question 1";

Forum s3Forum = new Forum();


s3Forum.name = "S3 Forum";
s3Forum.category = "Amazon Web Services";
s3Forum.threads = 1;

Thread dynamodbForumThread1 = new Thread();


dynamodbForumThread1.forumName = "DynamoDB Forum";
dynamodbForumThread1.subject = "Sample Subject 1";

Thread dynamodbForumThread2 = new Thread();


dynamodbForumThread2.forumName = "DynamoDB Forum";
dynamodbForumThread2.subject = "Sample Subject 2";
DynamoDBTransactionWriteExpression conditionExpressionForConditionCheck = new
DynamoDBTransactionWriteExpression()

.withConditionExpression("attribute_exists(Subject)");

Forum dynamodbForum = new Forum();


dynamodbForum.name = "DynamoDB Forum";
dynamodbForum.category = "Amazon Web Services";
dynamodbForum.threads = 1;

TransactionWriteRequest transactionWriteRequest = new TransactionWriteRequest();


transactionWriteRequest.addPut(s3ForumThread);
transactionWriteRequest.addUpdate(s3Forum);
transactionWriteRequest.addDelete(dynamodbForumThread1);
transactionWriteRequest.addConditionCheck(dynamodbForumThread2,
conditionExpressionForConditionCheck);
transactionWriteRequest.addUpdate(dynamodbForum);
executeTransactionWrite(transactionWriteRequest);
}
private static List<Object> executeTransactionLoad(TransactionLoadRequest
transactionLoadRequest) {
List<Object> loadedObjects = new ArrayList<Object>();
try {
loadedObjects = mapper.transactionLoad(transactionLoadRequest);
} 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());
}

API Version 2012-08-10


267
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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;
}

public void setForumName(String forumName) {


this.forumName = forumName;
}

// Sort key
@DynamoDBRangeKey(attributeName = "Subject")
public String getSubject() {
return subject;
}

public void setSubject(String subject) {


this.subject = subject;
}

@DynamoDBAttribute(attributeName = "Message")
public String getMessage() {
return message;
}

public void setMessage(String message) {


this.message = message;
}

@DynamoDBAttribute(attributeName = "LastPostedDateTime")

API Version 2012-08-10


268
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

public String getLastPostedDateTime() {


return lastPostedDateTime;
}

public void setLastPostedDateTime(String lastPostedDateTime) {


this.lastPostedDateTime = lastPostedDateTime;
}

@DynamoDBAttribute(attributeName = "LastPostedBy")
public String getLastPostedBy() {
return lastPostedBy;
}

public void setLastPostedBy(String lastPostedBy) {


this.lastPostedBy = lastPostedBy;
}

@DynamoDBAttribute(attributeName = "Tags")
public Set<String> getTags() {
return tags;
}

public void setTags(Set<String> tags) {


this.tags = tags;
}

@DynamoDBAttribute(attributeName = "Answered")
public int getAnswered() {
return answered;
}

public void setAnswered(int answered) {


this.answered = answered;
}

@DynamoDBAttribute(attributeName = "Views")
public int getViews() {
return views;
}

public void setViews(int views) {


this.views = views;
}

@DynamoDBAttribute(attributeName = "Replies")
public int getReplies() {
return replies;
}

public void setReplies(int replies) {


this.replies = 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;
}

API Version 2012-08-10


269
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

public void setName(String name) {


this.name = name;
}

@DynamoDBAttribute(attributeName = "Category")
public String getCategory() {
return category;
}

public void setCategory(String category) {


this.category = category;
}

@DynamoDBAttribute(attributeName = "Threads")
public int getThreads() {
return threads;
}

public void setThreads(int threads) {


this.threads = threads;
}
}
}

Optimistic Locking with Version Number


Optimistic locking is a strategy to ensure that the client-side item that you are updating (or deleting) is
the same as the item in Amazon DynamoDB. If you use this strategy, your database writes are protected
from being overwritten by the writes of others, and vice versa.

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.

ConditionalCheckFailedException is thrown if:

• 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.

API Version 2012-08-10


270
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

• DynamoDBMapper transactional write operations do not support


@DynamoDBVersionAttribute annotation and condition expressions within
the same API call. If an object within a transactional write is annotated with
@DynamoDBVersionAttribute and also has a condition expression, then an
SdkClientException will be thrown.

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 {

private Integer id;


private String title;
private String ISBN;
private Set<String> bookAuthors;
private String someProp;
private Long version;

@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.

Optimistic locking has the following impact on these DynamoDBMapper methods:

• 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.

API Version 2012-08-10


271
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

• 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.

Disabling Optimistic Locking


To disable optimistic locking, you can change the DynamoDBMapperConfig.SaveBehavior
enumeration value from UPDATE to CLOBBER. You can do this by creating a DynamoDBMapperConfig
instance that skips version checking and use this instance for all your requests. For information about
DynamoDBMapperConfig.SaveBehavior and other optional DynamoDBMapper parameters, see
Optional Configuration Settings for DynamoDBMapper (p. 244).

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

DynamoDBMapper mapper = new DynamoDBMapper(client);

// Load a catalog item.


CatalogItem item = mapper.load(CatalogItem.class, 101);
item.setTitle("This is a new title for the item");
...
// Save the item.
mapper.save(item,
new DynamoDBMapperConfig(
DynamoDBMapperConfig.SaveBehavior.CLOBBER));

Mapping Arbitrary Data


In addition to the supported Java types (see Supported Data Types (p. 231)), you can use types in your
application for which there is no direct mapping to the Amazon DynamoDB types. To map these types,
you must provide an implementation that converts your complex type to a DynamoDB supported type
and vice versa, and annotate the complex type accessor method using the @DynamoDBTypeConverted
annotation. The converter code transforms data when objects are saved or loaded. It is also used for
all operations that consume complex types. Note that when comparing data during query and scan
operations, the comparisons are made against the data stored in DynamoDB.

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

API Version 2012-08-10


272
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

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;

public class DynamoDBMapperExample {

static AmazonDynamoDB client;

public static void main(String[] args) throws IOException {

// Set the AWS region you want to access.


Regions usWest2 = Regions.US_WEST_2;
client = AmazonDynamoDBClientBuilder.standard().withRegion(usWest2).build();

DimensionType dimType = new DimensionType();


dimType.setHeight("8.00");
dimType.setLength("11.0");
dimType.setThickness("1.0");

Book book = new Book();


book.setId(502);
book.setTitle("Book 502");
book.setISBN("555-5555555555");
book.setBookAuthors(new HashSet<String>(Arrays.asList("Author1", "Author2")));
book.setDimensions(dimType);

API Version 2012-08-10


273
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

DynamoDBMapper mapper = new DynamoDBMapper(client);


mapper.save(book);

Book bookRetrieved = mapper.load(Book.class, 502);


System.out.println("Book info: " + "\n" + bookRetrieved);

bookRetrieved.getDimensions().setHeight("9.0");
bookRetrieved.getDimensions().setLength("12.0");
bookRetrieved.getDimensions().setThickness("2.0");

mapper.save(bookRetrieved);

bookRetrieved = mapper.load(Book.class, 502);


System.out.println("Updated book info: " + "\n" + 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;
}

public void setId(int 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;
}

@DynamoDBTypeConverted(converter = DimensionTypeConverter.class)
@DynamoDBAttribute(attributeName = "Dimensions")
public DimensionType getDimensions() {
return dimensionType;
}

API Version 2012-08-10


274
Amazon DynamoDB Developer Guide
Java: DynamoDBMapper

@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 + "]";
}
}

static public class DimensionType {

private String length;


private String height;
private String thickness;

public String getLength() {


return length;
}

public void setLength(String length) {


this.length = length;
}

public String getHeight() {


return height;
}

public void setHeight(String height) {


this.height = height;
}

public String getThickness() {


return thickness;
}

public void setThickness(String thickness) {


this.thickness = thickness;
}
}

// Converts the complex type DimensionType to a string and vice-versa.


static public class DimensionTypeConverter implements DynamoDBTypeConverter<String,
DimensionType> {

@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;

API Version 2012-08-10


275
Amazon DynamoDB Developer Guide
.NET: Document Model

@Override
public DimensionType unconvert(String s) {

DimensionType itemDimension = new DimensionType();


try {
if (s != null && s.length() != 0) {
String[] data = s.split("x");
itemDimension.setLength(data[0].trim());
itemDimension.setHeight(data[1].trim());
itemDimension.setThickness(data[2].trim());
}
}
catch (Exception e) {
e.printStackTrace();
}

return itemDimension;
}
}
}

.NET: Document Model


Topics
• Operations Not Supported by the Document Model (p. 276)
• Working with Items in DynamoDB Using the AWS SDK for .NET Document Model (p. 276)
• Getting an Item - Table.GetItem (p. 280)
• Deleting an Item - Table.DeleteItem (p. 281)
• Updating an Item - Table.UpdateItem (p. 282)
• Batch Write - Putting and Deleting Multiple Items (p. 283)
• Example: CRUD Operations Using the AWS SDK for .NET Document Model (p. 285)
• Example: Batch Operations Using the AWS SDK for .NET Document Model API (p. 288)
• Querying Tables in DynamoDB Using the AWS SDK for .NET Document Model (p. 290)

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.

The preceding document model classes are available in the Amazon.DynamoDBv2.DocumentModel


namespace.

Operations Not Supported by the Document Model


You can't use the document model classes to create, update, and delete tables. However, the document
model does support most common data operations.

Working with Items in DynamoDB Using the AWS SDK for .NET
Document Model
Topics

API Version 2012-08-10


276
Amazon DynamoDB Developer Guide
.NET: Document Model

• Putting an Item - Table.PutItem Method (p. 278)


• Specifying Optional Parameters (p. 279)

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

Table table = Table.LoadTable(client, "ProductCatalog");

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

// Configuration object that specifies optional parameters.


GetItemOperationConfig config = new GetItemOperationConfig()
{
AttributesToGet = new List<string>() { "Id", "Title" },
};
// Pass in the configuration to the GetItem method.
// 1. Table that has only a partition key as primary key.
Table.GetItem(Primitive partitionKey, GetItemOperationConfig config);
// 2. Table that has both a partition key and a sort key.
Table.GetItem(Primitive partitionKey, Primitive sortKey, GetItemOperationConfig config);

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.

API Version 2012-08-10


277
Amazon DynamoDB Developer Guide
.NET: Document Model

Putting an Item - Table.PutItem Method


The PutItem method uploads the input Document instance to the table. If an item that has a primary
key that is specified in the input Document exists in the table, the PutItem operation replaces the
entire existing item. The new item is identical to the Document object that you provided to the PutItem
method. If your original item had any extra attributes, they are no longer present in the new item.

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