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

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 list of attribute names and their values.
3. Execute Table.PutItem by providing the Document instance as a parameter.

The following C# code example demonstrates the preceding tasks. The example uploads an item to the
ProductCatalog table.

Example

Table table = Table.LoadTable(client, "ProductCatalog");

var book = new Document();


book["Id"] = 101;
book["Title"] = "Book 101 Title";
book["ISBN"] = "11-11-11-11";
book["Authors"] = new List<string> { "Author 1", "Author 2" };
book["InStock"] = new DynamoDBBool(true);
book["QuantityOnHand"] = new DynamoDBNull();

table.PutItem(book);

In the preceding example, the Document instance creates an item that has Number, String, String
Set, Boolean, and Null attributes. (Null is used to indicate that the QuantityOnHand for this product
is unknown.) For Boolean and Null, use the constructor methods DynamoDBBool and DynamoDBNull.

In DynamoDB, the List and Map data types can contain elements composed of other data types. Here is
how to map these data types to the document model API:

• List — use the DynamoDBList constructor.


• Map — use the Document constructor.

You can modify the preceding example to add a List attribute to the item. To do this, use a
DynamoDBList constructor, as shown in the following code example.

Example

Table table = Table.LoadTable(client, "ProductCatalog");

var book = new Document();


book["Id"] = 101;

/*other attributes omitted for brevity...*/

var relatedItems = new DynamoDBList();


relatedItems.Add(341);
relatedItems.Add(472);
relatedItems.Add(649);
item.Add("RelatedItems", relatedItems);

API Version 2012-08-10


278
Amazon DynamoDB Developer Guide
.NET: Document Model

table.PutItem(book);

To add a Map attribute to the book, you define another Document. The following code example
illustrates how to do this.

Example

Table table = Table.LoadTable(client, "ProductCatalog");

var book = new Document();


book["Id"] = 101;

/*other attributes omitted for brevity...*/

var pictures = new Document();


pictures.Add("FrontView", "http://example.com/products/101_front.jpg" );
pictures.Add("RearView", "http://example.com/products/101_rear.jpg" );

book.Add("Pictures", pictures);

table.PutItem(book);

These examples are based on the item shown in Specifying Item Attributes When Using
Expressions (p. 386). The document model lets you create complex nested attributes, such as the
ProductReviews attribute shown in the case study.

Specifying Optional Parameters


You can configure optional parameters for the PutItem operation by adding the
PutItemOperationConfig parameter. For a complete list of optional parameters, see PutItem. The
following C# code example puts an item in the ProductCatalog table. It specifies the following
optional parameter:

• The ConditionalExpression parameter to make this a conditional put request. The example
creates an expression that specifies the ISBN attribute must have a specific value that has to be
present in the item that you are replacing.

Example

Table table = Table.LoadTable(client, "ProductCatalog");

var book = new Document();


book["Id"] = 555;
book["Title"] = "Book 555 Title";
book["Price"] = "25.00";
book["ISBN"] = "55-55-55-55";
book["Name"] = "Item 1 updated";
book["Authors"] = new List<string> { "Author x", "Author y" };
book["InStock"] = new DynamoDBBool(true);
book["QuantityOnHand"] = new DynamoDBNull();

// Create a condition expression for the optional conditional put operation.


Expression expr = new Expression();
expr.ExpressionStatement = "ISBN = :val";
expr.ExpressionAttributeValues[":val"] = "55-55-55-55";

PutItemOperationConfig config = new PutItemOperationConfig()


{
// Optional parameter.

API Version 2012-08-10


279
Amazon DynamoDB Developer Guide
.NET: Document Model

ConditionalExpression = expr
};

table.PutItem(book, config);

Getting an Item - Table.GetItem


The GetItem operation retrieves an item as a Document instance. You must provide the primary key of
the item that you want to retrieve as shown in the following C# code example.

Example

Table table = Table.LoadTable(client, "ProductCatalog");


Document document = table.GetItem(101); // Primary key 101.

The GetItem operation returns all the attributes of the item and performs an eventually consistent read
(see Read Consistency (p. 16)) by default.

Specifying Optional Parameters


You can configure additional options for the GetItem operation by adding the
GetItemOperationConfig parameter. For a complete list of optional parameters, see GetItem.
The following C# code example retrieves an item from the ProductCatalog table. It specifies the
GetItemOperationConfig to provide the following optional parameters:

• The AttributesToGet parameter to retrieve only the specified attributes.


• The ConsistentRead parameter to request the latest values for all the specified attributes. To learn
more about data consistency, see Read Consistency (p. 16).

Example

Table table = Table.LoadTable(client, "ProductCatalog");

GetItemOperationConfig config = new GetItemOperationConfig()


{
AttributesToGet = new List<string>() { "Id", "Title", "Authors", "InStock",
"QuantityOnHand" },
ConsistentRead = true
};
Document doc = table.GetItem(101, config);

When you retrieve an item using the document model API, you can access individual elements within the
Document object is returned, as shown in the following example.

Example

int id = doc["Id"].AsInt();
string title = doc["Title"].AsString();
List<string> authors = doc["Authors"].AsListOfString();
bool inStock = doc["InStock"].AsBoolean();
DynamoDBNull quantityOnHand = doc["QuantityOnHand"].AsDynamoDBNull();

For attributes that are of type List or Map, here is how to map these attributes to the document model
API:

• List — Use the AsDynamoDBList method.


• Map — Use the AsDocument method.

API Version 2012-08-10


280
Amazon DynamoDB Developer Guide
.NET: Document Model

The following code example shows how to retrieve a List (RelatedItems) and a Map (Pictures) from the
Document object:

Example

DynamoDBList relatedItems = doc["RelatedItems"].AsDynamoDBList();

Document pictures = doc["Pictures"].AsDocument();

Deleting an Item - Table.DeleteItem


The DeleteItem operation deletes an item from a table. You can pass the item's primary key as a
parameter. Or, if you've already read an item and have the corresponding Document object, you can pass
it as a parameter to the DeleteItem method, as shown in the following C# code example.

Example

Table table = Table.LoadTable(client, "ProductCatalog");

// Retrieve a book (a Document instance)


Document document = table.GetItem(111);

// 1) Delete using the Document instance.


table.DeleteItem(document);

// 2) Delete using the primary key.


int partitionKey = 222;
table.DeleteItem(partitionKey)

Specifying Optional Parameters


You can configure additional options for the Delete operation by adding the
DeleteItemOperationConfig parameter. For a complete list of optional parameters, see DeleteTable.
The following C# code example specifies the two following optional parameters:

• The ConditionalExpression parameter to ensure that the book item being deleted has a specific
value for the ISBN attribute.
• The ReturnValues parameter to request that the Delete method return the item that it deleted.

Example

Table table = Table.LoadTable(client, "ProductCatalog");


int partitionKey = 111;

Expression expr = new Expression();


expr.ExpressionStatement = "ISBN = :val";
expr.ExpressionAttributeValues[":val"] = "11-11-11-11";

// Specify optional parameters for Delete operation.


DeleteItemOperationConfig config = new DeleteItemOperationConfig
{
ConditionalExpression = expr,
ReturnValues = ReturnValues.AllOldAttributes // This is the only supported value when
using the document model.
};

// Delete the book.


Document d = table.DeleteItem(partitionKey, config);

API Version 2012-08-10


281
Amazon DynamoDB Developer Guide
.NET: Document Model

Updating an Item - Table.UpdateItem


The UpdateItem operation updates an existing item if it is present. If the item that has the specified
primary key is not found, the UpdateItem operation adds a new item.

You can use the UpdateItem operation to update existing attribute values, add new attributes to
the existing collection, or delete attributes from the existing collection. You provide these updates by
creating a Document instance that describes the updates that you want to perform.

The UpdateItem action uses the following guidelines:

• If the item does not exist, UpdateItem adds a new item using the primary key that is specified in the
input.
• If the item exists, UpdateItem applies the updates as follows:
• Replaces the existing attribute values with the values in the update.
• If an attribute that you provide in the input does not exist, it adds a new attribute to the item.
• If the input attribute value is null, it deletes the attributes, if it is present.

Note
This midlevel UpdateItem operation does not support the Add action (see UpdateItem) that is
supported by the underlying DynamoDB operation.
Note
The PutItem operation (Putting an Item - Table.PutItem Method (p. 278)) can also perform
an update. If you call PutItem to upload an item and the primary key exists, the PutItem
operation replaces the entire item. If there are attributes in the existing item and those
attributes are not specified on the Document that is being put, the PutItem operation deletes
those attributes. However, UpdateItem only updates the specified input attributes. Any other
existing attributes of that item remain unchanged.

The following are the steps to update an item using the AWS SDK for .NET document model:

1. Execute the Table.LoadTable method by providing the name of the table in which you want to
perform the update operation.
2. Create a Document instance by providing all the updates that you want to perform.

To delete an existing attribute, specify the attribute value as null.


3. Call the Table.UpdateItem method and provide the Document instance as an input parameter.

You must provide the primary key either in the Document instance or explicitly as a parameter.

The following C# code example demonstrates the preceding tasks. The code example updates an item
in the Book table. The UpdateItem operation updates the existing Authors attribute, deletes the
PageCount attribute, and adds a new XYZ attribute. The Document instance includes the primary key of
the book to update.

Example

Table table = Table.LoadTable(client, "ProductCatalog");

var book = new Document();

// Set the attributes that you wish to update.


book["Id"] = 111; // Primary key.
// Replace the authors attribute.
book["Authors"] = new List<string> { "Author x", "Author y" };
// Add a new attribute.

API Version 2012-08-10


282
Amazon DynamoDB Developer Guide
.NET: Document Model

book["XYZ"] = 12345;
// Delete the existing PageCount attribute.
book["PageCount"] = null;

table.Update(book);

Specifying Optional Parameters


You can configure additional options for the UpdateItem operation by adding the
UpdateItemOperationConfig parameter. For a complete list of optional parameters, see UpdateItem.

The following C# code example updates a book item price to 25. It specifies the two following optional
parameters:

• The ConditionalExpression parameter that identifies the Price attribute with value 20 that you
expect to be present.
• The ReturnValues parameter to request the UpdateItem operation to return the item that is
updated.

Example

Table table = Table.LoadTable(client, "ProductCatalog");


string partitionKey = "111";

var book = new Document();


book["Id"] = partitionKey;
book["Price"] = 25;

Expression expr = new Expression();


expr.ExpressionStatement = "Price = :val";
expr.ExpressionAttributeValues[":val"] = "20";

UpdateOperationConfig config = new UpdateOperationConfig()


{
ConditionalExpression = expr,
ReturnValues = ReturnValues.AllOldAttributes
};

Document d1 = table.Update(book, config);

Batch Write - Putting and Deleting Multiple Items


Batch write refers to putting and deleting multiple items in a batch. The operation enables you to put
and delete multiple items from one or more tables in a single call. The following are the steps to put or
delete multiple items from a table using the AWS SDK for .NET document model API.

1. Create a Table object by executing the Table.LoadTable method by providing the name of the
table in which you want to perform the batch operation.
2. Execute the CreateBatchWrite method on the table instance you created in the preceding step and
create a DocumentBatchWrite object.
3. Use the DocumentBatchWrite object methods to specify the documents that you want to upload or
delete.
4. Call the DocumentBatchWrite.Execute method to execute the batch operation.

When using the document model API, you can specify any number of operations in a batch. However,
DynamoDB limits the number of operations in a batch and the total size of the batch in a batch
operation. For more information about the specific limits, see BatchWriteItem. If the document model
API detects that your batch write request exceeded the number of allowed write requests, or the HTTP

API Version 2012-08-10


283
Amazon DynamoDB Developer Guide
.NET: Document Model

payload size of a batch exceeded the limit allowed by BatchWriteItem, it breaks the batch into
several smaller batches. Additionally, if a response to a batch write returns unprocessed items, the
document model API automatically sends another batch request with those unprocessed items.

The following C# code example demonstrates the preceding steps. The example uses batch write
operation to perform two writes; upload a book item and delete another book item.

Table productCatalog = Table.LoadTable(client, "ProductCatalog");


var batchWrite = productCatalog.CreateBatchWrite();

var book1 = new Document();


book1["Id"] = 902;
book1["Title"] = "My book1 in batch write using .NET document model";
book1["Price"] = 10;
book1["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" };
book1["InStock"] = new DynamoDBBool(true);
book1["QuantityOnHand"] = 5;

batchWrite.AddDocumentToPut(book1);
// specify delete item using overload that takes PK.
batchWrite.AddKeyToDelete(12345);

batchWrite.Execute();

For a working example, see Example: Batch Operations Using the AWS SDK for .NET Document Model
API (p. 288).

You can use the batchWrite operation to perform put and delete operations on multiple tables. The
following are the steps to put or delete multiple items from multiple tables using the AWS SDK for .NET
document model.

1. You create a DocumentBatchWrite instance for each table in which you want to put or delete
multiple items, as described in the preceding procedure.
2. Create an instance of the MultiTableDocumentBatchWrite and add the individual
DocumentBatchWrite objects to it.
3. Execute the MultiTableDocumentBatchWrite.Execute method.

The following C# code example demonstrates the preceding steps. The example uses the batch write
operation to perform the following write operations:

• Put a new item in the Forum table item.


• Put an item in the Thread table and delete an item from the same table.

// 1. Specify item to add in the Forum table.


Table forum = Table.LoadTable(client, "Forum");
var forumBatchWrite = forum.CreateBatchWrite();

var forum1 = new Document();


forum1["Name"] = "Test BatchWrite Forum";
forum1["Threads"] = 0;
forumBatchWrite.AddDocumentToPut(forum1);

// 2a. Specify item to add in the Thread table.


Table thread = Table.LoadTable(client, "Thread");
var threadBatchWrite = thread.CreateBatchWrite();

API Version 2012-08-10


284
Amazon DynamoDB Developer Guide
.NET: Document Model

var thread1 = new Document();


thread1["ForumName"] = "Amazon S3 forum";
thread1["Subject"] = "My sample question";
thread1["Message"] = "Message text";
thread1["KeywordTags"] = new List<string>{ "Amazon S3", "Bucket" };
threadBatchWrite.AddDocumentToPut(thread1);

// 2b. Specify item to delete from the Thread table.


threadBatchWrite.AddKeyToDelete("someForumName", "someSubject");

// 3. Create multi-table batch.


var superBatch = new MultiTableDocumentBatchWrite();
superBatch.AddBatch(forumBatchWrite);
superBatch.AddBatch(threadBatchWrite);

superBatch.Execute();

Example: CRUD Operations Using the AWS SDK for .NET


Document Model
The following C# code example performs the following actions:

• Creates a book item in the ProductCatalog table.


• Retrieves the book item.
• Updates the book item. The code example shows a normal update that adds new attributes and
updates existing attributes. It also shows a conditional update that updates the book price only if the
existing price value is as specified in the code.
• Deletes the book item.

For step-by-step instructions to test the following example, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class MidlevelItemCRUD
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

API Version 2012-08-10


285
Amazon DynamoDB Developer Guide
.NET: Document Model

private static string tableName = "ProductCatalog";


// The sample uses the following id PK value to add book item.
private static int sampleBookId = 555;

static void Main(string[] args)


{
try
{
Table productCatalog = Table.LoadTable(client, tableName);
CreateBookItem(productCatalog);
RetrieveBook(productCatalog);
// Couple of sample updates.
UpdateMultipleAttributes(productCatalog);
UpdateBookPriceConditionally(productCatalog);

// Delete.
DeleteBook(productCatalog);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }
}

// Creates a sample book item.


private static void CreateBookItem(Table productCatalog)
{
Console.WriteLine("\n*** Executing CreateBookItem() ***");
var book = new Document();
book["Id"] = sampleBookId;
book["Title"] = "Book " + sampleBookId;
book["Price"] = 19.99;
book["ISBN"] = "111-1111111111";
book["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" };
book["PageCount"] = 500;
book["Dimensions"] = "8.5x11x.5";
book["InPublication"] = new DynamoDBBool(true);
book["InStock"] = new DynamoDBBool(false);
book["QuantityOnHand"] = 0;

productCatalog.PutItem(book);
}

private static void RetrieveBook(Table productCatalog)


{
Console.WriteLine("\n*** Executing RetrieveBook() ***");
// Optional configuration.
GetItemOperationConfig config = new GetItemOperationConfig
{
AttributesToGet = new List<string> { "Id", "ISBN", "Title", "Authors",
"Price" },
ConsistentRead = true
};
Document document = productCatalog.GetItem(sampleBookId, config);
Console.WriteLine("RetrieveBook: Printing book retrieved...");
PrintDocument(document);
}

private static void UpdateMultipleAttributes(Table productCatalog)


{
Console.WriteLine("\n*** Executing UpdateMultipleAttributes() ***");
Console.WriteLine("\nUpdating multiple attributes....");
int partitionKey = sampleBookId;

var book = new Document();

API Version 2012-08-10


286
Amazon DynamoDB Developer Guide
.NET: Document Model

book["Id"] = partitionKey;
// List of attribute updates.
// The following replaces the existing authors list.
book["Authors"] = new List<string> { "Author x", "Author y" };
book["newAttribute"] = "New Value";
book["ISBN"] = null; // Remove it.

// Optional parameters.
UpdateItemOperationConfig config = new UpdateItemOperationConfig
{
// Get updated item in response.
ReturnValues = ReturnValues.AllNewAttributes
};
Document updatedBook = productCatalog.UpdateItem(book, config);
Console.WriteLine("UpdateMultipleAttributes: Printing item after updates ...");
PrintDocument(updatedBook);
}

private static void UpdateBookPriceConditionally(Table productCatalog)


{
Console.WriteLine("\n*** Executing UpdateBookPriceConditionally() ***");

int partitionKey = sampleBookId;

var book = new Document();


book["Id"] = partitionKey;
book["Price"] = 29.99;

// For conditional price update, creating a condition expression.


Expression expr = new Expression();
expr.ExpressionStatement = "Price = :val";
expr.ExpressionAttributeValues[":val"] = 19.00;

// Optional parameters.
UpdateItemOperationConfig config = new UpdateItemOperationConfig
{
ConditionalExpression = expr,
ReturnValues = ReturnValues.AllNewAttributes
};
Document updatedBook = productCatalog.UpdateItem(book, config);
Console.WriteLine("UpdateBookPriceConditionally: Printing item whose price was
conditionally updated");
PrintDocument(updatedBook);
}

private static void DeleteBook(Table productCatalog)


{
Console.WriteLine("\n*** Executing DeleteBook() ***");
// Optional configuration.
DeleteItemOperationConfig config = new DeleteItemOperationConfig
{
// Return the deleted item.
ReturnValues = ReturnValues.AllOldAttributes
};
Document document = productCatalog.DeleteItem(sampleBookId, config);
Console.WriteLine("DeleteBook: Printing deleted just deleted...");
PrintDocument(document);
}

private static void PrintDocument(Document updatedDocument)


{
foreach (var attribute in updatedDocument.GetAttributeNames())
{
string stringValue = null;
var value = updatedDocument[attribute];
if (value is Primitive)

API Version 2012-08-10


287
Amazon DynamoDB Developer Guide
.NET: Document Model

stringValue = value.AsPrimitive().Value.ToString();
else if (value is PrimitiveList)
stringValue = string.Join(",", (from primitive
in value.AsPrimitiveList().Entries
select primitive.Value).ToArray());
Console.WriteLine("{0} - {1}", attribute, stringValue);
}
}
}
}

Example: Batch Operations Using the AWS SDK for .NET


Document Model API
Topics
• Example: Batch Write Using the AWS SDK for .NET Document Model (p. 288)

Example: Batch Write Using the AWS SDK for .NET Document Model
The following C# code example illustrates single table and multi-table batch write operations. The
example performs the following tasks:

• Illustrates a single table batch write. It adds two items to the ProductCatalog table.
• Illustrates a multi-table batch write. It adds an item to both the Forum and Thread tables and deletes
an item from the Thread table.

If you followed the steps in Creating Tables and Loading Data for Code Examples in
DynamoDB (p. 326), you already have the ProductCatalog, Forum, and Thread tables created. You
can also create these sample tables programmatically. For more information, see Creating Example
Tables and Uploading Data Using the AWS SDK for .NET (p. 988). For step-by-step instructions for
testing the following example, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class MidLevelBatchWriteItem
{

API Version 2012-08-10


288
Amazon DynamoDB Developer Guide
.NET: Document Model

private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();


static void Main(string[] args)
{
try
{
SingleTableBatchWrite();
MultiTableBatchWrite();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void SingleTableBatchWrite()


{
Table productCatalog = Table.LoadTable(client, "ProductCatalog");
var batchWrite = productCatalog.CreateBatchWrite();

var book1 = new Document();


book1["Id"] = 902;
book1["Title"] = "My book1 in batch write using .NET helper classes";
book1["ISBN"] = "902-11-11-1111";
book1["Price"] = 10;
book1["ProductCategory"] = "Book";
book1["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" };
book1["Dimensions"] = "8.5x11x.5";
book1["InStock"] = new DynamoDBBool(true);
book1["QuantityOnHand"] = new DynamoDBNull(); //Quantity is unknown at this
time

batchWrite.AddDocumentToPut(book1);
// Specify delete item using overload that takes PK.
batchWrite.AddKeyToDelete(12345);
Console.WriteLine("Performing batch write in SingleTableBatchWrite()");
batchWrite.Execute();
}

private static void MultiTableBatchWrite()


{
// 1. Specify item to add in the Forum table.
Table forum = Table.LoadTable(client, "Forum");
var forumBatchWrite = forum.CreateBatchWrite();

var forum1 = new Document();


forum1["Name"] = "Test BatchWrite Forum";
forum1["Threads"] = 0;
forumBatchWrite.AddDocumentToPut(forum1);

// 2a. Specify item to add in the Thread table.


Table thread = Table.LoadTable(client, "Thread");
var threadBatchWrite = thread.CreateBatchWrite();

var thread1 = new Document();


thread1["ForumName"] = "S3 forum";
thread1["Subject"] = "My sample question";
thread1["Message"] = "Message text";
thread1["KeywordTags"] = new List<string> { "S3", "Bucket" };
threadBatchWrite.AddDocumentToPut(thread1);

// 2b. Specify item to delete from the Thread table.


threadBatchWrite.AddKeyToDelete("someForumName", "someSubject");

API Version 2012-08-10


289
Amazon DynamoDB Developer Guide
.NET: Document Model

// 3. Create multi-table batch.


var superBatch = new MultiTableDocumentBatchWrite();
superBatch.AddBatch(forumBatchWrite);
superBatch.AddBatch(threadBatchWrite);
Console.WriteLine("Performing batch write in MultiTableBatchWrite()");
superBatch.Execute();
}
}

Querying Tables in DynamoDB Using the AWS SDK for .NET


Document Model
Topics
• Table.Query Method in the AWS SDK for .NET (p. 290)
• Table.Scan Method in the AWS SDK for .NET (p. 294)

Table.Query Method in the AWS SDK for .NET


The Query method enables you to query your tables. You can only query the tables that have a
composite primary key (partition key and sort key). If your table's primary key is made of only a partition
key, then the Query operation is not supported. By default, Query internally performs queries that are
eventually consistent. To learn about the consistency model, see Read Consistency (p. 16).

The Query method provides two overloads. The minimum required parameters to the Query method are
a partition key value and a sort key filter. You can use the following overload to provide these minimum
required parameters.

Example

Query(Primitive partitionKey, RangeFilter Filter);

For example, the following C# code queries for all forum replies that were posted in the last 15 days.

Example

string tableName = "Reply";


Table table = Table.LoadTable(client, tableName);

DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);


RangeFilter filter = new RangeFilter(QueryOperator.GreaterThan, twoWeeksAgoDate);
Search search = table.Query("DynamoDB Thread 2", filter);

This creates a Search object. You can now call the Search.GetNextSet method iteratively to retrieve
one page of results at a time, as shown in the following C# code example. The code prints the attribute
values for each item that the query returns.

Example

List<Document> documentSet = new List<Document>();


do
{
documentSet = search.GetNextSet();
foreach (var document in documentSet)
PrintDocument(document);

API Version 2012-08-10


290
Amazon DynamoDB Developer Guide
.NET: Document Model

} while (!search.IsDone);

private static void PrintDocument(Document document)


{
Console.WriteLine();
foreach (var attribute in document.GetAttributeNames())
{
string stringValue = null;
var value = document[attribute];
if (value is Primitive)
stringValue = value.AsPrimitive().Value;
else if (value is PrimitiveList)
stringValue = string.Join(",", (from primitive
in value.AsPrimitiveList().Entries
select primitive.Value).ToArray());
Console.WriteLine("{0} - {1}", attribute, stringValue);
}
}

Specifying Optional Parameters

You can also specify optional parameters for Query, such as specifying a list of attributes to retrieve,
strongly consistent reads, page size, and the number of items returned per page. For a complete list of
parameters, see Query. To specify optional parameters, you must use the following overload in which
you provide the QueryOperationConfig object.

Example

Query(QueryOperationConfig config);

Assume that you want to execute the query in the preceding example (retrieve forum replies posted in
the last 15 days). However, assume that you want to provide optional query parameters to retrieve only
specific attributes and also request a strongly consistent read. The following C# code example constructs
the request using the QueryOperationConfig object.

Example

Table table = Table.LoadTable(client, "Reply");


DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
QueryOperationConfig config = new QueryOperationConfig()
{
HashKey = "DynamoDB Thread 2", //Partition key
AttributesToGet = new List<string>
{ "Subject", "ReplyDateTime", "PostedBy" },
ConsistentRead = true,
Filter = new RangeFilter(QueryOperator.GreaterThan, twoWeeksAgoDate)
};

Search search = table.Query(config);

Example: Query Using the Table.Query Method

The following C# code example uses the Table.Query method to execute the following sample queries.

• The following queries are executed against the Reply table.


• Find forum thread replies that were posted in the last 15 days.

This query is executed twice. In the first Table.Query call, the example provides only the required
query parameters. In the second Table.Query call, you provide optional query parameters to
request a strongly consistent read and a list of attributes to retrieve.

API Version 2012-08-10


291
Amazon DynamoDB Developer Guide
.NET: Document Model

• Find forum thread replies posted during a period of time.

This query uses the Between query operator to find replies posted in between two dates.
• Get a product from the ProductCatalog table.

Because the ProductCatalog table has a primary key that is only a partition key, you can only get
items; you cannot query the table. The example retrieves a specific product item using the item Id.

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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
class MidLevelQueryAndScan
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
// Query examples.
Table replyTable = Table.LoadTable(client, "Reply");
string forumName = "Amazon DynamoDB";
string threadSubject = "DynamoDB Thread 2";
FindRepliesInLast15Days(replyTable, forumName, threadSubject);
FindRepliesInLast15DaysWithConfig(replyTable, forumName, threadSubject);
FindRepliesPostedWithinTimePeriod(replyTable, forumName, threadSubject);

// Get Example.
Table productCatalogTable = Table.LoadTable(client, "ProductCatalog");
int productId = 101;
GetProduct(productCatalogTable, productId);

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }
}

API Version 2012-08-10


292
Amazon DynamoDB Developer Guide
.NET: Document Model

private static void GetProduct(Table tableName, int productId)


{
Console.WriteLine("*** Executing GetProduct() ***");
Document productDocument = tableName.GetItem(productId);
if (productDocument != null)
{
PrintDocument(productDocument);
}
else
{
Console.WriteLine("Error: product " + productId + " does not exist");
}
}

private static void FindRepliesInLast15Days(Table table, string forumName, string


threadSubject)
{
string Attribute = forumName + "#" + threadSubject;

DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);


QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, partitionKey);
filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan,
twoWeeksAgoDate);

// Use Query overloads that takes the minimum required query parameters.
Search search = table.Query(filter);

List<Document> documentSet = new List<Document>();


do
{
documentSet = search.GetNextSet();
Console.WriteLine("\nFindRepliesInLast15Days: printing ............");
foreach (var document in documentSet)
PrintDocument(document);
} while (!search.IsDone);
}

private static void FindRepliesPostedWithinTimePeriod(Table table, string


forumName, string threadSubject)
{
DateTime startDate = DateTime.UtcNow.Subtract(new TimeSpan(21, 0, 0, 0));
DateTime endDate = DateTime.UtcNow.Subtract(new TimeSpan(1, 0, 0, 0));

QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#"


+ threadSubject);
filter.AddCondition("ReplyDateTime", QueryOperator.Between, startDate,
endDate);

QueryOperationConfig config = new QueryOperationConfig()


{
Limit = 2, // 2 items/page.
Select = SelectValues.SpecificAttributes,
AttributesToGet = new List<string> { "Message",
"ReplyDateTime",
"PostedBy" },
ConsistentRead = true,
Filter = filter
};

Search search = table.Query(config);

List<Document> documentList = new List<Document>();

do
{
documentList = search.GetNextSet();

API Version 2012-08-10


293
Amazon DynamoDB Developer Guide
.NET: Document Model

Console.WriteLine("\nFindRepliesPostedWithinTimePeriod: printing replies


posted within dates: {0} and {1} ............", startDate, endDate);
foreach (var document in documentList)
{
PrintDocument(document);
}
} while (!search.IsDone);
}

private static void FindRepliesInLast15DaysWithConfig(Table table, string


forumName, string threadName)
{
DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
QueryFilter filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#"
+ threadName);
filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan,
twoWeeksAgoDate);
// You are specifying optional parameters so use QueryOperationConfig.
QueryOperationConfig config = new QueryOperationConfig()
{
Filter = filter,
// Optional parameters.
Select = SelectValues.SpecificAttributes,
AttributesToGet = new List<string> { "Message", "ReplyDateTime",
"PostedBy" },
ConsistentRead = true
};

Search search = table.Query(config);

List<Document> documentSet = new List<Document>();


do
{
documentSet = search.GetNextSet();
Console.WriteLine("\nFindRepliesInLast15DaysWithConfig:
printing ............");
foreach (var document in documentSet)
PrintDocument(document);
} while (!search.IsDone);
}

private static void PrintDocument(Document document)


{
// count++;
Console.WriteLine();
foreach (var attribute in document.GetAttributeNames())
{
string stringValue = null;
var value = document[attribute];
if (value is Primitive)
stringValue = value.AsPrimitive().Value.ToString();
else if (value is PrimitiveList)
stringValue = string.Join(",", (from primitive
in value.AsPrimitiveList().Entries
select primitive.Value).ToArray());
Console.WriteLine("{0} - {1}", attribute, stringValue);
}
}
}

Table.Scan Method in the AWS SDK for .NET


The Scan method performs a full table scan. It provides two overloads. The only parameter required by
the Scan method is the scan filter, which you can provide using the following overload.

API Version 2012-08-10


294
Amazon DynamoDB Developer Guide
.NET: Document Model

Example

Scan(ScanFilter filter);

For example, assume that you maintain a table of forum threads tracking information such as thread
subject (primary), the related message, forum Id to which the thread belongs, Tags, and other
information. Assume that the subject is the primary key.

Example

Thread(Subject, Message, ForumId, Tags, LastPostedDateTime, .... )

This is a simplified version of forums and threads that you see on AWS forums (see Discussion Forums).
The following C# code example queries all threads in a specific forum (ForumId = 101) that are tagged
"sortkey". Because the ForumId is not a primary key, the example scans the table. The ScanFilter
includes two conditions. The query returns all the threads that satisfy both of the conditions.

Example

string tableName = "Thread";


Table ThreadTable = Table.LoadTable(client, tableName);

ScanFilter scanFilter = new ScanFilter();


scanFilter.AddCondition("ForumId", ScanOperator.Equal, 101);
scanFilter.AddCondition("Tags", ScanOperator.Contains, "sortkey");

Search search = ThreadTable.Scan(scanFilter);

Specifying Optional Parameters


You also can specify optional parameters to Scan, such as a specific list of attributes to retrieve or
whether to perform a strongly consistent read. To specify optional parameters, you must create a
ScanOperationConfig object that includes both the required and optional parameters and use the
following overload.

Example

Scan(ScanOperationConfig config);

The following C# code example executes the same preceding query (find forum threads in which
the ForumId is 101 and the Tag attribute contains the "sortkey" keyword). Assume that you want
to add an optional parameter to retrieve only a specific attribute list. In this case, you must create a
ScanOperationConfig object by providing all the parameters, required and optional parameters, as
shown in the following code example.

Example

string tableName = "Thread";


Table ThreadTable = Table.LoadTable(client, tableName);

ScanFilter scanFilter = new ScanFilter();


scanFilter.AddCondition("ForumId", ScanOperator.Equal, forumId);
scanFilter.AddCondition("Tags", ScanOperator.Contains, "sortkey");

ScanOperationConfig config = new ScanOperationConfig()


{
AttributesToGet = new List<string> { "Subject", "Message" } ,
Filter = scanFilter
};

API Version 2012-08-10


295
Amazon DynamoDB Developer Guide
.NET: Document Model

Search search = ThreadTable.Scan(config);

Example: Scan Using the Table.Scan Method


The Scan operation performs a full table scan making it a potentially expensive operation. You should
use queries instead. However, there are times when you might need to execute a scan against a table. For
example, you might have a data entry error in the product pricing, and you must scan the table as shown
in the following C# code example. The example scans the ProductCatalog table to find products for
which the price value is less than 0. The example illustrates the use of the two Table.Scan overloads.

• Table.Scan that takes the ScanFilter object as a parameter.

You can pass the ScanFilter parameter when passing in only the required parameters.
• Table.Scan that takes the ScanOperationConfig object as a parameter.

You must use the ScanOperationConfig parameter if you want to pass any optional parameters to
the Scan method.

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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

namespace com.amazonaws.codesamples
{
class MidLevelScanOnly
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
Table productCatalogTable = Table.LoadTable(client, "ProductCatalog");
// Scan example.
FindProductsWithNegativePrice(productCatalogTable);
FindProductsWithNegativePriceWithConfig(productCatalogTable);

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void FindProductsWithNegativePrice(Table productCatalogTable)


{
// Assume there is a price error. So we scan to find items priced < 0.
ScanFilter scanFilter = new ScanFilter();

API Version 2012-08-10


296
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

scanFilter.AddCondition("Price", ScanOperator.LessThan, 0);

Search search = productCatalogTable.Scan(scanFilter);

List<Document> documentList = new List<Document>();


do
{
documentList = search.GetNextSet();
Console.WriteLine("\nFindProductsWithNegativePrice:
printing ............");
foreach (var document in documentList)
PrintDocument(document);
} while (!search.IsDone);
}

private static void FindProductsWithNegativePriceWithConfig(Table


productCatalogTable)
{
// Assume there is a price error. So we scan to find items priced < 0.
ScanFilter scanFilter = new ScanFilter();
scanFilter.AddCondition("Price", ScanOperator.LessThan, 0);

ScanOperationConfig config = new ScanOperationConfig()


{
Filter = scanFilter,
Select = SelectValues.SpecificAttributes,
AttributesToGet = new List<string> { "Title", "Id" }
};

Search search = productCatalogTable.Scan(config);

List<Document> documentList = new List<Document>();


do
{
documentList = search.GetNextSet();
Console.WriteLine("\nFindProductsWithNegativePriceWithConfig:
printing ............");
foreach (var document in documentList)
PrintDocument(document);
} while (!search.IsDone);
}

private static void PrintDocument(Document document)


{
// count++;
Console.WriteLine();
foreach (var attribute in document.GetAttributeNames())
{
string stringValue = null;
var value = document[attribute];
if (value is Primitive)
stringValue = value.AsPrimitive().Value.ToString();
else if (value is PrimitiveList)
stringValue = string.Join(",", (from primitive
in value.AsPrimitiveList().Entries
select primitive.Value).ToArray());
Console.WriteLine("{0} - {1}", attribute, stringValue);
}
}
}

.NET: Object Persistence Model


Topics

API Version 2012-08-10


297
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

• DynamoDB Attributes (p. 299)


• DynamoDBContext Class (p. 301)
• Supported Data Types (p. 306)
• Optimistic Locking Using a Version Number with DynamoDB Using the AWS SDK for .NET Object
Persistence Model (p. 307)
• Mapping Arbitrary Data with DynamoDB Using the AWS SDK for .NET Object Persistence
Model (p. 308)
• Batch Operations Using the AWS SDK for .NET Object Persistence Model (p. 311)
• Example: CRUD Operations Using the AWS SDK for .NET Object Persistence Model (p. 314)
• Example: Batch Write Operation Using the AWS SDK for .NET Object Persistence Model (p. 316)
• Example: Query and Scan in DynamoDB Using the AWS SDK for .NET Object Persistence
Model (p. 321)

The AWS SDK for .NET provides an object persistence model that enables you to map your client-side
classes to Amazon DynamoDB tables. Each object instance then maps to an item in the corresponding
tables. To save your client-side objects to the tables, the object persistence model provides the
DynamoDBContext class, an entry point to DynamoDB. This class provides you a connection to
DynamoDB and enables you to access tables, perform various CRUD operations, and execute queries.

The object persistence model provides a set of attributes to map client-side classes to tables, and
properties/fields to table attributes.
Note
The object persistence model does not provide an API to create, update, or delete tables.
It provides only data operations. You can use only the AWS SDK for .NET low-level API to
create, update, and delete tables. For more information, see Working with DynamoDB Tables
in .NET (p. 368).

The following example shows how the object persistence model works. It starts with the
ProductCatalog table. It has Id as the primary key.

ProductCatalog(Id, ...)

Suppose that you have a Book class with Title, ISBN, and Authors properties. You can map the Book
class to the ProductCatalog table by adding the attributes defined by the object persistence model, as
shown in the following C# code example.

Example

[DynamoDBTable("ProductCatalog")]
public class Book
{
[DynamoDBHashKey]
public int Id { get; set; }

public string Title { get; set; }


public int ISBN { get; set; }

[DynamoDBProperty("Authors")]
public List<string> BookAuthors { get; set; }

[DynamoDBIgnore]
public string CoverPage { get; set; }
}

In the preceding example, the DynamoDBTable attribute maps the Book class to the ProductCatalog
table.

API Version 2012-08-10


298
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

The object persistence model supports both the explicit and default mapping between class properties
and table attributes.

• Explicit mapping—To map a property to a primary key, you must use the DynamoDBHashKey and
DynamoDBRangeKey object persistence model attributes. Additionally, for the nonprimary key
attributes, if a property name in your class and the corresponding table attribute to which you want to
map it are not the same, you must define the mapping by explicitly adding the DynamoDBProperty
attribute.

In the preceding example, the Id property maps to the primary key with the same name, and the
BookAuthors property maps to the Authors attribute in the ProductCatalog table.
• Default mapping—By default, the object persistence model maps the class properties to the
attributes with the same name in the table.

In the preceding example, the properties Title and ISBN map to the attributes with the same name
in the ProductCatalog table.

You don't have to map every single class property. You identify these properties by adding the
DynamoDBIgnore attribute. When you save a Book instance to the table, the DynamoDBContext does
not include the CoverPage property. It also does not return this property when you retrieve the book
instance.

You can map properties of .NET primitive types such as int and string. You also can map any arbitrary
data types as long as you provide an appropriate converter to map the arbitrary data to one of the
DynamoDB types. To learn about mapping arbitrary types, see Mapping Arbitrary Data with DynamoDB
Using the AWS SDK for .NET Object Persistence Model (p. 308).

The object persistence model supports optimistic locking. During an update operation, this ensures
that you have the latest copy of the item you are about to update. For more information, see Optimistic
Locking Using a Version Number with DynamoDB Using the AWS SDK for .NET Object Persistence
Model (p. 307).

DynamoDB Attributes
This section describes the attributes that the object persistence model offers so that you can map your
classes and properties to DynamoDB tables and attributes.
Note
In the following attributes, only DynamoDBTable and DynamoDBHashKey are required.

DynamoDBGlobalSecondaryIndexHashKey
Maps a class property to the partition key of a global secondary index. Use this attribute if you need to
Query a global secondary index.

DynamoDBGlobalSecondaryIndexRangeKey
Maps a class property to the sort key of a global secondary index. Use this attribute if you need to Query
a global secondary index and want to refine your results using the index sort key.

DynamoDBHashKey
Maps a class property to the partition key of the table's primary key. The primary key attributes cannot
be a collection type.

The following C# code example maps the Book class to the ProductCatalog table, and the Id property
to the table's primary key partition key.

API Version 2012-08-10


299
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

[DynamoDBTable("ProductCatalog")]
public class Book {
[DynamoDBHashKey]
public int Id { get; set; }

// Additional properties go here.


}

DynamoDBIgnore
Indicates that the associated property should be ignored. If you don't want to save any of your class
properties, you can add this attribute to instruct DynamoDBContext not to include this property when
saving objects to the table.

DynamoDBLocalSecondaryIndexRangeKey
Maps a class property to the sort key of a local secondary index. Use this attribute if you need to Query a
local secondary index and want to refine your results using the index sort key.

DynamoDBProperty
Maps a class property to a table attribute. If the class property maps to a table attribute of the same
name, you don't need to specify this attribute. However, if the names are not the same, you can use
this tag to provide the mapping. In the following C# statement, the DynamoDBProperty maps the
BookAuthors property to the Authors attribute in the table.

[DynamoDBProperty("Authors")]
public List<string> BookAuthors { get; set; }

DynamoDBContext uses this mapping information to create the Authors attribute when saving object
data to the corresponding table.

DynamoDBRenamable
Specifies an alternative name for a class property. This is useful if you are writing a custom converter
for mapping arbitrary data to a DynamoDB table where the name of a class property is different from a
table attribute.

DynamoDBRangeKey
Maps a class property to the sort key of the table's primary key. If the table has a composite primary key
(partition key and sort key), you must specify both the DynamoDBHashKey and DynamoDBRangeKey
attributes in your class mapping.

For example, the sample table Reply has a primary key made of the Id partition key and
Replenishment sort key. The following C# code example maps the Reply class to the Reply table. The
class definition also indicates that two of its properties map to the primary key.

For more information about sample tables, see Creating Tables and Loading Data for Code Examples in
DynamoDB (p. 326).

[DynamoDBTable("Reply")]
public class Reply {
[DynamoDBHashKey]
public int ThreadId { get; set; }
[DynamoDBRangeKey]
public string Replenishment { get; set; }

API Version 2012-08-10


300
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

// Additional properties go here.


}

DynamoDBTable
Identifies the target table in DynamoDB to which the class maps. For example, the following C# code
example maps the Developer class to the People table in DynamoDB.

[DynamoDBTable("People")]
public class Developer { ...}

This attribute can be inherited or overridden.

• The DynamoDBTable attribute can be inherited. In the preceding example, if you add a new class,
Lead, that inherits from the Developer class, it also maps to the People table. Both the Developer
and Lead objects are stored in the People table.
• The DynamoDBTable attribute can also be overridden. In the following C# code example, the Manager
class inherits from the Developer class. However, the explicit addition of the DynamoDBTable
attribute maps the class to another table (Managers).

[DynamoDBTable("Managers")]
public class Manager : Developer { ...}

You can add the optional parameter, LowerCamelCaseProperties, to request DynamoDB to make the
first letter of the property name lowercase when storing the objects to a table, as shown in the following
C# example.

[DynamoDBTable("People", LowerCamelCaseProperties=true)]
public class Developer {
string DeveloperName;
...}

When saving instances of the Developer class, DynamoDBContext saves the DeveloperName property
as the developerName.

DynamoDBVersion
Identifies a class property for storing the item version number. For more information about versioning,
see Optimistic Locking Using a Version Number with DynamoDB Using the AWS SDK for .NET Object
Persistence Model (p. 307).

DynamoDBContext Class
The DynamoDBContext class is the entry point to the Amazon DynamoDB database. It provides a
connection to DynamoDB and enables you to access your data in various tables, perform various CRUD
operations, and execute queries. The DynamoDBContext class provides the following methods.

CreateMultiTableBatchGet
Creates a MultiTableBatchGet object, composed of multiple individual BatchGet objects. Each of
these BatchGet objects can be used for retrieving items from a single DynamoDB table.

To retrieve the items from tables, use the ExecuteBatchGet method, passing the
MultiTableBatchGet object as a parameter.

API Version 2012-08-10


301
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

CreateMultiTableBatchWrite
Creates a MultiTableBatchWrite object, composed of multiple individual BatchWrite objects. Each
of these BatchWrite objects can be used for writing or deleting items in a single DynamoDB table.

To write to tables, use the ExecuteBatchWrite method, passing the MultiTableBatchWrite object
as a parameter.

CreateBatchGet
Creates a BatchGet object that you can use to retrieve multiple items from a table. For more
information, see Batch Get: Getting Multiple Items (p. 313).

CreateBatchWrite
Creates a BatchWrite object that you can use to put multiple items into a table, or to delete multiple
items from a table. For more information, see Batch Write: Putting and Deleting Multiple Items
(p. 311).

Delete
Deletes an item from the table. The method requires the primary key of the item you want to delete.
You can provide either the primary key value or a client-side object containing a primary key value as a
parameter to this method.

• If you specify a client-side object as a parameter and you have enabled optimistic locking, the delete
succeeds only if the client-side and the server-side versions of the object match.
• If you specify only the primary key value as a parameter, the delete succeeds regardless of whether
you have enabled optimistic locking or not.

Note
To perform this operation in the background, use the DeleteAsync method instead.

Dispose
Disposes of all managed and unmanaged resources.

ExecuteBatchGet
Reads data from one or more tables, processing all of the BatchGet objects in a
MultiTableBatchGet.
Note
To perform this operation in the background, use the ExecuteBatchGetAsync method
instead.

ExecuteBatchWrite
Writes or deletes data in one or more tables, processing all of the BatchWrite objects in a
MultiTableBatchWrite.
Note
To perform this operation in the background, use the ExecuteBatchWriteAsync method
instead.

FromDocument
Given an instance of a Document, the FromDocument method returns an instance of a client-side class.

API Version 2012-08-10


302
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

This is helpful if you want to use the document model classes along with the object persistence model to
perform any data operations. For more information about the document model classes provided by the
AWS SDK for .NET, see .NET: Document Model (p. 276).

Suppose that you have a Document object named doc, that contains a representation of a Forum item.
(To see how to construct this object, see the description for the ToDocument method later in this topic.)
You can use FromDocument to retrieve the Forum item from the Document, as shown in the following
C# code example.

Example

forum101 = context.FromDocument<Forum>(101);

Note
If your Document object implements the IEnumerable interface, you can use the
FromDocuments method instead. This allows you to iterate over all of the class instances in the
Document.

FromQuery
Executes a Query operation, with the query parameters defined in a QueryOperationConfig object.
Note
To perform this operation in the background, use the FromQueryAsync method instead.

FromScan
Executes a Scan operation, with the scan parameters defined in a ScanOperationConfig object.
Note
To perform this operation in the background, use the FromScanAsync method instead.

GetTargetTable
Retrieves the target table for the specified type. This is useful if you are writing a custom converter for
mapping arbitrary data to a DynamoDB table, and you need to determine which table is associated with
a custom data type.

Load
Retrieves an item from a table. The method requires only the primary key of the item you want to
retrieve.

By default, DynamoDB returns the item with values that are eventually consistent. For information about
the eventual consistency model, see Read Consistency (p. 16).
Note
To perform this operation in the background, use the LoadAsync method instead.

Query
Queries a table based on query parameters you provide.

You can query a table only if it has a composite primary key (partition key and sort key). When querying,
you must specify a partition key and a condition that applies to the sort key.

Suppose that you have a client-side Reply class mapped to the Reply table in DynamoDB. The
following C# code example queries the Reply table to find forum thread replies posted in the past 15
days. The Reply table has a primary key that has the Id partition key and the ReplyDateTime sort key.
For more information about the Reply table, see Creating Tables and Loading Data for Code Examples in
DynamoDB (p. 326).

API Version 2012-08-10


303
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

Example

DynamoDBContext context = new DynamoDBContext(client);

string replyId = "DynamoDB#DynamoDB Thread 1"; //Partition key


DateTime twoWeeksAgoDate = DateTime.UtcNow.Subtract(new TimeSpan(14, 0, 0, 0)); // Date to
compare.
IEnumerable<Reply> latestReplies = context.Query<Reply>(replyId, QueryOperator.GreaterThan,
twoWeeksAgoDate);

This returns a collection of Reply objects.

The Query method returns a "lazy-loaded" IEnumerable 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, you
need to iterate only over the IEnumerable.

If your table has a simple primary key (partition key), you can't use the Query method. Instead, you can
use the Load method and provide the partition key to retrieve the item.
Note
To perform this operation in the background, use the QueryAsync method instead.

Save
Saves the specified object to the table. If the primary key specified in the input object doesn't exist in
the table, the method adds a new item to the table. If the primary key exists, the method updates the
existing item.

If you have optimistic locking configured, the update succeeds only if the client and the server-side
versions of the item match. For more information, see Optimistic Locking Using a Version Number with
DynamoDB Using the AWS SDK for .NET Object Persistence Model (p. 307).
Note
To perform this operation in the background, use the SaveAsync method instead.

Scan
Performs an entire table scan.

You can filter scan results by specifying a scan condition. The condition can be evaluated on any
attributes in the table. Suppose that you have a client-side class Book mapped to the ProductCatalog
table in DynamoDB. The following C# example scans the table and returns only the book items priced
less than 0.

Example

IEnumerable<Book> itemsWithWrongPrice = context.Scan<Book>(


new ScanCondition("Price", ScanOperator.LessThan, price),
new ScanCondition("ProductCategory", ScanOperator.Equal, "Book")
);

The Scan method returns a "lazy-loaded" IEnumerable 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, you
only need to iterate over the IEnumerable.

For performance reasons, you should query your tables and avoid a table scan.
Note
To perform this operation in the background, use the ScanAsync method instead.

API Version 2012-08-10


304
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

ToDocument
Returns an instance of the Document document model class from your class instance.

This is helpful if you want to use the document model classes along with the object persistence model to
perform any data operations. For more information about the document model classes provided by the
AWS SDK for .NET, see .NET: Document Model (p. 276).

Suppose that you have a client-side class mapped to the sample Forum table. You can then use a
DynamoDBContext to get an item as a Document object from the Forum table, as shown in the
following C# code example.

Example

DynamoDBContext context = new DynamoDBContext(client);

Forum forum101 = context.Load<Forum>(101); // Retrieve a forum by primary key.


Document doc = context.ToDocument<Forum>(forum101);

Specifying Optional Parameters for DynamoDBContext


When using the object persistence model, you can specify the following optional parameters for the
DynamoDBContext.

• ConsistentRead—When retrieving data using the Load, Query, or Scan operations, you can add
this optional parameter to request the latest values for the data.
• IgnoreNullValues—This parameter informs DynamoDBContext to ignore null values on attributes
during a Save operation. If this parameter is false (or if it is not set), then a null value is interpreted as
a directive to delete the specific attribute.
• SkipVersionCheck— This parameter informs DynamoDBContext not to compare versions when
saving or deleting an item. For more information about versioning, see Optimistic Locking Using a
Version Number with DynamoDB Using the AWS SDK for .NET Object Persistence Model (p. 307).
• TableNamePrefix— Prefixes all table names with a specific string. If this parameter is null (or if it is
not set), then no prefix is used.

The following C# example creates a new DynamoDBContext by specifying two of the preceding optional
parameters.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


...
DynamoDBContext context =
new DynamoDBContext(client, new DynamoDBContextConfig { ConsistentRead = true,
SkipVersionCheck = true});

DynamoDBContext includes these optional parameters with each request that you send using this
context.

Instead of setting these parameters at the DynamoDBContext level, you can specify them for individual
operations you execute using DynamoDBContext, as shown in the following C# code example. The
example loads a specific book item. The Load method of DynamoDBContext specifies the preceding
optional parameters.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

API Version 2012-08-10


305
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

...
DynamoDBContext context = new DynamoDBContext(client);
Book bookItem = context.Load<Book>(productId,new DynamoDBContextConfig{ ConsistentRead =
true, SkipVersionCheck = true });

In this case, DynamoDBContext includes these parameters only when sending the Get request.

Supported Data Types


The object persistence model supports a set of primitive .NET data types, collections, and arbitrary data
types. The model supports the following primitive data types.

• bool
• byte
• char
• DateTime
• decimal
• double
• float
• Int16
• Int32
• Int64
• SByte
• string
• UInt16
• UInt32
• UInt64

The object persistence model also supports the .NET collection types. DynamoDBContext is able to
convert concrete collection types and simple Plain Old CLR Objects (POCOs).

The following table summarizes the mapping of the preceding .NET types to the DynamoDB types.

.NET primitive type DynamoDB type

All number types N (number type)

All string types S (string type)

MemoryStream, byte[] B (binary type)

bool N (number type). 0 represents false and 1


represents true.

Collection types BS (binary set) type, SS (string set) type, and NS


(number set) type

DateTime S (string type). The DateTime values are stored as


ISO-8601 formatted strings.

The object persistence model also supports arbitrary data types. However, you must provide converter
code to map the complex types to the DynamoDB types.

API Version 2012-08-10


306
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

Optimistic Locking Using a Version Number with DynamoDB


Using the AWS SDK for .NET Object Persistence Model
Optimistic locking support in the object persistence model ensures that the item version for your
application is the same as the item version on the server side before updating or deleting the item.
Suppose that you retrieve an item for update. However, before you send your updates back, some other
application updates the same item. Now your application has a stale copy of the item. Without optimistic
locking, any update you perform will overwrite the update made by the other application.

The optimistic locking feature of the object persistence model provides the DynamoDBVersion tag
that you can use to enable optimistic locking. To use this feature, you add a property to your class for
storing the version number. You add the DynamoDBVersion attribute to the property. When you first
save the object, the DynamoDBContext assigns a version number and increments this value each time
you update the item.

Your update or delete request succeeds only if the client-side object version matches the corresponding
version number of the item on the server side. If your application has a stale copy, it must get the latest
version from the server before it can update or delete that item.

The following C# code example defines a Book class with object persistence attributes mapping
it to the ProductCatalog table. The VersionNumber property in the class decorated with the
DynamoDBVersion attribute stores the version number value.

Example

[DynamoDBTable("ProductCatalog")]
public class Book
{
[DynamoDBHashKey] //Partition key
public int Id { get; set; }
[DynamoDBProperty]
public string Title { get; set; }
[DynamoDBProperty]
public string ISBN { get; set; }
[DynamoDBProperty("Authors")]
public List<string> BookAuthors { get; set; }
[DynamoDBVersion]
public int? VersionNumber { get; set; }
}

Note
You can apply the DynamoDBVersion attribute only to a nullable numeric primitive type (such
as int?).

Optimistic locking has the following impact on DynamoDBContext operations:

• For a new item, DynamoDBContext assigns initial version number 0. If you retrieve an existing item,
update one or more of its properties, and try to save the changes, the save operation succeeds only if
the version number on the client side and the server side match. DynamoDBContext increments the
version number. You don't need to set the version number.
• The Delete method provides overloads that can take either a primary key value or an object as
parameter, as shown in the following C# code example.

Example

DynamoDBContext context = new DynamoDBContext(client);


...

API Version 2012-08-10


307
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

// Load a book.
Book book = context.Load<ProductCatalog>(111);
// Do other operations.
// Delete 1 - Pass in the book object.
context.Delete<ProductCatalog>(book);

// Delete 2 - Pass in the Id (primary key)


context.Delete<ProductCatalog>(222);

If you provide an object as the parameter, the delete succeeds only if the object version matches the
corresponding server-side item version. However, if you provide a primary key value as the parameter,
DynamoDBContext is unaware of any version numbers, and it deletes the item without making the
version check.

Note that the internal implementation of optimistic locking in the object persistence model code uses
the conditional update and the conditional delete API actions in DynamoDB.

Disabling Optimistic Locking


To disable optimistic locking, you use the SkipVersionCheck configuration property. You can set
this property when creating DynamoDBContext. In this case, optimistic locking is disabled for any
requests that you make using the context. For more information, see Specifying Optional Parameters for
DynamoDBContext (p. 305).

Instead of setting the property at the context level, you can disable optimistic locking for a specific
operation, as shown in the following C# code example. The example uses the context to delete a book
item. The Delete method sets the optional SkipVersionCheck property to true, disabling version
checking.

Example

DynamoDBContext context = new DynamoDBContext(client);


// Load a book.
Book book = context.Load<ProductCatalog>(111);
...
// Delete the book.
context.Delete<Book>(book, new DynamoDBContextConfig { SkipVersionCheck = true });

Mapping Arbitrary Data with DynamoDB Using the AWS SDK


for .NET Object Persistence Model
In addition to the supported .NET types (see Supported Data Types (p. 306)), you can use types in your
application for which there is no direct mapping to the Amazon DynamoDB types. The object persistence
model supports storing data of arbitrary types as long as you provide the converter to convert data from
the arbitrary type to the DynamoDB type and vice versa. The converter code transforms data during both
the saving and loading of the objects.

You can create any types on the client-side. However the data stored in the tables is one of the
DynamoDB types, and during query and scan, any data comparisons made are against the data stored in
DynamoDB.

The following C# code example defines a Book class with Id, Title, ISBN, and Dimension properties.
The Dimension property is of the DimensionType that describes Height, Width, and Thickness
properties. The example code provides the converter methods ToEntry and FromEntry to convert
data between the DimensionType and the DynamoDB string types. For example, when saving a Book
instance, the converter creates a book Dimension string such as "8.5x11x.05". When you retrieve a book,
it converts the string to a DimensionType instance.

API Version 2012-08-10


308
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

The example maps the Book type to the ProductCatalog table. It saves a sample Book instance,
retrieves it, updates its dimensions, and saves the updated Book again.

For step-by-step instructions for testing the following example, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
class HighLevelMappingArbitraryData
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
DynamoDBContext context = new DynamoDBContext(client);

// 1. Create a book.
DimensionType myBookDimensions = new DimensionType()
{
Length = 8M,
Height = 11M,
Thickness = 0.5M
};

Book myBook = new Book


{
Id = 501,
Title = "AWS SDK for .NET Object Persistence Model Handling Arbitrary
Data",
ISBN = "999-9999999999",
BookAuthors = new List<string> { "Author 1", "Author 2" },
Dimensions = myBookDimensions
};

context.Save(myBook);

// 2. Retrieve the book.


Book bookRetrieved = context.Load<Book>(501);

// 3. Update property (book dimensions).

API Version 2012-08-10


309
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

bookRetrieved.Dimensions.Height += 1;
bookRetrieved.Dimensions.Length += 1;
bookRetrieved.Dimensions.Thickness += 0.2M;
// Update the book.
context.Save(bookRetrieved);

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }
}
}
[DynamoDBTable("ProductCatalog")]
public class Book
{
[DynamoDBHashKey] //Partition key
public int Id
{
get; set;
}
[DynamoDBProperty]
public string Title
{
get; set;
}
[DynamoDBProperty]
public string ISBN
{
get; set;
}
// Multi-valued (set type) attribute.
[DynamoDBProperty("Authors")]
public List<string> BookAuthors
{
get; set;
}
// Arbitrary type, with a converter to map it to DynamoDB type.
[DynamoDBProperty(typeof(DimensionTypeConverter))]
public DimensionType Dimensions
{
get; set;
}
}

public class DimensionType


{
public decimal Length
{
get; set;
}
public decimal Height
{
get; set;
}
public decimal Thickness
{
get; set;
}
}

// Converts the complex type DimensionType to string and vice-versa.


public class DimensionTypeConverter : IPropertyConverter
{
public DynamoDBEntry ToEntry(object value)

API Version 2012-08-10


310
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

{
DimensionType bookDimensions = value as DimensionType;
if (bookDimensions == null) throw new ArgumentOutOfRangeException();

string data = string.Format("{1}{0}{2}{0}{3}", " x ",


bookDimensions.Length, bookDimensions.Height,
bookDimensions.Thickness);

DynamoDBEntry entry = new Primitive


{
Value = data
};
return entry;
}

public object FromEntry(DynamoDBEntry entry)


{
Primitive primitive = entry as Primitive;
if (primitive == null || !(primitive.Value is String) ||
string.IsNullOrEmpty((string)primitive.Value))
throw new ArgumentOutOfRangeException();

string[] data = ((string)(primitive.Value)).Split(new string[] { " x " },


StringSplitOptions.None);
if (data.Length != 3) throw new ArgumentOutOfRangeException();

DimensionType complexData = new DimensionType


{
Length = Convert.ToDecimal(data[0]),
Height = Convert.ToDecimal(data[1]),
Thickness = Convert.ToDecimal(data[2])
};
return complexData;
}
}
}

Batch Operations Using the AWS SDK for .NET Object


Persistence Model
Batch Write: Putting and Deleting Multiple Items
To put or delete multiple objects from a table in a single request, do the following:

• Execute the CreateBatchWrite method of the DynamoDBContext, and create an instance of the
BatchWrite class.
• Specify the items that you want to put or delete.
• To put one or more items, use either the AddPutItem or the AddPutItems method.
• To delete one or more items, you can specify either the primary key of the item or a client-side
object that maps to the item that you want to delete. Use the AddDeleteItem, AddDeleteItems,
and the AddDeleteKey methods to specify the list of items to delete.
• Call the BatchWrite.Execute method to put and delete all the specified items from the table.

Note
When using the object persistence model, you can specify any number of operations in a batch.
However, note that Amazon DynamoDB limits the number of operations in a batch and the
total size of the batch in a batch operation. For more information about the specific limits, see
BatchWriteItem. If the API detects that your batch write request exceeded the allowed number
of write requests or exceeded the maximum allowed HTTP payload size, it breaks the batch into

API Version 2012-08-10


311
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

several smaller batches. Additionally, if a response to a batch write returns unprocessed items,
the API automatically sends another batch request with those unprocessed items.

Suppose that you defined a C# class Book class that maps to the ProductCatalog table in DynamoDB.
The following C# code example uses the BatchWrite object to upload two items and delete one item
from the ProductCatalog table.

Example

DynamoDBContext context = new DynamoDBContext(client);


var bookBatch = context.CreateBatchWrite<Book>();

// 1. Specify two books to add.


Book book1 = new Book
{
Id = 902,
ISBN = "902-11-11-1111",
ProductCategory = "Book",
Title = "My book3 in batch write"
};
Book book2 = new Book
{
Id = 903,
ISBN = "903-11-11-1111",
ProductCategory = "Book",
Title = "My book4 in batch write"
};

bookBatch.AddPutItems(new List<Book> { book1, book2 });

// 2. Specify one book to delete.


bookBatch.AddDeleteKey(111);

bookBatch.Execute();

To put or delete objects from multiple tables, do the following:

• Create one instance of the BatchWrite class for each type and specify the items you want to put or
delete as described in the preceding section.
• Create an instance of MultiTableBatchWrite using one of the following methods:
• Execute the Combine method on one of the BatchWrite objects that you created in the preceding
step.
• Create an instance of the MultiTableBatchWrite type by providing a list of BatchWrite objects.
• Execute the CreateMultiTableBatchWrite method of DynamoDBContext and pass in your list
of BatchWrite objects.
• Call the Execute method of MultiTableBatchWrite, which performs the specified put and delete
operations on various tables.

Suppose that you defined Forum and Thread C# classes that map to the Forum and Thread tables
in DynamoDB. Also, suppose that the Thread class has versioning enabled. Because versioning is not
supported when using batch operations, you must explicitly disable versioning as shown in the following
C# code example. The example uses the MultiTableBatchWrite object to perform a multi-table
update.

Example

DynamoDBContext context = new DynamoDBContext(client);

API Version 2012-08-10


312
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

// Create BatchWrite objects for each of the Forum and Thread classes.
var forumBatch = context.CreateBatchWrite<Forum>();

DynamoDBOperationConfig config = new DynamoDBOperationConfig();


config.SkipVersionCheck = true;
var threadBatch = context.CreateBatchWrite<Thread>(config);

// 1. New Forum item.


Forum newForum = new Forum
{
Name = "Test BatchWrite Forum",
Threads = 0
};
forumBatch.AddPutItem(newForum);

// 2. Specify a forum to delete by specifying its primary key.


forumBatch.AddDeleteKey("Some forum");

// 3. New Thread item.


Thread newThread = new Thread
{
ForumName = "Amazon S3 forum",
Subject = "My sample question",
KeywordTags = new List<string> { "Amazon S3", "Bucket" },
Message = "Message text"
};

threadBatch.AddPutItem(newThread);

// Now execute multi-table batch write.


var superBatch = new MultiTableBatchWrite(forumBatch, threadBatch);
superBatch.Execute();

For a working example, see Example: Batch Write Operation Using the AWS SDK for .NET Object
Persistence Model (p. 316).
Note
The DynamoDB batch API limits the number of writes in a batch and also limits the size of the
batch. For more information, see BatchWriteItem. When using the .NET object persistence model
API, you can specify any number of operations. However, if either the number of operations in
a batch or the size exceeds the limit, the .NET API breaks the batch write request into smaller
batches and sends multiple batch write requests to DynamoDB.

Batch Get: Getting Multiple Items


To retrieve multiple items from a table in a single request, do the following:

• Create an instance of the CreateBatchGet class.


• Specify a list of primary keys to retrieve.
• Call the Execute method. The response returns the items in the Results property.

The following C# code example retrieves three items from the ProductCatalog table. The items in the
result are not necessarily in the same order in which you specified the primary keys.

Example

DynamoDBContext context = new DynamoDBContext(client);


var bookBatch = context.CreateBatchGet<ProductCatalog>();
bookBatch.AddKey(101);
bookBatch.AddKey(102);
bookBatch.AddKey(103);

API Version 2012-08-10


313
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

bookBatch.Execute();
// Process result.
Console.WriteLine(bookBatch.Results.Count);
Book book1 = bookBatch.Results[0];
Book book2 = bookBatch.Results[1];
Book book3 = bookBatch.Results[2];

To retrieve objects from multiple tables, do the following:

• For each type, create an instance of the CreateBatchGet type and provide the primary key values
you want to retrieve from each table.
• Create an instance of the MultiTableBatchGet class using one of the following methods:
• Execute the Combine method on one of the BatchGet objects you created in the preceding step.
• Create an instance of the MultiBatchGet type by providing a list of BatchGet objects.
• Execute the CreateMultiTableBatchGet method of DynamoDBContext and pass in your list of
BatchGet objects.
• Call the Execute method of MultiTableBatchGet, which returns the typed results in the individual
BatchGet objects.

The following C# code example retrieves multiple items from the Order and OrderDetail tables using
the CreateBatchGet method.

Example

var orderBatch = context.CreateBatchGet<Order>();


orderBatch.AddKey(101);
orderBatch.AddKey(102);

var orderDetailBatch = context.CreateBatchGet<OrderDetail>();


orderDetailBatch.AddKey(101, "P1");
orderDetailBatch.AddKey(101, "P2");
orderDetailBatch.AddKey(102, "P3");
orderDetailBatch.AddKey(102, "P1");

var orderAndDetailSuperBatch = orderBatch.Combine(orderDetailBatch);


orderAndDetailSuperBatch.Execute();

Console.WriteLine(orderBatch.Results.Count);
Console.WriteLine(orderDetailBatch.Results.Count);

Order order1 = orderBatch.Results[0];


Order order2 = orderDetailBatch.Results[1];
OrderDetail orderDetail1 = orderDetailBatch.Results[0];

Example: CRUD Operations Using the AWS SDK for .NET Object
Persistence Model
The following C# code example declares a Book class with Id, Title, ISBN, and Authors properties.
The example uses object persistence attributes to map these properties to the ProductCatalog table
in Amazon DynamoDB. The example then uses the DynamoDBContext to illustrate typical create, read,
update, and delete (CRUD) operations. The example creates a sample Book instance and saves it to the
ProductCatalog table. It then retrieves the book item and updates its ISBN and Authors properties.
Note that the update replaces the existing authors list. Finally, the example deletes the book item.

For more information about the ProductCatalog table used in this example, see Creating Tables
and Loading Data for Code Examples in DynamoDB (p. 326). For step-by-step instructions to test the
following example, see .NET Code Examples (p. 333).

API Version 2012-08-10


314
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

Note
The following example doesn't work with .NET core because it doesn't support synchronous
methods. For more information, see AWS Asynchronous APIs for .NET.

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class HighLevelItemCRUD
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
DynamoDBContext context = new DynamoDBContext(client);
TestCRUDOperations(context);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }
}

private static void TestCRUDOperations(DynamoDBContext context)


{
int bookID = 1001; // Some unique value.
Book myBook = new Book
{
Id = bookID,
Title = "object persistence-AWS SDK for.NET SDK-Book 1001",
ISBN = "111-1111111001",
BookAuthors = new List<string> { "Author 1", "Author 2" },
};

// Save the book.


context.Save(myBook);
// Retrieve the book.
Book bookRetrieved = context.Load<Book>(bookID);

// Update few properties.


bookRetrieved.ISBN = "222-2222221001";

API Version 2012-08-10


315
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

bookRetrieved.BookAuthors = new List<string> { " Author 1", "Author x" }; //


Replace existing authors list with this.
context.Save(bookRetrieved);

// Retrieve the updated book. This time add the optional ConsistentRead
parameter using DynamoDBContextConfig object.
Book updatedBook = context.Load<Book>(bookID, new DynamoDBContextConfig
{
ConsistentRead = true
});

// Delete the book.


context.Delete<Book>(bookID);
// Try to retrieve deleted book. It should return null.
Book deletedBook = context.Load<Book>(bookID, new DynamoDBContextConfig
{
ConsistentRead = true
});
if (deletedBook == null)
Console.WriteLine("Book is deleted");
}
}

[DynamoDBTable("ProductCatalog")]
public class Book
{
[DynamoDBHashKey] //Partition key
public int Id
{
get; set;
}
[DynamoDBProperty]
public string Title
{
get; set;
}
[DynamoDBProperty]
public string ISBN
{
get; set;
}
[DynamoDBProperty("Authors")] //String Set datatype
public List<string> BookAuthors
{
get; set;
}
}
}

Example: Batch Write Operation Using the AWS SDK for .NET
Object Persistence Model
The following C# code example declares Book, Forum, Thread, and Reply classes and maps them to
Amazon DynamoDB tables using the object persistence model attributes.

The example then uses the DynamoDBContext to illustrate the following batch write operations:

• BatchWrite object to put and delete book items from the ProductCatalog table.
• MultiTableBatchWrite object to put and delete items from the Forum and the Thread tables.

API Version 2012-08-10


316
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

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 to test the following example, see
.NET Code Examples (p. 333).
Note
The following example doesn't work with .NET core because it doesn't support synchronous
methods. For more information, see AWS Asynchronous APIs for .NET.

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
class HighLevelBatchWriteItem
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
DynamoDBContext context = new DynamoDBContext(client);
SingleTableBatchWrite(context);
MultiTableBatchWrite(context);
}
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void SingleTableBatchWrite(DynamoDBContext context)


{
Book book1 = new Book
{
Id = 902,
InPublication = true,
ISBN = "902-11-11-1111",
PageCount = "100",
Price = 10,
ProductCategory = "Book",
Title = "My book3 in batch write"
};
Book book2 = new Book

API Version 2012-08-10


317
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

{
Id = 903,
InPublication = true,
ISBN = "903-11-11-1111",
PageCount = "200",
Price = 10,
ProductCategory = "Book",
Title = "My book4 in batch write"
};

var bookBatch = context.CreateBatchWrite<Book>();


bookBatch.AddPutItems(new List<Book> { book1, book2 });

Console.WriteLine("Performing batch write in SingleTableBatchWrite().");


bookBatch.Execute();
}

private static void MultiTableBatchWrite(DynamoDBContext context)


{
// 1. New Forum item.
Forum newForum = new Forum
{
Name = "Test BatchWrite Forum",
Threads = 0
};
var forumBatch = context.CreateBatchWrite<Forum>();
forumBatch.AddPutItem(newForum);

// 2. New Thread item.


Thread newThread = new Thread
{
ForumName = "S3 forum",
Subject = "My sample question",
KeywordTags = new List<string> { "S3", "Bucket" },
Message = "Message text"
};

DynamoDBOperationConfig config = new DynamoDBOperationConfig();


config.SkipVersionCheck = true;
var threadBatch = context.CreateBatchWrite<Thread>(config);
threadBatch.AddPutItem(newThread);
threadBatch.AddDeleteKey("some partition key value", "some sort key value");

var superBatch = new MultiTableBatchWrite(forumBatch, threadBatch);


Console.WriteLine("Performing batch write in MultiTableBatchWrite().");
superBatch.Execute();
}
}

[DynamoDBTable("Reply")]
public class Reply
{
[DynamoDBHashKey] //Partition key
public string Id
{
get; set;
}

[DynamoDBRangeKey] //Sort key


public DateTime ReplyDateTime
{
get; set;
}

// Properties included implicitly.


public string Message

API Version 2012-08-10


318
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

{
get; set;
}
// Explicit property mapping with object persistence model attributes.
[DynamoDBProperty("LastPostedBy")]
public string PostedBy
{
get; set;
}
// Property to store version number for optimistic locking.
[DynamoDBVersion]
public int? Version
{
get; set;
}
}

[DynamoDBTable("Thread")]
public class Thread
{
// PK mapping.
[DynamoDBHashKey] //Partition key
public string ForumName
{
get; set;
}
[DynamoDBRangeKey] //Sort key
public String Subject
{
get; set;
}
// Implicit mapping.
public string Message
{
get; set;
}
public string LastPostedBy
{
get; set;
}
public int Views
{
get; set;
}
public int Replies
{
get; set;
}
public bool Answered
{
get; set;
}
public DateTime LastPostedDateTime
{
get; set;
}
// Explicit mapping (property and table attribute names are different.
[DynamoDBProperty("Tags")]
public List<string> KeywordTags
{
get; set;
}
// Property to store version number for optimistic locking.
[DynamoDBVersion]
public int? Version
{

API Version 2012-08-10


319
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

get; set;
}
}

[DynamoDBTable("Forum")]
public class Forum
{
[DynamoDBHashKey] //Partition key
public string Name
{
get; set;
}
// All the following properties are explicitly mapped,
// only to show how to provide mapping.
[DynamoDBProperty]
public int Threads
{
get; set;
}
[DynamoDBProperty]
public int Views
{
get; set;
}
[DynamoDBProperty]
public string LastPostBy
{
get; set;
}
[DynamoDBProperty]
public DateTime LastPostDateTime
{
get; set;
}
[DynamoDBProperty]
public int Messages
{
get; set;
}
}

[DynamoDBTable("ProductCatalog")]
public class Book
{
[DynamoDBHashKey] //Partition key
public int Id
{
get; set;
}
public string Title
{
get; set;
}
public string ISBN
{
get; set;
}
public int Price
{
get; set;
}
public string PageCount
{
get; set;
}
public string ProductCategory

API Version 2012-08-10


320
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

{
get; set;
}
public bool InPublication
{
get; set;
}
}
}

Example: Query and Scan in DynamoDB Using the AWS SDK


for .NET Object Persistence Model
The C# example in this section defines the following classes and maps them to the tables in DynamoDB.
For more information about creating the tables used in this example, see Creating Tables and Loading
Data for Code Examples in DynamoDB (p. 326).

• The Book class maps to the ProductCatalog table.


• The Forum, Thread, and Reply classes map to tables of the same name.

The example then executes the following query and scan operations using DynamoDBContext.

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

For performance reasons, you should use a query operation instead of a 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 is set to less than 0. This example scans the ProductCategory table to find book
items (the ProductCategory is book) at price of less than 0.

For instructions about creating a working sample, see .NET Code Examples (p. 333).
Note
The following example does not work with .NET core because it does not support synchronous
methods. For more information, see AWS Asynchronous APIs for .NET.

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


321
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR


* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Configuration;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class HighLevelQueryAndScan
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
DynamoDBContext context = new DynamoDBContext(client);
// Get an item.
GetBook(context, 101);

// Sample forum and thread to test queries.


string forumName = "Amazon DynamoDB";
string threadSubject = "DynamoDB Thread 1";
// Sample queries.
FindRepliesInLast15Days(context, forumName, threadSubject);
FindRepliesPostedWithinTimePeriod(context, forumName, threadSubject);

// Scan table.
FindProductsPricedLessThanZero(context);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }
}

private static void GetBook(DynamoDBContext context, int productId)


{
Book bookItem = context.Load<Book>(productId);

Console.WriteLine("\nGetBook: Printing result.....");


Console.WriteLine("Title: {0} \n No.Of threads:{1} \n No. of messages: {2}",
bookItem.Title, bookItem.ISBN, bookItem.PageCount);
}

private static void FindRepliesInLast15Days(DynamoDBContext context,


string forumName,
string threadSubject)
{
string replyId = forumName + "#" + threadSubject;
DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);
IEnumerable<Reply> latestReplies =
context.Query<Reply>(replyId, QueryOperator.GreaterThan, twoWeeksAgoDate);
Console.WriteLine("\nFindRepliesInLast15Days: Printing result.....");
foreach (Reply r in latestReplies)
Console.WriteLine("{0}\t{1}\t{2}\t{3}", r.Id, r.PostedBy, r.Message,
r.ReplyDateTime);
}

API Version 2012-08-10


322
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

private static void FindRepliesPostedWithinTimePeriod(DynamoDBContext context,


string forumName,
string threadSubject)
{
string forumId = forumName + "#" + threadSubject;
Console.WriteLine("\nFindRepliesPostedWithinTimePeriod: Printing result.....");

DateTime startDate = DateTime.UtcNow - TimeSpan.FromDays(30);


DateTime endDate = DateTime.UtcNow - TimeSpan.FromDays(1);

IEnumerable<Reply> repliesInAPeriod = context.Query<Reply>(forumId,


QueryOperator.Between, startDate, endDate);
foreach (Reply r in repliesInAPeriod)
Console.WriteLine("{0}\t{1}\t{2}\t{3}", r.Id, r.PostedBy, r.Message,
r.ReplyDateTime);
}

private static void FindProductsPricedLessThanZero(DynamoDBContext context)


{
int price = 0;
IEnumerable<Book> itemsWithWrongPrice = context.Scan<Book>(
new ScanCondition("Price", ScanOperator.LessThan, price),
new ScanCondition("ProductCategory", ScanOperator.Equal, "Book")
);
Console.WriteLine("\nFindProductsPricedLessThanZero: Printing result.....");
foreach (Book r in itemsWithWrongPrice)
Console.WriteLine("{0}\t{1}\t{2}\t{3}", r.Id, r.Title, r.Price, r.ISBN);
}
}

[DynamoDBTable("Reply")]
public class Reply
{
[DynamoDBHashKey] //Partition key
public string Id
{
get; set;
}

[DynamoDBRangeKey] //Sort key


public DateTime ReplyDateTime
{
get; set;
}

// Properties included implicitly.


public string Message
{
get; set;
}
// Explicit property mapping with object persistence model attributes.
[DynamoDBProperty("LastPostedBy")]
public string PostedBy
{
get; set;
}
// Property to store version number for optimistic locking.
[DynamoDBVersion]
public int? Version
{
get; set;
}
}

[DynamoDBTable("Thread")]
public class Thread

API Version 2012-08-10


323
Amazon DynamoDB Developer Guide
.NET: Object Persistence Model

{
// Partition key mapping.
[DynamoDBHashKey] //Partition key
public string ForumName
{
get; set;
}
[DynamoDBRangeKey] //Sort key
public DateTime Subject
{
get; set;
}
// Implicit mapping.
public string Message
{
get; set;
}
public string LastPostedBy
{
get; set;
}
public int Views
{
get; set;
}
public int Replies
{
get; set;
}
public bool Answered
{
get; set;
}
public DateTime LastPostedDateTime
{
get; set;
}
// Explicit mapping (property and table attribute names are different).
[DynamoDBProperty("Tags")]
public List<string> KeywordTags
{
get; set;
}
// Property to store version number for optimistic locking.
[DynamoDBVersion]
public int? Version
{
get; set;
}
}

[DynamoDBTable("Forum")]
public class Forum
{
[DynamoDBHashKey]
public string Name
{
get; set;
}
// All the following properties are explicitly mapped
// to show how to provide mapping.
[DynamoDBProperty]
public int Threads
{
get; set;
}

API Version 2012-08-10


324
Amazon DynamoDB Developer Guide
Running the Code Examples

[DynamoDBProperty]
public int Views
{
get; set;
}
[DynamoDBProperty]
public string LastPostBy
{
get; set;
}
[DynamoDBProperty]
public DateTime LastPostDateTime
{
get; set;
}
[DynamoDBProperty]
public int Messages
{
get; set;
}
}

[DynamoDBTable("ProductCatalog")]
public class Book
{
[DynamoDBHashKey] //Partition key
public int Id
{
get; set;
}
public string Title
{
get; set;
}
public string ISBN
{
get; set;
}
public int Price
{
get; set;
}
public string PageCount
{
get; set;
}
public string ProductCategory
{
get; set;
}
public bool InPublication
{
get; set;
}
}
}

Running the Code Examples in This Developer


Guide
The AWS SDKs provide broad support for Amazon DynamoDB in the following languages:

API Version 2012-08-10


325
Amazon DynamoDB Developer Guide
Load Sample Data

• Java
• JavaScript in the browser
• .NET
• Node.js
• PHP
• Python
• Ruby
• C++
• Go
• Android
• iOS

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

The code examples in this developer guide provide more in-depth coverage of DynamoDB operations,
using the following programming languages:

• Java Code Examples (p. 331)


• .NET Code Examples (p. 333)

Before you can begin with this exercise, you need to create an AWS account, get your access key
and secret key, and set up the AWS Command Line Interface (AWS CLI) on your computer. For more
information, see Setting Up DynamoDB (Web Service) (p. 51).
Note
If you are using the downloadable version of DynamoDB, you need to use the AWS CLI to create
the tables and sample data. You also need to specify the --endpoint-url parameter with
each AWS CLI command. For more information, see Setting the Local Endpoint (p. 50).

Creating Tables and Loading Data for Code Examples


in DynamoDB
In this tutorial, you use the AWS Management Console to create tables in Amazon DynamoDB. You then
load data into these tables using the AWS Command Line Interface (AWS CLI).

These tables and their data are used as examples throughout this developer guide.
Note
If you are an application developer, we recommend that you also read Getting Started with
DynamoDB and AWS SDKs (p. 76), which uses the downloadable version of DynamoDB. This lets
you learn about the DynamoDB low-level API without having to pay any fees for throughput,
storage, or data transfer.

Topics
• Step 1: Create Example Tables (p. 327)
• Step 2: Load Data into Tables (p. 329)
• Step 3: Query the Data (p. 330)
• Step 4: (Optional) Clean Up (p. 331)
• Summary (p. 331)

API Version 2012-08-10


326
Amazon DynamoDB Developer Guide
Load Sample Data

Step 1: Create Example Tables


In this section, you use the AWS Management Console to create tables in Amazon DynamoDB for two
simple use cases.

Use Case 1: Product Catalog


Suppose that you want to store product information in DynamoDB. Each product has its own distinct
attributes, so you need to store different information about each of these products.

You can create a ProductCatalog table, where each item is uniquely identified by a single, numeric
attribute: Id.

Table Name Primary Key

ProductCatalog Partition key: Id (Number)

Use Case 2: Forum Application


Suppose that you want to build an application for message boards or discussion forums. AWS Discussion
Forums represent one example of such an application. Customers can engage with the developer
community, ask questions, or reply to other customers' posts. Each AWS service has a dedicated forum.
Anyone can start a new discussion thread by posting a message in a forum. Each thread might receive
any number of replies.

You can model this application by creating three tables: Forum, Thread, and Reply.

Table Name Primary Key

Forum Partition key: Name (String)

Thread Partition key: ForumName (String)

Sort key: Subject (String)

Reply Partition key: Id (String)

Sort key: ReplyDateTime (String)

The Reply table has a global secondary index named PostedBy-Message-Index. This index facilitates
queries on two non-key attributes of the Reply table.

Index Name Primary Key

PostedBy-Message-Index Partition key: PostedBy (String)

Sort key: Message (String)

Create the ProductCatalog Table


1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.
2. Choose Create Table.

API Version 2012-08-10


327
Amazon DynamoDB Developer Guide
Load Sample Data

3. In the Create DynamoDB table screen, do the following:

a. On the Table name box, enter ProductCatalog.


b. For the Primary key, in the Partition key box, enter Id. Set the data type to Number.
4. When the settings are as you want them, choose Create.

Create the Forum Table


1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.
2. Choose Create Table.
3. In the Create DynamoDB table screen, do the following:

a. In the Table name box, enter Forum.


b. For the Primary key, in the Partition key box, enter Name. Set the data type to String.
4. When the settings are as you want them, choose Create.

Create the Thread Table


1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.
2. Choose Create Table.
3. In the Create DynamoDB table screen, do the following:

a. In the Table name box, enter Thread.


b. For the Primary key, do the following:

• In the Partition key box, enter ForumName. Set the data type to String.
• Choose Add sort key.
• In the Sort key box, enter Subject. Set the data type to String.
4. When the settings are as you want them, choose Create.

Create the Reply Table


1. Open the DynamoDB console at https://console.aws.amazon.com/dynamodb/.
2. Choose Create Table.
3. In the Create DynamoDB table screen, do the following:

a. In the Table name box, enter Reply.


b. For the Primary key, do the following:

• In the Partition key box, enter Id. Set the data type to String.
• Choose Add sort key.
• In the Sort key box, enter ReplyDateTime. Set the data type to String.
c. In the Table settings section, clear Use default settings.
d. In the Secondary indexes section, choose Add index.
e. In the Add index window, do the following:

• For the Primary key, do the following:


• In the Partition key box, enter PostedBy. Set the data type to String.
• Choose Add sort key.
• In the Sort key box, enter Message. Set the data type to String.

API Version 2012-08-10


328
Amazon DynamoDB Developer Guide
Load Sample Data

• In the Index name box, enter PostedBy-Message-Index.


• Set the Projected attributes to All.
• Choose Add index.
4. When the settings are as you want them, choose Create.

Step 2: Load Data into Tables


In this step, you load sample data into the tables that you created. You could enter the data manually
into the Amazon DynamoDB console. However, to save time, you use the AWS Command Line Interface
(AWS CLI) instead.
Note
If you have not yet set up the AWS CLI, see Using the AWS CLI (p. 56) for instructions.

You will download a .zip archive that contains JSON files with sample data for each table. For each file,
you use the AWS CLI to load the data into DynamoDB. Each successful data load produces the following
output.

{
"UnprocessedItems": {}
}

Download the Sample Data File Archive


1. Download the sample data archive (sampledata.zip) using this link:

• sampledata.zip
2. Extract the .json data files from the archive.
3. Copy the .json data files to your current directory.

Load the Sample Data into DynamoDB Tables


1. To load the ProductCatalog table with data, enter the following command.

aws dynamodb batch-write-item --request-items file://ProductCatalog.json


2. To load the Forum table with data, enter the following command.

aws dynamodb batch-write-item --request-items file://Forum.json


3. To load the Thread table with data, enter the following command.

aws dynamodb batch-write-item --request-items file://Thread.json


4. To load the Reply table with data, enter the following command.

aws dynamodb batch-write-item --request-items file://Reply.json

Verify Data Load


You can use the AWS Management Console to verify the data that you loaded into the tables.

To verify the data using the AWS Management Console

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

API Version 2012-08-10


329
Amazon DynamoDB Developer Guide
Load Sample Data

2. In the navigation pane, choose Tables.


3. In the list of tables, choose ProductCatalog.
4. Choose the Items tab to view the data that you loaded into the table.
5. To view an item in the table, choose its Id. (If you want, you can also edit the item.)
6. To return to the list of tables, choose Cancel.

Repeat this procedure for each of the other tables you created:

• Forum
• Thread
• Reply

Step 3: Query the Data


In this step, you try some simple queries against the tables that you created, using the Amazon
DynamoDB console.

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


2. In the navigation pane, choose Tables.
3. In the list of tables, choose Reply.
4. Choose the Items tab to view the data that you loaded into the table.
5. Choose the data filtering link, located just below the Create item button.

When you choose the link, the console reveals a data filtering pane.

6. In the data filtering pane, do the following:

a. Change the operation from Scan to Query.


b. For the Partition key, enter the value Amazon DynamoDB#DynamoDB Thread 1.
c. Choose Start. Only the items that match your query criteria are returned from the Reply table.
7. The Reply table has a global secondary index on the PostedBy and Message attributes. You can
use the data filtering pane to query the index. Do the following:

a. Change the query source from the following:

API Version 2012-08-10


330
Amazon DynamoDB Developer Guide
Java Code Examples

[Table] Reply: Id, ReplyDateTime

To the following:

[Index] PostedBy-Message-Index: PostedBy, Message


b. For the Partition key, enter the value User A.
c. Choose Start. Only the items that match your query criteria are returned from PostedBy-
Message-Index.

Take some time to explore your other tables using the DynamoDB console:

• ProductCatalog
• Forum
• Thread

Step 4: (Optional) Clean Up


These sample tables are used throughout the Amazon DynamoDB Developer Guide to help illustrate table
and item operations using the low-level API and various AWS SDKs. If you plan to read the rest of this
guide, you might find the tables useful as a reference. However, if you don't want to keep these tables,
you should delete them to avoid being charged for resources that you don't need.

To delete the sample tables

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


2. In the navigation pane, choose Tables.
3. In the list of tables, choose ProductCatalog.
4. Choose Delete Table. You are asked to confirm your selection.

Repeat this procedure for each of the other tables you created:

• Forum
• Thread
• Reply

Summary
In this exercise, you used the DynamoDB console to create several tables in DynamoDB. You then used
the AWS CLI to load data into the tables, and performed some basic operations on the data using the
console.

The console and the AWS CLI are helpful for getting started quickly. However, you probably want to
learn more about how DynamoDB works, and how to write application programs with DynamoDB. The
rest of this developer guide addresses those topics.

Java Code Examples


Topics
• Java: Setting Your AWS Credentials (p. 332)
• Java: Setting the AWS Region and Endpoint (p. 333)

API Version 2012-08-10


331
Amazon DynamoDB Developer Guide
Java Code Examples

This Developer Guide contains Java code snippets and ready-to-run programs. You can find these code
examples in the following sections:

• Working with Items and Attributes (p. 375)


• Working with Tables and Data in DynamoDB (p. 336)
• Working with Queries in DynamoDB (p. 458)
• Working with Scans in DynamoDB (p. 476)
• Improving Data Access with Secondary Indexes (p. 497)
• Java: DynamoDBMapper (p. 229)
• Capturing Table Activity with DynamoDB Streams (p. 574)

You can get started quickly by using Eclipse with the AWS Toolkit for Eclipse. In addition to a full-
featured IDE, you also get the AWS SDK for Java with automatic updates, and preconfigured templates
for building AWS applications.

To run the Java code examples (using Eclipse)

1. Download and install the Eclipse IDE.


2. Download and install the AWS Toolkit for Eclipse.
3. Start Eclipse, and on the Eclipse menu, choose File, New, and then Other.
4. In Select a wizard, choose AWS, choose AWS Java Project, and then choose Next.
5. In Create an AWS Java, do the following:

a. In Project name, enter a name for your project.


b. In Select Account, choose your credentials profile from the list.

If this is your first time using the AWS Toolkit for Eclipse, choose Configure AWS Accounts to
set up your AWS credentials.
6. Choose Finish to create the project.
7. From the Eclipse menu, choose File, New, and then Class.
8. In Java Class, enter a name for your class in Name (use the same name as the code example that you
want to run), and then choose Finish to create the class.
9. Copy the code example from the documentation page into the Eclipse editor.
10. To run the code, choose Run on the Eclipse menu.

The SDK for Java provides thread-safe clients for working with DynamoDB. As a best practice, your
applications should create one client and reuse the client between threads.

For more information, see the AWS SDK for Java.


Note
The code examples in this guide are intended for use with the latest version of the AWS SDK for
Java.
If you are using the AWS Toolkit for Eclipse, you can configure automatic updates for the SDK
for Java. To do this in Eclipse, go to Preferences and choose AWS Toolkit, AWS SDK for Java,
Download new SDKs automatically.

Java: Setting Your AWS Credentials


The SDK for Java requires that you provide AWS credentials to your application at runtime. The code
examples in this guide assume that you are using an AWS credentials file, as described in Set Up Your
AWS Credentials in the AWS SDK for Java Developer Guide.

API Version 2012-08-10


332
Amazon DynamoDB Developer Guide
.NET Code Examples

The following is an example of an AWS credentials file named ~/.aws/credentials, where the tilde
character (~) represents your home directory.

[default]
aws_access_key_id = AWS access key ID goes here
aws_secret_access_key = Secret key goes here

Java: Setting the AWS Region and Endpoint


By default, the code examples access DynamoDB in the US West (Oregon) Region. You can change the
Region by modifying the AmazonDynamoDB properties.

The following code example instantiates a new AmazonDynamoDB.

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.regions.Regions;
...
// This client will default to US West (Oregon)
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(Regions.US_WEST_2)
.build();

You can use the withRegion method to run your code against DynamoDB in any Region where it is
available. For a complete list, see AWS Regions and Endpoints in the Amazon Web Services General
Reference.

If you want to run the code examples using DynamoDB locally on your computer, set the endpoint as
follows.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(


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

.NET Code Examples


Topics
• .NET: Setting Your AWS Credentials (p. 334)
• .NET: Setting the AWS Region and Endpoint (p. 335)

This guide contains .NET code snippets and ready-to-run programs. You can find these code examples in
the following sections:

• Working with Items and Attributes (p. 375)


• Working with Tables and Data in DynamoDB (p. 336)
• Working with Queries in DynamoDB (p. 458)
• Working with Scans in DynamoDB (p. 476)
• Improving Data Access with Secondary Indexes (p. 497)
• .NET: Document Model (p. 276)
• .NET: Object Persistence Model (p. 297)
• Capturing Table Activity with DynamoDB Streams (p. 574)

You can get started quickly by using the AWS SDK for .NET with the Toolkit for Visual Studio.

API Version 2012-08-10


333
Amazon DynamoDB Developer Guide
.NET Code Examples

To run the .NET code examples (using Visual Studio)

1. Download and install Microsoft Visual Studio.


2. Download and install the Toolkit for Visual Studio.
3. Start Visual Studio. Choose File, New, Project.
4. In New Project, choose AWS Empty Project, and then choose OK.
5. In AWS Access Credentials, choose Use existing profile, choose your credentials profile from the
list, and then choose OK.

If this is your first time using Toolkit for Visual Studio, choose Use a new profile to set up your AWS
credentials.
6. In your Visual Studio project, choose the tab for your program's source code (Program.cs). Copy
the code example from the documentation page into the Visual Studio editor, replacing any other
code that you see in the editor.
7. If you see error messages of the form The type or namespace name...could not be found, you need
to install the AWS SDK assembly for DynamoDB as follows:

a. In Solution Explorer, open the context (right-click) menu for your project, and then choose
Manage NuGet Packages.
b. In NuGet Package Manager, choose Browse.
c. In the search box, enter AWSSDK.DynamoDBv2, and wait for the search to complete.
d. Choose AWSSDK.DynamoDBv2, and then choose Install.
e. When the installation is complete, choose the Program.cs tab to return to your program.
8. To run the code, choose Start in the Visual Studio toolbar.

The AWS SDK for .NET provides thread-safe clients for working with DynamoDB. As a best practice, your
applications should create one client and reuse the client between threads.

For more information, see AWS SDK for .NET.


Note
The code examples in this guide are intended for use with the latest version of the AWS SDK
for .NET.

.NET: Setting Your AWS Credentials


The AWS SDK for .NET requires that you provide AWS credentials to your application at runtime. The
code examples in this guide assume that you are using the SDK Store to manage your AWS credentials
file, as described in Using the SDK Store in the AWS SDK for .NET Developer Guide.

The Toolkit for Visual Studio supports multiple sets of credentials from any number of accounts. Each
set is referred to as a profile. Visual Studio adds entries to the project's App.config file so that your
application can find the AWS credentials at runtime.

The following example shows the default App.config file that is generated when you create a new
project using Toolkit for Visual Studio.

<?xml version="1.0" encoding="utf-8" ?>


<configuration>
<appSettings>
<add key="AWSProfileName" value="default"/>
<add key="AWSRegion" value="us-west-2" />
</appSettings>
</configuration>

API Version 2012-08-10


334
Amazon DynamoDB Developer Guide
.NET Code Examples

At runtime, the program uses the default set of AWS credentials, as specified by the AWSProfileName
entry. The AWS credentials themselves are kept in the SDK Store in encrypted form. The Toolkit for
Visual Studio provides a graphical user interface for managing your credentials, all from within Visual
Studio. For more information, see Specifying Credentials in the AWS Toolkit for Visual Studio User Guide.
Note
By default, the code examples access DynamoDB in the US West (Oregon) Region. You can
change the Region by modifying the AWSRegion entry in the App.config file. You can set
AWSRegion to any Region where DynamoDB is available. For a complete list, see AWS Regions
and Endpoints in the Amazon Web Services General Reference.

.NET: Setting the AWS Region and Endpoint


By default, the code examples access DynamoDB in the US West (Oregon) Region. You can change the
Region by modifying the AWSRegion entry in the App.config file. Or, you can change the Region by
modifying the AmazonDynamoDBClient properties.

The following code example instantiates a new AmazonDynamoDBClient. The client is modified so that
the code runs against DynamoDB in a different Region.

AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();


// This client will access the US East 1 region.
clientConfig.RegionEndpoint = RegionEndpoint.USEast1;
AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);

For a complete list of Regions, see AWS Regions and Endpoints in the Amazon Web Services General
Reference.

If you want to run the code examples using DynamoDB locally on your computer, set the endpoint as
follows.

AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();


// Set the endpoint URL
clientConfig.ServiceURL = "http://localhost:8000";
AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);

API Version 2012-08-10


335
Amazon DynamoDB Developer Guide
Working with Tables

Working with Tables, Items, Queries,


Scans, and Indexes
This section provides details about working with tables, items, queries, and more in Amazon DynamoDB.

Topics
• Working with Tables and Data in DynamoDB (p. 336)
• Working with Items and Attributes (p. 375)
• Working with Queries in DynamoDB (p. 458)
• Working with Scans in DynamoDB (p. 476)
• Improving Data Access with Secondary Indexes (p. 497)
• Capturing Table Activity with DynamoDB Streams (p. 574)

Working with Tables and Data in DynamoDB


This section describes how to use the AWS Command Line Interface (AWS CLI) and the AWS SDKs to
create, update, and delete tables in Amazon DynamoDB.
Note
You can also perform these same tasks using the AWS Management Console. For more
information, see Using the Console (p. 54).

This section also provides more information about throughput capacity using DynamoDB auto scaling or
manually setting provisioned throughput.

Topics
• Basic Operations on DynamoDB Tables (p. 336)
• Considerations When Changing Read/Write Capacity Mode (p. 341)
• Managing Settings on DynamoDB Provisioned Capacity Tables (p. 342)
• DynamoDB Item Sizes and Formats (p. 346)
• Managing Throughput Capacity Automatically with DynamoDB Auto Scaling (p. 346)
• Adding Tags and Labels to Resources (p. 360)
• Working with DynamoDB Tables in Java (p. 363)
• Working with DynamoDB Tables in .NET (p. 368)

Basic Operations on DynamoDB Tables


Similar to other database systems, Amazon DynamoDB stores data in tables. You can manage your tables
using a few basic operations.

Topics
• Creating a Table (p. 337)
• Describing a Table (p. 339)
• Updating a Table (p. 339)
• Deleting a Table (p. 340)
• Listing Table Names (p. 340)

API Version 2012-08-10


336
Amazon DynamoDB Developer Guide
Basic Operations on Tables

• Describing Provisioned Throughput Limits (p. 340)

Creating a Table
Use the CreateTable operation to create a table in Amazon DynamoDB. To create the table, you must
provide the following information:

• Table name. The name must conform to the DynamoDB naming rules, and must be unique for the
current AWS account and Region. For example, you could create a People table in US East (N. Virginia)
and another People table in Europe (Ireland). However, these two tables would be entirely different
from each other. For more information, see Naming Rules and Data Types (p. 12).
• Primary key. The primary key can consist of one attribute (partition key) or two attributes (partition
key and sort key). You need to provide the attribute names, data types, and the role of each attribute:
HASH (for a partition key) and RANGE (for a sort key). For more information, see Primary Key (p. 6).
• Throughput settings (for provisioned tables). If using provisioned mode, you must specify the
initial read and write throughput settings for the table. You can modify these settings later, or
enable DynamoDB auto scaling to manage the settings for you. For more information, see Managing
Settings on DynamoDB Provisioned Capacity Tables (p. 342) and Managing Throughput Capacity
Automatically with DynamoDB Auto Scaling (p. 346).

Example 1: Create a Provisioned Table


The following AWS CLI example shows how to create a table (Music). The primary key consists of
Artist (partition key) and SongTitle (sort key), each of which has a data type of String. The
maximum throughput for this table is 10 read capacity units and 5 write capacity units.

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

The CreateTable operation returns metadata for the table, as shown following.

{
"TableDescription": {
"TableArn": "arn:aws:dynamodb:us-east-1:123456789012:table/Music",
"AttributeDefinitions": [
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"WriteCapacityUnits": 5,
"ReadCapacityUnits": 10
},

API Version 2012-08-10


337
Amazon DynamoDB Developer Guide
Basic Operations on Tables

"TableSizeBytes": 0,
"TableName": "Music",
"TableStatus": "CREATING",
"TableId": "12345678-0123-4567-a123-abcdefghijkl",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "Artist"
},
{
"KeyType": "RANGE",
"AttributeName": "SongTitle"
}
],
"ItemCount": 0,
"CreationDateTime": 1542397215.37
}
}

The TableStatus element indicates the current state of the table (CREATING). It might take
a while to create the table, depending on the values you specify for ReadCapacityUnits and
WriteCapacityUnits. Larger values for these require DynamoDB to allocate more resources for the
table.

Example 2: Create an On-Demand Table


To create the same table Music using on-demand mode.

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 \
--billing-mode=PAY_PER_REQUEST

The CreateTable operation returns metadata for the table, as shown following.

{
"TableDescription": {
"TableArn": "arn:aws:dynamodb:us-east-1:123456789012:table/Music",
"AttributeDefinitions": [
{
"AttributeName": "Artist",
"AttributeType": "S"
},
{
"AttributeName": "SongTitle",
"AttributeType": "S"
}
],
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"WriteCapacityUnits": 0,
"ReadCapacityUnits": 0
},
"TableSizeBytes": 0,
"TableName": "Music",
"BillingModeSummary": {
"BillingMode": "PAY_PER_REQUEST"

API Version 2012-08-10


338
Amazon DynamoDB Developer Guide
Basic Operations on Tables

},
"TableStatus": "CREATING",
"TableId": "12345678-0123-4567-a123-abcdefghijkl",
"KeySchema": [
{
"KeyType": "HASH",
"AttributeName": "Artist"
},
{
"KeyType": "RANGE",
"AttributeName": "SongTitle"
}
],
"ItemCount": 0,
"CreationDateTime": 1542397468.348
}
}

Important
When calling DescribeTable on an on-demand table, read capacity units and write capacity
units are set to 0.

Describing a Table
To view details about a table, use the DescribeTable operation. You must provide the table name.
The output from DescribeTable is in the same format as that from CreateTable. It includes the
timestamp when the table was created, its key schema, its provisioned throughput settings, its estimated
size, and any secondary indexes that are present.
Important
When calling DescribeTable on an on-demand table, read capacity units and write capacity
units are set to 0.

Example

aws dynamodb describe-table --table-name Music

The table is ready for use when the TableStatus has changed from CREATING to ACTIVE.
Note
If you issue a DescribeTable request immediately after a CreateTable request, DynamoDB
might return an error (ResourceNotFoundException). This is because DescribeTable uses
an eventually consistent query, and the metadata for your table might not be available at that
moment. Wait for a few seconds, and then try the DescribeTable request again.
For billing purposes, your DynamoDB storage costs include a per-item overhead of 100 bytes.
(For more information, go to DynamoDB Pricing.) This extra 100 bytes per item is not used in
capacity unit calculations or by the DescribeTable operation.

Updating a Table
The UpdateTable operation allows you to do one of the following:

• Modify a table's provisioned throughput settings (for provisioned mode tables).


• Change the table's read/write capacity mode.
• Manipulate global secondary indexes on the table (see Using Global Secondary Indexes in
DynamoDB (p. 500)).
• Enable or disable DynamoDB Streams on the table (see Capturing Table Activity with DynamoDB
Streams (p. 574)).

API Version 2012-08-10


339
Amazon DynamoDB Developer Guide
Basic Operations on Tables

Example

The following AWS CLI example shows how to modify a table's provisioned throughput settings.

aws dynamodb update-table --table-name Music \


--provisioned-throughput ReadCapacityUnits=20,WriteCapacityUnits=10

Note
When you issue an UpdateTable request, the status of the table changes from AVAILABLE to
UPDATING. The table remains fully available for use while it is UPDATING. When this process is
completed, the table status changes from UPDATING to AVAILABLE.

Example

The following AWS CLI example shows how to modify a table's read/write capacity mode to on-demand
mode.

aws dynamodb update-table --table-name Music \


--billing-mode PAY_PER_REQUEST

Deleting a Table
You can remove an unused table with the DeleteTable operation. Deleting a table is an unrecoverable
operation.

Example

The following AWS CLI example shows how to delete a table.

aws dynamodb delete-table --table-name Music

When you issue a DeleteTable request, the table's status changes from ACTIVE to DELETING. It might
take a while to delete the table, depending on the resources it uses (such as the data stored in the table,
and any streams or indexes on the table).

When the DeleteTable operation concludes, the table no longer exists in DynamoDB.

Listing Table Names


The ListTables operation returns the names of the DynamoDB tables for the current AWS account and
Region.

Example

The following AWS CLI example shows how to list the DynamoDB table names.

aws dynamodb list-tables

Describing Provisioned Throughput Limits


The DescribeLimits operation returns the current read and write capacity limits for the current AWS
account and Region.

API Version 2012-08-10


340
Amazon DynamoDB Developer Guide
Considerations When Changing Read/Write Capacity Mode

Example
The following AWS CLI example shows how to describe the current provisioned throughput limits.

aws dynamodb describe-limits

The output shows the upper limits of read and write capacity units for the current AWS account and
Region.

For more information about these limits, and how to request limit increases, see Throughput Default
Limits (p. 960).

Considerations When Changing Read/Write Capacity


Mode
You can switch between read/write capacity modes once every 24 hours. Consider the following when
updating your read/write capacity mode in Amazon DynamoDB.

Managing Capacity
When you update a table from provisioned to on-demand mode, you don't need to specify how much
read and write throughput you expect your application to perform.

Consider the following when you update a table from on-demand to provisioned mode:

• If you're using the AWS Management Console, the console estimates initial provisioned capacity values
based on the consumed read and write capacity of your table and global secondary indexes over the
past 30 minutes. To override these recommended values, choose Override recommended values.
• If you're using the AWS CLI or AWS SDK, choose the right provisioned capacity settings of your table
and global secondary indexes by using Amazon CloudWatch to look at your historical consumption
(ConsumedWriteCapacityUnits and ConsumedReadCapacityUnits metrics) to determine the
new throughput settings.
Note
If you're switching a global table to provisioned mode, look at the maximum consumption
across all your regional replicas for base tables and global secondary indexes when
determining the new throughput settings.

Managing Auto Scaling


When you update a table from provisioned to on-demand mode:

• If you're using the console, all of your auto scaling settings (if any) will be deleted.
• If you're using the AWS CLI or AWS SDK, all of your auto scaling settings will be preserved. These
settings can be applied when you update your table to provisioned billing mode again.

When you update a table from on-demand to provisioned mode:

• If you're using the console, DynamoDB recommends enabling auto scaling with the following defaults:
• Target utilization: 70%
• Minimum provisioned capacity: 5 units
• Maximum provisioned capacity: The Region maximum
• If you're using the AWS CLI or SDK, your previous auto scaling settings (if any) are preserved.

API Version 2012-08-10


341
Amazon DynamoDB Developer Guide
Provisioned Capacity Tables

Managing Settings on DynamoDB Provisioned


Capacity Tables
When you create a new provisioned table in Amazon DynamoDB, you must specify its provisioned
throughput capacity. This is the amount of read and write activity that the table can support. DynamoDB
uses this information to reserve sufficient system resources to meet your throughput requirements.
Note
You can create an on-demand mode table instead so that you don't have to manage any
capacity settings for servers, storage, or throughput. 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. For more
information, see On-Demand Mode (p. 17).

You can optionally allow DynamoDB auto scaling to manage your table's throughput capacity. However,
you still must provide initial settings for read and write capacity when you create the table. DynamoDB
auto scaling uses these initial settings as a starting point, and then adjusts them dynamically in
response to your application's requirements. For more information, see Managing Throughput Capacity
Automatically with DynamoDB Auto Scaling (p. 346).

As your application data and access requirements change, you might need to adjust your table's
throughput settings. If you're using DynamoDB auto scaling, the throughput settings are automatically
adjusted in response to actual workloads. You can also use the UpdateTable operation to manually
adjust your table's throughput capacity. You might decide to do this if you need to bulk-load data from
an existing data store into your new DynamoDB table. You could create the table with a large write
throughput setting and then reduce this setting after the bulk data load is complete.

You specify throughput requirements in terms of capacity units—the amount of data your application
needs to read or write per second. You can modify these settings later, if needed, or enable DynamoDB
auto scaling to modify them automatically.

Topics
• Read Capacity Units (p. 342)
• Write Capacity Units (p. 343)
• Request Throttling and Burst Capacity (p. 344)
• Request Throttling and Adaptive Capacity (p. 344)
• Choosing Initial Throughput Settings (p. 345)
• Modifying Throughput Settings (p. 345)

Read Capacity Units


A 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.
Note
To learn more about DynamoDB read consistency models, see Read Consistency (p. 16).

For example, suppose that you create a table with 10 provisioned read capacity units. This allows you to
perform 10 strongly consistent reads per second, or 20 eventually consistent reads per second, for items
up to 4 KB.

Reading an item larger than 4 KB consumes more read capacity units. For example, a strongly consistent
read of an item that is 8 KB (4 KB × 2) consumes 2 read capacity units. An eventually consistent read on
that same item consumes only 1 read capacity unit.

API Version 2012-08-10


342
Amazon DynamoDB Developer Guide
Provisioned Capacity Tables

Item sizes for reads are rounded up to the next 4 KB multiple. For example, reading a 3,500-byte item
consumes the same throughput as reading a 4 KB item.

Capacity Unit Consumption for Reads


The following describes how DynamoDB read operations consume read capacity units:

• GetItem—Reads a single item from a table. To determine the number of capacity units that GetItem
will consume, take the item size and round it up to the next 4 KB boundary. If you specified a strongly
consistent read, this is the number of capacity units required. For an eventually consistent read (the
default), divide this number by two.

For example, if you read an item that is 3.5 KB, DynamoDB rounds the item size to 4 KB. If you read an
item of 10 KB, DynamoDB rounds the item size to 12 KB.
• BatchGetItem—Reads up to 100 items, from one or more tables. DynamoDB processes each item
in the batch as an individual GetItem request, so DynamoDB first rounds up the size of each item to
the next 4 KB boundary, and then calculates the total size. The result is not necessarily the same as
the total size of all the items. For example, if BatchGetItem reads a 1.5 KB item and a 6.5 KB item,
DynamoDB calculates the size as 12 KB (4 KB + 8 KB), not 8 KB (1.5 KB + 6.5 KB).
• Query—Reads multiple items that have the same partition key value. All items returned are treated
as a single read operation, where DynamoDB computes the total size of all items and then rounds up
to the next 4 KB boundary. For example, suppose your query returns 10 items whose combined size is
40.8 KB. DynamoDB rounds the item size for the operation to 44 KB. If a query returns 1500 items of
64 bytes each, the cumulative size is 96 KB.
• Scan—Reads all items in a table. DynamoDB considers the size of the items that are evaluated, not the
size of the items returned by the scan.

If you perform a read operation on an item that does not exist, DynamoDB still consumes provisioned
read throughput: A strongly consistent read request consumes one read capacity unit, while an
eventually consistent read request consumes 0.5 of a read capacity unit.

For any operation that returns items, you can request a subset of attributes to retrieve. However, doing
so has no impact on the item size calculations. In addition, Query and Scan can return item counts
instead of attribute values. Getting the count of items uses the same quantity of read capacity units and
is subject to the same item size calculations. This is because DynamoDB has to read each item in order to
increment the count.

Read Operations and Read Consistency

The preceding calculations assume strongly consistent read requests. For an eventually consistent read
request, the operation consumes only half the capacity units. For an eventually consistent read, if the
total item size is 80 KB, the operation consumes only 10 capacity units.

Write Capacity Units


A write capacity unit represents one write per second, for an item up to 1 KB in size.

For example, suppose that you create a table with 10 write capacity units. This allows you to perform 10
writes per second, for items up to 1 KB in size per second.

Item sizes for writes are rounded up to the next 1 KB multiple. For example, writing a 500-byte item
consumes the same throughput as writing a 1 KB item.

Capacity Unit Consumption for Writes


The following describes how DynamoDB write operations consume write capacity units:

API Version 2012-08-10


343
Amazon DynamoDB Developer Guide
Provisioned Capacity Tables

• PutItem—Writes a single item to a table. If an item with the same primary key exists in the table, the
operation replaces the item. For calculating provisioned throughput consumption, the item size that
matters is the larger of the two.
• UpdateItem—Modifies a single item in the table. DynamoDB considers the size of the item as it
appears before and after the update. The provisioned throughput consumed reflects the larger of
these item sizes. Even if you update just a subset of the item's attributes, UpdateItem will still
consume the full amount of provisioned throughput (the larger of the "before" and "after" item sizes).
• DeleteItem—Removes a single item from a table. The provisioned throughput consumption is based
on the size of the deleted item.
• BatchWriteItem—Writes up to 25 items to one or more tables. DynamoDB processes each item
in the batch as an individual PutItem or DeleteItem request (updates are not supported). So
DynamoDB first rounds up the size of each item to the next 1 KB boundary, and then calculates the
total size. The result is not necessarily the same as the total size of all the items. For example, if
BatchWriteItem writes a 500-byte item and a 3.5 KB item, DynamoDB calculates the size as 5 KB (1
KB + 4 KB), not 4 KB (500 bytes + 3.5 KB).

For PutItem, UpdateItem, and DeleteItem operations, DynamoDB rounds the item size up to the
next 1 KB. For example, if you put or delete an item of 1.6 KB, DynamoDB rounds the item size up to 2
KB.

PutItem, UpdateItem, and DeleteItem allow conditional writes, where you specify an expression
that must evaluate to true in order for the operation to succeed. If the expression evaluates to false,
DynamoDB still consumes write capacity units from the table:

• For an existing item, the number of write capacity units consumed depends on the size of the new
item. (For example, a failed conditional write of a 1 KB item would consume one write capacity unit.
If the new item were twice that size, the failed conditional write would consume two write capacity
units.)
• For a new item, DynamoDB consumes one write capacity unit.

Request Throttling and Burst Capacity


If your application performs reads or writes at a higher rate than your table can support,
DynamoDB begins to throttle those requests. When DynamoDB throttles a read or write, it returns
a ProvisionedThroughputExceededException to the caller. The application can then take
appropriate action, such as waiting for a short interval before retrying the request.
Note
We recommend that you use the AWS SDKs for software development. The AWS SDKs provide
built-in support for retrying throttled requests; you do not need to write this logic yourself. For
more information, see Error Retries and Exponential Backoff (p. 228).

The DynamoDB console displays Amazon CloudWatch metrics for your tables, so you can monitor
throttled read requests and write requests. If you encounter excessive throttling, you should consider
increasing your table's provisioned throughput settings.

In some cases, DynamoDB uses burst capacity to accommodate reads or writes in excess of your table's
throughput settings. With burst capacity, unexpected read or write requests can succeed where they
otherwise would be throttled. For more information, see Using Burst Capacity Effectively (p. 899).

Request Throttling and Adaptive Capacity


DynamoDB automatically distributes your data across partitions, which are stored on multiple servers
in the AWS Cloud (For more information, see Partitions and Data Distribution (p. 21)). It's not always
possible to distribute read and write activity evenly all the time. When data access is imbalanced, a

API Version 2012-08-10


344
Amazon DynamoDB Developer Guide
Provisioned Capacity Tables

"hot" partition can receive such a higher volume of read and write traffic compared to other partitions.
Adaptive capacity works by automatically increasing throughput capacity for partitions that receive more
traffic. For more information, see Understanding DynamoDB Adaptive Capacity (p. 899).

Choosing Initial Throughput Settings


Every application has different requirements for reading and writing from a database. When you are
determining the initial throughput settings for a DynamoDB table, take the following inputs into
consideration:

• Item sizes. Some items are small enough that they can be read or written using a single capacity unit.
Larger items require multiple capacity units. By estimating the sizes of the items that will be in your
table, you can specify accurate settings for your table's provisioned throughput.
• Expected read and write request rates. In addition to item size, you should estimate the number of
reads and writes you need to perform per second.
• Read consistency requirements. Read capacity units are based on strongly consistent read operations,
which consume twice as many database resources as eventually consistent reads. You should
determine whether your application requires strongly consistent reads, or whether it can relax this
requirement and perform eventually consistent reads instead. (Read operations in DynamoDB are
eventually consistent, by default. You can request strongly consistent reads for these operations if
necessary.)

For example, suppose that you want to read 80 items per second from a table. The items are 3 KB in
size, and you want strongly consistent reads. For this scenario, each read requires one provisioned read
capacity unit. To determine this number, you divide the item size of the operation by 4 KB, and then
round up to the nearest whole number, as in this example:

• 3 KB / 4 KB = 0.75, or 1 read capacity unit

For this scenario, you have to set the table's provisioned read throughput to 80 read capacity units:

• 1 read capacity unit per item × 80 reads per second = 80 read capacity units

Now suppose that you want to write 100 items per second to your table, and that the items are 512
bytes in size. For this scenario, each write requires one provisioned write capacity unit. To determine
this number, you divide the item size of the operation by 1 KB, and then round up to the nearest whole
number:

• 512 bytes / 1 KB = 0.5, or 1

For this scenario, you would want to set the table's provisioned write throughput to 100 write capacity
units:

• 1 write capacity unit per item × 100 writes per second = 100 write capacity units

Note
For recommendations on provisioned throughput and related topics, see Best Practices for
Designing and Using Partition Keys Effectively (p. 899).

Modifying Throughput Settings


If you have enabled DynamoDB auto scaling for a table, then its throughput capacity is dynamically
adjusted in response to actual usage. No manual intervention is required.

API Version 2012-08-10


345
Amazon DynamoDB Developer Guide
Item Sizes and Formats

You can modify your table's provisioned throughput settings using the AWS Management Console or the
UpdateTable operation. For more information about throughput increases and decreases per day, see
Service, Account, and Table Limits in Amazon DynamoDB (p. 959).

DynamoDB Item Sizes and Formats


DynamoDB tables are schemaless, except for the primary key, so the items in a table can all have
different attributes, sizes, and data types.

The total size of an item is the sum of the lengths of its attribute names and values. You can use the
following guidelines to estimate attribute sizes:

• Strings are Unicode with UTF-8 binary encoding. The size of a string is (length of attribute name) +
(number of UTF-8-encoded bytes).
• Numbers are variable length, with up to 38 significant digits. Leading and trailing zeroes are trimmed.
The size of a number is approximately (length of attribute name) + (1 byte per two significant digits) +
(1 byte).
• A binary value must be encoded in base64 format before it can be sent to DynamoDB, but the value's
raw byte length is used for calculating size. The size of a binary attribute is (length of attribute name) +
(number of raw bytes).
• The size of a null attribute or a Boolean attribute is (length of attribute name) + (1 byte).
• An attribute of type List or Map requires 3 bytes of overhead, regardless of its contents. The size of
a List or Map is (length of attribute name) + sum (size of nested elements) + (3 bytes) . The size of an
empty List or Map is (length of attribute name) + (3 bytes).

Note
We recommend that you choose shorter attribute names rather than long ones. This helps you
reduce the amount of storage required, but also can lower the amount of RCU/WCUs you use.

Managing Throughput Capacity Automatically with


DynamoDB Auto Scaling
Many database workloads are cyclical in nature or are difficult to predict in advance. For example,
consider a social networking app where most of the users are active during daytime hours. The database
must be able to handle the daytime activity, but there's no need for the same levels of throughput
at night. Another example might be a new mobile gaming app that is experiencing rapid adoption.
If the game becomes too popular, it could exceed the available database resources, resulting in slow
performance and unhappy customers. These kinds of workloads often require manual intervention to
scale database resources up or down in response to varying usage levels.

Amazon DynamoDB auto scaling uses the AWS Application Auto Scaling service to dynamically adjust
provisioned throughput capacity on your behalf, in response to actual traffic patterns. This enables a
table or a global secondary index to increase its provisioned read and write capacity to handle sudden
increases in traffic, without throttling. When the workload decreases, Application Auto Scaling decreases
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 modify your auto scaling settings at any
time. For more information, see Using the AWS Management Console with DynamoDB Auto
Scaling (p. 349).

With Application Auto Scaling, you create a scaling policy for a table or a global secondary index. The
scaling policy specifies whether you want to scale read capacity or write capacity (or both), and the
minimum and maximum provisioned capacity unit settings for the table or index.

API Version 2012-08-10


346
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

The scaling policy also contains a target utilization—the percentage of consumed provisioned
throughput at a point in time. Application Auto Scaling uses a target tracking algorithm to adjust the
provisioned throughput of the table (or index) upward or downward in response to actual workloads, so
that the actual capacity utilization remains at or near your target utilization.

You can set the auto scaling target utilization values between 20 and 90 percent for your read and write
capacity.
Note
In addition to tables, DynamoDB auto scaling also supports global secondary indexes. Every
global secondary index has its own provisioned throughput capacity, separate from that of its
base table. When you create a scaling policy for a global secondary index, Application Auto
Scaling adjusts the provisioned throughput settings for the index to ensure that its actual
utilization stays at or near your desired utilization ratio.

How DynamoDB Auto Scaling Works


Note
To get started quickly with DynamoDB auto scaling, see Using the AWS Management Console
with DynamoDB Auto Scaling (p. 349).

The following diagram provides a high-level overview of how DynamoDB auto scaling manages
throughput capacity for a table.

The following steps summarize the auto scaling process as shown in the previous diagram:

1. You create an Application Auto Scaling policy for your DynamoDB table.
2. DynamoDB publishes consumed capacity metrics to Amazon CloudWatch.
3. If the table's consumed capacity exceeds your target utilization (or falls below the target) for a specific
length of time, Amazon CloudWatch triggers an alarm. You can view the alarm on the console and
receive notifications using Amazon Simple Notification Service (Amazon SNS).

API Version 2012-08-10


347
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

4. The CloudWatch alarm invokes Application Auto Scaling to evaluate your scaling policy.
5. Application Auto Scaling issues an UpdateTable request to adjust your table's provisioned
throughput.
6. DynamoDB processes the UpdateTable request, dynamically increasing (or decreasing) the table's
provisioned throughput capacity so that it approaches your target utilization.

To understand how DynamoDB auto scaling works, suppose that you have a table named
ProductCatalog. The table is bulk-loaded with data infrequently, so it doesn't incur very much write
activity. However, it does experience a high degree of read activity, which varies over time. By monitoring
the Amazon CloudWatch metrics for ProductCatalog, you determine that the table requires 1,200
read capacity units (to avoid DynamoDB throttling read requests when activity is at its peak). You also
determine that ProductCatalog requires 150 read capacity units at a minimum, when read traffic is at
its lowest point.

Within the range of 150 to 1,200 read capacity units, you decide that a target utilization of 70 percent
would be appropriate for the ProductCatalog table. Target utilization is the ratio of consumed
capacity units to provisioned capacity units, expressed as a percentage. Application Auto Scaling uses its
target tracking algorithm to ensure that the provisioned read capacity of ProductCatalog is adjusted
as required so that utilization remains at or near 70 percent.
Note
DynamoDB auto scaling modifies provisioned throughput settings only when the actual
workload stays elevated (or depressed) for a sustained period of several minutes. The
Application Auto Scaling target tracking algorithm seeks to keep the target utilization at or near
your chosen value over the long term.
Sudden, short-duration spikes of activity are accommodated by the table's built-in burst
capacity. For more information, see Using Burst Capacity Effectively (p. 899).

To enable DynamoDB auto scaling for the ProductCatalog table, you create a scaling policy. This
policy specifies the following:

• The table or global secondary index that you want to manage


• Which capacity type to manage (read capacity or write capacity)
• The upper and lower boundaries for the provisioned throughput settings
• Your target utilization

When you create a scaling policy, Application Auto Scaling creates a pair of Amazon CloudWatch alarms
on your behalf. Each pair represents your upper and lower boundaries for provisioned throughput
settings. These CloudWatch alarms are triggered when the table's actual utilization deviates from your
target utilization for a sustained period of time.

When one of the CloudWatch alarms is triggered, Amazon SNS sends you a notification (if you have
enabled it). The CloudWatch alarm then invokes Application Auto Scaling, which in turn notifies
DynamoDB to adjust the ProductCatalog table's provisioned capacity upward or downward as
appropriate.

Usage Notes
Before you begin using DynamoDB auto scaling, you should be aware of the following:

• DynamoDB auto scaling can increase read capacity or write capacity as often as necessary, in
accordance with your auto scaling policy. All DynamoDB limits remain in effect, as described in Limits
in DynamoDB.
• DynamoDB auto scaling doesn't prevent you from manually modifying provisioned throughput
settings. These manual adjustments don't affect any existing CloudWatch alarms that are related to
DynamoDB auto scaling.

API Version 2012-08-10


348
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

• If you enable DynamoDB auto scaling for a table that has one or more global secondary indexes, we
highly recommend that you also apply auto scaling uniformly to those indexes. You can do this by
choosing Apply same settings to global secondary indexes in the AWS Management Console. For
more information, see Enabling DynamoDB Auto Scaling on Existing Tables (p. 350).

Using the AWS Management Console with DynamoDB Auto


Scaling
When you use the AWS Management Console to create a new table, Amazon DynamoDB auto scaling is
enabled for that table by default. You can also use the console to enable auto scaling for existing tables,
modify auto scaling settings, or disable auto scaling.
Note
For more advanced features like setting scale-in and scale-out cooldown times, use the AWS
Command Line Interface (AWS CLI) to manage DynamoDB auto scaling. For more information,
see Using the AWS CLI to Manage DynamoDB Auto Scaling (p. 351).

Topics
• Before You Begin: Granting User Permissions for DynamoDB Auto Scaling (p. 349)
• Creating a New Table with Auto Scaling Enabled (p. 349)
• Enabling DynamoDB Auto Scaling on Existing Tables (p. 350)
• Viewing Auto Scaling Activities on the Console (p. 351)
• Modifying or Disabling DynamoDB Auto Scaling Settings (p. 351)

Before You Begin: Granting User Permissions for DynamoDB Auto Scaling
In AWS Identity and Access Management (IAM), the AWS managed policy DynamoDBFullAccess
provides the required permissions for using the DynamoDB console. However, for DynamoDB auto
scaling, IAM users require additional privileges.
Important
application-autoscaling:* permissions are required to delete an auto scaling-enabled
table. The AWS managed policy DynamoDBFullAccess includes such permissions.

To set up an IAM user for DynamoDB console access and DynamoDB auto scaling, add the following
policy.

To attach the AmazonDynamoDBFullAccess policy

1. Sign in to the AWS Management Console and open the IAM console at https://
console.aws.amazon.com/iam/.
2. On the IAM console dashboard, choose Users, and then choose your IAM user from the list.
3. On the Summary page, choose Add permissions.
4. Choose Attach existing policies directly.
5. From the list of policies, choose AmazonDynamoDBFullAccess, and then choose Next: Review.
6. Choose Add permissions.

Creating a New Table with Auto Scaling Enabled


Note
DynamoDB auto scaling requires the presence of a service linked role
(AWSServiceRoleForApplicationAutoScaling_DynamoDBTable) that performs auto
scaling actions on your behalf. This role is created automatically for you. For more information,
see Service-Linked Roles for Application Auto Scaling in the Application Auto Scaling User Guide.

API Version 2012-08-10


349
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

To create a new table with auto scaling enabled

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


2. Choose Create Table.
3. On the Create DynamoDB table page, enter a Table name and Primary key details.
4. Ensure that Use default settings is selected. (Your AWS account already has
AWSServiceRoleForApplicationAutoScaling_DynamoDBTable.)

Otherwise, for custom settings:

1. Clear Use default settings.


2. In the Auto scaling section, set the parameter settings and ensure that
AWSServiceRoleForApplicationAutoScaling_DynamoDBTable is selected.
5. When the settings are as you want them, choose Create. Your table is created with the auto scaling
parameters.

Enabling DynamoDB Auto Scaling on Existing Tables


Note
DynamoDB auto scaling requires the presence of a service linked role
(AWSServiceRoleForApplicationAutoScaling_DynamoDBTable) that performs auto
scaling actions on your behalf. This role is created automatically for you. For more information,
see Service-Linked Roles for Application Auto Scaling.
If you have never used DynamoDB auto scaling before, see Creating a New Table with Auto
Scaling Enabled (p. 349).

To enable DynamoDB auto scaling for an existing table

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


2. Choose the table that you want to work with, and then choose Capacity.
3. In the Auto Scaling section, do the following:

• Select Read capacity, Write capacity, or both. (For write capacity, you can choose Same
settings as read.) For each of these, do the following:

• Target utilization—Enter your target utilization percentage for the table.


• Minimum provisioned capacity—Enter your lower boundary for the auto scaling range.
• Maximum provisioned capacity—Enter your upper boundary for the auto scaling range.
• Apply same settings to global secondary indexes—Keep this option at its default setting
(enabled).
Note
For best performance, we recommend that you enable Apply same settings to
global secondary indexes. This option allows DynamoDB auto scaling to uniformly
scale all the global secondary indexes on the base table. This includes existing global
secondary indexes, and any others that you create for this table in the future.
With this option enabled, you can't set a scaling policy on an individual global
secondary index.

(For Write capacity, you can choose Same settings as read.)

In the IAM Role section, ensure that


AWSServiceRoleForApplicationAutoScaling_DynamoDBTable is selected.
4. When the settings are as you want them, choose Save.
API Version 2012-08-10
350
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

Viewing Auto Scaling Activities on the Console


As your application drives read and write traffic to your table, DynamoDB auto scaling dynamically
modifies the table's throughput settings.

To view these auto scaling activities on the DynamoDB console, choose the table that you want to work
with. Choose Capacity, and then expand the Scaling activities section. When your table's throughput
settings are modified, you see informational messages here.

Modifying or Disabling DynamoDB Auto Scaling Settings


You can use the AWS Management Console to modify your DynamoDB auto scaling settings. To do this,
go to the Capacity tab for your table, and modify the settings in the Auto Scaling section. For more
information about these settings, see Enabling DynamoDB Auto Scaling on Existing Tables (p. 350).

To disable DynamoDB auto scaling, go to the Capacity tab for your table and clear Read capacity, Write
capacity, or both.

Using the AWS CLI to Manage DynamoDB Auto Scaling


Instead of using the AWS Management Console, you can use the AWS Command Line Interface (AWS CLI)
to manage Amazon DynamoDB auto scaling. The tutorial in this section demonstrates how to install and
configure the AWS CLI for managing DynamoDB auto scaling. In this tutorial, you do the following:

• Create a DynamoDB table named TestTable. The initial throughput settings are 5 read capacity units
and 5 write capacity units.
• Create an Application Auto Scaling policy for TestTable. The policy seeks to maintain a 50 percent
target ratio between consumed write capacity and provisioned write capacity. The range for this
metric is between 5 and 10 write capacity units. (Application Auto Scaling is not allowed to adjust the
throughput beyond this range.)
• Run a Python program to drive write traffic to TestTable. When the target ratio exceeds 50 percent
for a sustained period of time, Application Auto Scaling notifies DynamoDB to adjust the throughput
of TestTable upward to maintain the 50 percent target utilization.
• Verify that DynamoDB has successfully adjusted the provisioned write capacity for TestTable.

Topics
• Before You Begin (p. 351)
• Step 1: Create a DynamoDB Table (p. 352)
• Step 2: Register a Scalable Target (p. 352)
• Step 3: Create a Scaling Policy (p. 353)
• Step 4: Drive Write Traffic to TestTable (p. 354)
• Step 5: View Application Auto Scaling Actions (p. 355)
• (Optional) Step 6: Clean Up (p. 356)

Before You Begin


Complete the following tasks before starting the tutorial.

Install the AWS CLI

If you haven't already done so, you must install and configure the AWS CLI. To do this, follow these
instructions in the AWS Command Line Interface User Guide:

API Version 2012-08-10


351
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

• Installing the AWS CLI


• Configuring the AWS CLI

Install Python

Part of this tutorial requires you to run a Python program (see Step 4: Drive Write Traffic to
TestTable (p. 354)). If you don't already have it installed, you can download Python.

Step 1: Create a DynamoDB Table


In this step, you use the AWS CLI to create TestTable. The primary key consists of pk (partition key)
and sk (sort key). Both of these attributes are of type Number. The initial throughput settings are 5 read
capacity units and 5 write capacity units.

1. Use the following AWS CLI command to create the table.

aws dynamodb create-table \


--table-name TestTable \
--attribute-definitions \
AttributeName=pk,AttributeType=N \
AttributeName=sk,AttributeType=N \
--key-schema \
AttributeName=pk,KeyType=HASH \
AttributeName=sk,KeyType=RANGE \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5

2. To check the status of the table, use the following command.

aws dynamodb describe-table \


--table-name TestTable \
--query "Table.[TableName,TableStatus,ProvisionedThroughput]"

The table is ready for use when its status is ACTIVE.

Step 2: Register a Scalable Target


Next you register the table's write capacity as a scalable target with Application Auto Scaling. This allows
Application Auto Scaling to adjust the provisioned write capacity for TestTable, but only within the range
of 5–10 capacity units.
Note
DynamoDB auto scaling requires the presence of a service linked role
(AWSServiceRoleForApplicationAutoScaling_DynamoDBTable) that performs auto
scaling actions on your behalf. This role is created automatically for you. For more information,
see Service-Linked Roles for Application Auto Scaling in the Application Auto Scaling User Guide.

1. Enter the following command to register the scalable target.

aws application-autoscaling register-scalable-target \


--service-namespace dynamodb \
--resource-id "table/TestTable" \
--scalable-dimension "dynamodb:table:WriteCapacityUnits" \
--min-capacity 5 \

API Version 2012-08-10


352
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

--max-capacity 10

2. To verify the registration, use the following command.

aws application-autoscaling describe-scalable-targets \


--service-namespace dynamodb \
--resource-id "table/TestTable"

Note
You can also register a scalable target against a global secondary index. For example, for a
global secondary index ("test-index"), the resource ID and scalable dimension arguments are
updated appropriately.

aws application-autoscaling register-scalable-target \


--service-namespace dynamodb \
--resource-id "table/TestTable/index/test-index" \
--scalable-dimension "dynamodb:index:WriteCapacityUnits" \
--min-capacity 5 \
--max-capacity 10

Step 3: Create a Scaling Policy


In this step, you create a scaling policy for TestTable. The policy defines the details under which
Application Auto Scaling can adjust your table's provisioned throughput, and what actions to take when
it does so. You associate this policy with the scalable target that you defined in the previous step (write
capacity units for the TestTable table).

The policy contains the following elements:

• PredefinedMetricSpecification—The metric that Application Auto Scaling is allowed to adjust.


For DynamoDB, the following values are valid values for PredefinedMetricType:
• DynamoDBReadCapacityUtilization
• DynamoDBWriteCapacityUtilization
• ScaleOutCooldown—The minimum amount of time (in seconds) between each Application Auto
Scaling event that increases provisioned throughput. This parameter allows Application Auto Scaling
to continuously, but not aggressively, increase the throughput in response to real-world workloads.
The default setting for ScaleOutCooldown is 0.
• ScaleInCooldown—The minimum amount of time (in seconds) between each Application Auto
Scaling event that decreases provisioned throughput. This parameter allows Application Auto Scaling
to decrease the throughput gradually and predictably. The default setting for ScaleInCooldown is 0.
• TargetValue—Application Auto Scaling ensures that the ratio of consumed capacity to provisioned
capacity stays at or near this value. You define TargetValue as a percentage.

Note
To further understand how TargetValue works, suppose that you have a table with a
provisioned throughput setting of 200 write capacity units. You decide to create a scaling policy
for this table, with a TargetValue of 70 percent.
Now suppose that you begin driving write traffic to the table so that the actual write throughput
is 150 capacity units. The consumed-to-provisioned ratio is now (150 / 200), or 75 percent. This
ratio exceeds your target, so Application Auto Scaling increases the provisioned write capacity

API Version 2012-08-10


353
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

to 215 so that the ratio is (150 / 215), or 69.77 percent—as close to your TargetValue as
possible, but not exceeding it.

For TestTable, you set TargetValue to 50 percent. Application Auto Scaling adjusts the table's
provisioned throughput within the range of 5–10 capacity units (see Step 2: Register a Scalable
Target (p. 352)) so that the consumed-to-provisioned ratio remains at or near 50 percent. You set the
values for ScaleOutCooldown and ScaleInCooldown to 60 seconds.

1. Create a file named scaling-policy.json with the following contents.

{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
},
"ScaleOutCooldown": 60,
"ScaleInCooldown": 60,
"TargetValue": 50.0
}

2. Use the following AWS CLI command to create the policy.

aws application-autoscaling put-scaling-policy \


--service-namespace dynamodb \
--resource-id "table/TestTable" \
--scalable-dimension "dynamodb:table:WriteCapacityUnits" \
--policy-name "MyScalingPolicy" \
--policy-type "TargetTrackingScaling" \
--target-tracking-scaling-policy-configuration file://scaling-policy.json

3. In the output, note that Application Auto Scaling has created two Amazon CloudWatch alarms—one
each for the upper and lower boundary of the scaling target range.
4. Use the following AWS CLI command to view more details about the scaling policy.

aws application-autoscaling describe-scaling-policies \


--service-namespace dynamodb \
--resource-id "table/TestTable" \
--policy-name "MyScalingPolicy"

5. In the output, verify that the policy settings match your specifications from Step 2: Register a
Scalable Target (p. 352) and Step 3: Create a Scaling Policy (p. 353).

Step 4: Drive Write Traffic to TestTable


Now you can test your scaling policy by writing data to TestTable. To do this, you run a Python
program.

1. Create a file named bulk-load-test-table.py with the following contents.

import boto3
dynamodb = boto3.resource('dynamodb')

table = dynamodb.Table("TestTable")

filler = "x" * 100000

API Version 2012-08-10


354
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

i = 0
while (i < 10):
j = 0
while (j < 10):
print (i, j)

table.put_item(
Item={
'pk':i,
'sk':j,
'filler':{"S":filler}
}
)
j += 1
i += 1

2. Enter the following command to run the program.

python bulk-load-test-table.py

The provisioned write capacity for TestTable is very low (5 write capacity units), so the program
stalls occasionally due to write throttling. This is expected behavior.

Let the program continue running while you move on to the next step.

Step 5: View Application Auto Scaling Actions


In this step, you view the Application Auto Scaling actions that are initiated on your behalf. You also
verify that Application Auto Scaling has updated the provisioned write capacity for TestTable.

1. Enter the following command to view the Application Auto Scaling actions.

aws application-autoscaling describe-scaling-activities \


--service-namespace dynamodb

Rerun this command occasionally, while the Python program is running. (It takes several minutes
before your scaling policy is invoked.) You should eventually see the following output.

...
{
"ScalableDimension": "dynamodb:table:WriteCapacityUnits",
"Description": "Setting write capacity units to 10.",
"ResourceId": "table/TestTable",
"ActivityId": "0cc6fb03-2a7c-4b51-b67f-217224c6b656",
"StartTime": 1489088210.175,
"ServiceNamespace": "dynamodb",
"EndTime": 1489088246.85,
"Cause": "monitor alarm AutoScaling-table/TestTable-AlarmHigh-1bb3c8db-1b97-4353-
baf1-4def76f4e1b9 in state ALARM triggered policy MyScalingPolicy",
"StatusMessage": "Successfully set write capacity units to 10. Change successfully
fulfilled by dynamodb.",
"StatusCode": "Successful"
},
...

This indicates that Application Auto Scaling has issued an UpdateTable request to DynamoDB.
2. Enter the following command to verify that DynamoDB increased the table's write capacity.
API Version 2012-08-10
355
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

aws dynamodb describe-table \


--table-name TestTable \
--query "Table.[TableName,TableStatus,ProvisionedThroughput]"

The WriteCapacityUnits should have been scaled from 5 to 10.

(Optional) Step 6: Clean Up


In this tutorial, you created several resources. You can delete these resources if you no longer need them.

1. Delete the scaling policy for TestTable.

aws application-autoscaling delete-scaling-policy \


--service-namespace dynamodb \
--resource-id "table/TestTable" \
--scalable-dimension "dynamodb:table:WriteCapacityUnits" \
--policy-name "MyScalingPolicy"

2. Deregister the scalable target.

aws application-autoscaling deregister-scalable-target \


--service-namespace dynamodb \
--resource-id "table/TestTable" \
--scalable-dimension "dynamodb:table:WriteCapacityUnits"

3. Delete the TestTable table.

aws dynamodb delete-table --table-name TestTable

Using the AWS SDK to Configure Auto Scaling on Amazon


DynamoDB Tables
In addition to using the AWS Management Console and the AWS Command Line Interface (AWS CLI), you
can write applications that interact with Amazon DynamoDB auto scaling. This section contains two Java
programs that you can use to test this functionality:

• EnableDynamoDBAutoscaling.java
• DisableDynamoDBAutoscaling.java

Enabling Application Auto Scaling for a Table


The following program shows an example of setting up an auto scaling policy for a DynamoDB table
(TestTable). It proceeds as follows:

• The program registers write capacity units as a scalable target for TestTable. The range for this
metric is between 5 and 10 write capacity units.

API Version 2012-08-10


356
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

• After the scalable target is created, the program builds a target tracking configuration. The policy
seeks to maintain a 50 percent target ratio between consumed write capacity and provisioned write
capacity.
• The program then creates the scaling policy, based on the target tracking configuration.

The program requires that you provide an Amazon Resource Name (ARN) for a valid Application
Auto Scaling service linked role. (For example: arn:aws:iam::122517410325:role/
AWSServiceRoleForApplicationAutoScaling_DynamoDBTable.) In the following program,
replace SERVICE_ROLE_ARN_GOES_HERE with the actual ARN.

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

import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScalingClient;
import
com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScalingClientBuilder;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsRequest;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsResult;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalingPoliciesRequest;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalingPoliciesResult;
import com.amazonaws.services.applicationautoscaling.model.MetricType;
import com.amazonaws.services.applicationautoscaling.model.PolicyType;
import com.amazonaws.services.applicationautoscaling.model.PredefinedMetricSpecification;
import com.amazonaws.services.applicationautoscaling.model.PutScalingPolicyRequest;
import com.amazonaws.services.applicationautoscaling.model.RegisterScalableTargetRequest;
import com.amazonaws.services.applicationautoscaling.model.ScalableDimension;
import com.amazonaws.services.applicationautoscaling.model.ServiceNamespace;
import
com.amazonaws.services.applicationautoscaling.model.TargetTrackingScalingPolicyConfiguration;

public class EnableDynamoDBAutoscaling {

static AWSApplicationAutoScalingClient aaClient = (AWSApplicationAutoScalingClient)


AWSApplicationAutoScalingClientBuilder.standard().build();

public static void main(String args[]) {

ServiceNamespace ns = ServiceNamespace.Dynamodb;
ScalableDimension tableWCUs = ScalableDimension.DynamodbTableWriteCapacityUnits;
String resourceID = "table/TestTable";

// Define the scalable target


RegisterScalableTargetRequest rstRequest = new RegisterScalableTargetRequest()
.withServiceNamespace(ns)
.withResourceId(resourceID)
.withScalableDimension(tableWCUs)
.withMinCapacity(5)
.withMaxCapacity(10)
.withRoleARN("SERVICE_ROLE_ARN_GOES_HERE");

try {

API Version 2012-08-10


357
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

aaClient.registerScalableTarget(rstRequest);
} catch (Exception e) {
System.err.println("Unable to register scalable target: ");
System.err.println(e.getMessage());
}

// Verify that the target was created


DescribeScalableTargetsRequest dscRequest = new DescribeScalableTargetsRequest()
.withServiceNamespace(ns)
.withScalableDimension(tableWCUs)
.withResourceIds(resourceID);
try {
DescribeScalableTargetsResult dsaResult =
aaClient.describeScalableTargets(dscRequest);
System.out.println("DescribeScalableTargets result: ");
System.out.println(dsaResult);
System.out.println();
} catch (Exception e) {
System.err.println("Unable to describe scalable target: ");
System.err.println(e.getMessage());
}

System.out.println();

// Configure a scaling policy


TargetTrackingScalingPolicyConfiguration targetTrackingScalingPolicyConfiguration =
new TargetTrackingScalingPolicyConfiguration()
.withPredefinedMetricSpecification(
new PredefinedMetricSpecification()
.withPredefinedMetricType(MetricType. DynamoDBWriteCapacityUtilization))
.withTargetValue(50.0)
.withScaleInCooldown(60)
.withScaleOutCooldown(60);

// Create the scaling policy, based on your configuration


PutScalingPolicyRequest pspRequest = new PutScalingPolicyRequest()
.withServiceNamespace(ns)
.withScalableDimension(tableWCUs)
.withResourceId(resourceID)
.withPolicyName("MyScalingPolicy")
.withPolicyType(PolicyType.TargetTrackingScaling)
.withTargetTrackingScalingPolicyConfiguration(targetTrackingScalingPolicyConfiguration);

try {
aaClient.putScalingPolicy(pspRequest);
} catch (Exception e) {
System.err.println("Unable to put scaling policy: ");
System.err.println(e.getMessage());
}

// Verify that the scaling policy was created


DescribeScalingPoliciesRequest dspRequest = new DescribeScalingPoliciesRequest()
.withServiceNamespace(ns)
.withScalableDimension(tableWCUs)
.withResourceId(resourceID);

try {
DescribeScalingPoliciesResult dspResult =
aaClient.describeScalingPolicies(dspRequest);
System.out.println("DescribeScalingPolicies result: ");
System.out.println(dspResult);
} catch (Exception e) {
e.printStackTrace();
System.err.println("Unable to describe scaling policy: ");
System.err.println(e.getMessage());
}

API Version 2012-08-10


358
Amazon DynamoDB Developer Guide
Managing Throughput Capacity with Auto Scaling

Disabling Application Auto Scaling for a Table


The following program reverses the previous process. It removes the auto scaling policy and then
deregisters the scalable target.

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

import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScalingClient;
import com.amazonaws.services.applicationautoscaling.model.DeleteScalingPolicyRequest;
import com.amazonaws.services.applicationautoscaling.model.DeregisterScalableTargetRequest;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsRequest;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsResult;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalingPoliciesRequest;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalingPoliciesResult;
import com.amazonaws.services.applicationautoscaling.model.ScalableDimension;
import com.amazonaws.services.applicationautoscaling.model.ServiceNamespace;

public class DisableDynamoDBAutoscaling {

static AWSApplicationAutoScalingClient aaClient = new


AWSApplicationAutoScalingClient();

public static void main(String args[]) {

ServiceNamespace ns = ServiceNamespace.Dynamodb;
ScalableDimension tableWCUs = ScalableDimension.DynamodbTableWriteCapacityUnits;
String resourceID = "table/TestTable";

// Delete the scaling policy


DeleteScalingPolicyRequest delSPRequest = new DeleteScalingPolicyRequest()
.withServiceNamespace(ns)
.withScalableDimension(tableWCUs)
.withResourceId(resourceID)
.withPolicyName("MyScalingPolicy");

try {
aaClient.deleteScalingPolicy(delSPRequest);
} catch (Exception e) {
System.err.println("Unable to delete scaling policy: ");
System.err.println(e.getMessage());
}

// Verify that the scaling policy was deleted


DescribeScalingPoliciesRequest descSPRequest = new DescribeScalingPoliciesRequest()
.withServiceNamespace(ns)

API Version 2012-08-10


359
Amazon DynamoDB Developer Guide
Tagging Resources

.withScalableDimension(tableWCUs)
.withResourceId(resourceID);

try {
DescribeScalingPoliciesResult dspResult =
aaClient.describeScalingPolicies(descSPRequest);
System.out.println("DescribeScalingPolicies result: ");
System.out.println(dspResult);
} catch (Exception e) {
e.printStackTrace();
System.err.println("Unable to describe scaling policy: ");
System.err.println(e.getMessage());
}

System.out.println();

// Remove the scalable target


DeregisterScalableTargetRequest delSTRequest = new DeregisterScalableTargetRequest()
.withServiceNamespace(ns)
.withScalableDimension(tableWCUs)
.withResourceId(resourceID);

try {
aaClient.deregisterScalableTarget(delSTRequest);
} catch (Exception e) {
System.err.println("Unable to deregister scalable target: ");
System.err.println(e.getMessage());
}

// Verify that the scalable target was removed


DescribeScalableTargetsRequest dscRequest = new DescribeScalableTargetsRequest()
.withServiceNamespace(ns)
.withScalableDimension(tableWCUs)
.withResourceIds(resourceID);

try {
DescribeScalableTargetsResult dsaResult =
aaClient.describeScalableTargets(dscRequest);
System.out.println("DescribeScalableTargets result: ");
System.out.println(dsaResult);
System.out.println();
} catch (Exception e) {
System.err.println("Unable to describe scalable target: ");
System.err.println(e.getMessage());
}

Adding Tags and Labels to Resources


You can label Amazon DynamoDB resources using tags. Tags let you categorize your resources in
different ways, for example, by purpose, owner, environment, or other criteria. Tags can help you do the
following:

• Quickly identify a resource based on the tags that you assigned to it.
• See AWS bills broken down by tags.

API Version 2012-08-10


360
Amazon DynamoDB Developer Guide
Tagging Resources

Note
Any local secondary indexes (LSI) and global secondary indexes (GSI) related to tagged tables
are labeled with the same tags automatically. Currently, DynamoDB Streams usage cannot be
tagged.

Tagging is supported by AWS services like Amazon EC2, Amazon S3, DynamoDB, and more. Efficient
tagging can provide cost insights by enabling you to create reports across services that carry a specific
tag.

To get started with tagging, do the following:

1. Understand Tagging Restrictions in DynamoDB (p. 361).


2. Create tags by using Tagging Resources in DynamoDB (p. 361).
3. Use Cost Allocation Reports (p. 363) to track your AWS costs per active tag.

Finally, it is good practice to follow optimal tagging strategies. For information, see AWS Tagging
Strategies.

Tagging Restrictions in DynamoDB


Each tag consists of a key and a value, both of which you define. The following restrictions apply:

• Each DynamoDB table can have only one tag with the same key. If you try to add an existing tag (same
key), the existing tag value is updated to the new value.
• Tag keys and values are case sensitive.
• The maximum key length is 128 Unicode characters.
• The maximum value length is 256 Unicode characters.
• The allowed characters are letters, white space, and numbers, plus the following special characters: +
- = . _ : /
• The maximum number of tags per resource is 50.
• AWS-assigned tag names and values are automatically assigned the aws: prefix, which you can't
assign. AWS-assigned tag names don't count toward the tag limit of 50. User-assigned tag names have
the prefix user: in the cost allocation report.
• You can't backdate the application of a tag.

Tagging Resources in DynamoDB


You can use the Amazon DynamoDB console or the AWS Command Line Interface (AWS CLI) to add, list,
edit, or delete tags. You can then activate these user-defined tags so that they appear on the AWS Billing
and Cost Management console for cost allocation tracking. For more information, see Cost Allocation
Reports (p. 363).

For bulk editing, you can also use Tag Editor on the AWS Management Console. For more information,
see Working with Tag Editor.

To use the DynamoDB API instead, see the following operations in the Amazon DynamoDB API
Reference:

• TagResource
• UntagResource
• ListTagsOfResource

API Version 2012-08-10


361
Amazon DynamoDB Developer Guide
Tagging Resources

Topics
• Adding Tags to New or Existing Tables (Console) (p. 362)
• Adding Tags to New or Existing Tables (AWS CLI) (p. 362)

Adding Tags to New or Existing Tables (Console)


You can use the DynamoDB console to add tags to new tables when you create them, or to add, edit, or
delete tags for existing tables.

To tag resources on creation (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, choose Tables, and then choose Create table.
3. On the Create DynamoDB table page, provide a name and primary key. Choose Add tags and enter
the tags that you want to use.

For information about tag structure, see Tagging Restrictions in DynamoDB (p. 361).

For more information about creating tables, see Basic Operations on DynamoDB Tables (p. 336).

To tag existing resources (console)

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

1. In the navigation pane, choose Tables.


2. Choose a table in the list, and then choose the Tags tab to add, edit, or delete your tags.

Adding Tags to New or Existing Tables (AWS CLI)


The following examples show how to use the AWS CLI to specify tags when you create tables and
indexes, and to tag existing resources.

To tag resources on creation (AWS CLI)

• The following example creates a new Movies table and adds the Owner tag with a value of
blueTeam:

aws dynamodb create-table \


--table-name Movies \
--attribute-definitions AttributeName=Title,AttributeType=S \
--key-schema AttributeName=Title,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
--tags Key=Owner,Value=blueTeam

To tag existing resources (AWS CLI)

• The following example adds the Owner tag with a value of blueTeam for the Movies table:

aws dynamodb tag-resource \


--resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/Movies \
--tags Key=Owner,Value=blueTeam

API Version 2012-08-10


362
Amazon DynamoDB Developer Guide
Working with Tables: Java

To list all tags for a table (AWS CLI)

• The following example lists all the tags that are associated with the Movies table:

aws dynamodb list-tags-of-resource \


--resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/Movies

Cost Allocation Reports


AWS uses tags to organize resource costs on your cost allocation report. AWS provides two types of cost
allocation tags:

• An AWS-generated tag. AWS defines, creates, and applies this tag for you.
• User-defined tags. You define, create, and apply these tags.

You must activate both types of tags separately before they can appear in Cost Explorer or on a cost
allocation report.

To activate AWS-generated tags:

1. Sign in to the AWS Management Console and open the Billing and Cost Management console at
https://console.aws.amazon.com/billing/home#/.
2. In the navigation pane, choose Cost Allocation Tags.
3. Under AWS-Generated Cost Allocation Tags, choose Activate.

To activate user-defined tags:

1. Sign in to the AWS Management Console and open the Billing and Cost Management console at
https://console.aws.amazon.com/billing/home#/.
2. In the navigation pane, choose Cost Allocation Tags.
3. Under User-Defined Cost Allocation Tags, choose Activate.

After you create and activate tags, AWS generates a cost allocation report with your usage and costs
grouped by your active tags. The cost allocation report includes all of your AWS costs for each billing
period. The report includes both tagged and untagged resources, so that you can clearly organize the
charges for resources.
Note
Currently, any data transferred out from DynamoDB won't be broken down by tags on cost
allocation reports.

For more information, see Using Cost Allocation Tags.

Working with DynamoDB Tables in Java


You can use the AWS SDK for Java to create, update, and delete Amazon DynamoDB tables, list all the
tables in your account, or get information about a specific table.

Topics
• Creating a Table (p. 364)
• Updating a Table (p. 365)
• Deleting a Table (p. 365)

API Version 2012-08-10


363
Amazon DynamoDB Developer Guide
Working with Tables: Java

• Listing Tables (p. 366)


• Example: Create, Update, Delete, and List Tables Using the AWS SDK for Java Document
API (p. 366)

Creating a Table
To create a table, you must provide the table name, its primary key, and the provisioned throughput
values. The following code snippet creates an example table that uses a numeric type attribute ID as its
primary key.

To create a table using the AWS SDK for Java API

1. Create an instance of the DynamoDB class.


2. Instantiate a CreateTableRequest to provide the request information.

You must provide the table name, attribute definitions, key schema, and provisioned throughput
values.
3. Execute the createTable method by providing the request object as a parameter.

The following code example demonstrates the preceding steps.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

List<AttributeDefinition> attributeDefinitions= new ArrayList<AttributeDefinition>();


attributeDefinitions.add(new
AttributeDefinition().withAttributeName("Id").withAttributeType("N"));

List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();


keySchema.add(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH));

CreateTableRequest request = new CreateTableRequest()


.withTableName(tableName)
.withKeySchema(keySchema)
.withAttributeDefinitions(attributeDefinitions)
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits(5L)
.withWriteCapacityUnits(6L));

Table table = dynamoDB.createTable(request);

table.waitForActive();

The table is not ready for use until DynamoDB creates it and sets its status to ACTIVE. The createTable
request returns a Table object that you can use to obtain more information about the table.

Example

TableDescription tableDescription =
dynamoDB.getTable(tableName).describe();

System.out.printf("%s: %s \t ReadCapacityUnits: %d \t WriteCapacityUnits: %d",


tableDescription.getTableStatus(),
tableDescription.getTableName(),
tableDescription.getProvisionedThroughput().getReadCapacityUnits(),
tableDescription.getProvisionedThroughput().getWriteCapacityUnits());

You can call the describe method of the client to get table information at any time.

API Version 2012-08-10


364
Amazon DynamoDB Developer Guide
Working with Tables: Java

Example

TableDescription tableDescription = dynamoDB.getTable(tableName).describe();

Updating a Table
You can update only the provisioned throughput values of an existing table. Depending on your
application requirements, you might need to update these values.
Note
For more information about throughput increases and decreases per day, see Service, Account,
and Table Limits in Amazon DynamoDB (p. 959).

To update a table using the AWS SDK for Java API

1. Create an instance of the Table class.


2. Create an instance of the ProvisionedThroughput class to provide the new throughput values.
3. Execute the updateTable method by providing the ProvisionedThroughput instance as a
parameter.

The following code example demonstrates the preceding steps.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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

ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput()


.withReadCapacityUnits(15L)
.withWriteCapacityUnits(12L);

table.updateTable(provisionedThroughput);

table.waitForActive();

Deleting a Table
To delete a table using the AWS SDK for Java API

1. Create an instance of the Table class.


2. Create an instance of the DeleteTableRequest class and provide the table name that you want to
delete.
3. Execute the deleteTable method by providing the Table instance as a parameter.

The following code example demonstrates the preceding steps.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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

table.delete();

API Version 2012-08-10


365
Amazon DynamoDB Developer Guide
Working with Tables: Java

table.waitForDelete();

Listing Tables
To list tables in your account, create an instance of DynamoDB and execute the listTables method.
The ListTables operation requires no parameters.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

TableCollection<ListTablesResult> tables = dynamoDB.listTables();


Iterator<Table> iterator = tables.iterator();

while (iterator.hasNext()) {
Table table = iterator.next();
System.out.println(table.getTableName());
}

Example: Create, Update, Delete, and List Tables Using the AWS
SDK for Java Document API
The following code example uses the AWS SDK for Java Document API to create, update, and
delete an Amazon DynamoDB table (ExampleTable). As part of the table update, it increases the
provisioned throughput values. The example also lists all the tables in your account and gets the
description of a specific table. 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.
*/

package com.amazonaws.codesamples.document;

import java.util.ArrayList;
import java.util.Iterator;

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.TableCollection;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ListTablesResult;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.TableDescription;

API Version 2012-08-10


366
Amazon DynamoDB Developer Guide
Working with Tables: Java

public class DocumentAPITableExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

static String tableName = "ExampleTable";

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

createExampleTable();
listMyTables();
getTableInformation();
updateExampleTable();

deleteExampleTable();
}

static void createExampleTable() {

try {

List<AttributeDefinition> attributeDefinitions = new


ArrayList<AttributeDefinition>();
attributeDefinitions.add(new
AttributeDefinition().withAttributeName("Id").withAttributeType("N"));

List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();


keySchema.add(new
KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH)); // Partition

// key

CreateTableRequest request = new


CreateTableRequest().withTableName(tableName).withKeySchema(keySchema)
.withAttributeDefinitions(attributeDefinitions).withProvisionedThroughput(
new
ProvisionedThroughput().withReadCapacityUnits(5L).withWriteCapacityUnits(6L));

System.out.println("Issuing CreateTable request for " + tableName);


Table table = dynamoDB.createTable(request);

System.out.println("Waiting for " + tableName + " to be created...this may take


a while...");
table.waitForActive();

getTableInformation();

}
catch (Exception e) {
System.err.println("CreateTable request failed for " + tableName);
System.err.println(e.getMessage());
}

static void listMyTables() {

TableCollection<ListTablesResult> tables = dynamoDB.listTables();


Iterator<Table> iterator = tables.iterator();

System.out.println("Listing table names");

while (iterator.hasNext()) {
Table table = iterator.next();
System.out.println(table.getTableName());

API Version 2012-08-10


367
Amazon DynamoDB Developer Guide
Working with Tables: .NET

}
}

static void getTableInformation() {

System.out.println("Describing " + tableName);

TableDescription tableDescription = dynamoDB.getTable(tableName).describe();


System.out.format(
"Name: %s:\n" + "Status: %s \n" + "Provisioned Throughput (read capacity units/
sec): %d \n"
+ "Provisioned Throughput (write capacity units/sec): %d \n",
tableDescription.getTableName(), tableDescription.getTableStatus(),
tableDescription.getProvisionedThroughput().getReadCapacityUnits(),
tableDescription.getProvisionedThroughput().getWriteCapacityUnits());
}

static void updateExampleTable() {

Table table = dynamoDB.getTable(tableName);


System.out.println("Modifying provisioned throughput for " + tableName);

try {
table.updateTable(new
ProvisionedThroughput().withReadCapacityUnits(6L).withWriteCapacityUnits(7L));

table.waitForActive();
}
catch (Exception e) {
System.err.println("UpdateTable request failed for " + tableName);
System.err.println(e.getMessage());
}
}

static void deleteExampleTable() {

Table table = dynamoDB.getTable(tableName);


try {
System.out.println("Issuing DeleteTable request for " + tableName);
table.delete();

System.out.println("Waiting for " + tableName + " to be deleted...this may take


a while...");

table.waitForDelete();
}
catch (Exception e) {
System.err.println("DeleteTable request failed for " + tableName);
System.err.println(e.getMessage());
}
}

Working with DynamoDB Tables in .NET


You can use the AWS SDK for .NET to create, update, and delete tables, list all the tables in your account,
or get information about a specific table.

The following are the common steps for Amazon DynamoDB table operations using the AWS SDK
for .NET.

1. Create an instance of the AmazonDynamoDBClient class (the client).

API Version 2012-08-10


368
Amazon DynamoDB Developer Guide
Working with Tables: .NET

2. Provide the required and optional parameters for the operation by creating the corresponding
request objects.

For example, create a CreateTableRequest object to create a table and UpdateTableRequest


object to update an existing table.
3. Execute the appropriate method provided by the client that you created in the preceding step.

Note
The examples in this section don't work with .NET core because it doesn't support synchronous
methods. For more information, see AWS Asynchronous APIs for .NET.

Topics
• Creating a Table (p. 369)
• Updating a Table (p. 370)
• Deleting a Table (p. 371)
• Listing Tables (p. 371)
• Example: Create, Update, Delete, and List Tables Using the AWS SDK for .NET Low-Level
API (p. 372)

Creating a Table
To create a table, you must provide the table name, its primary key, and the provisioned throughput
values.

To create a table using the AWS SDK for .NET low-level API

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the CreateTableRequest class to provide the request information.

You must provide the table name, primary key, and the provisioned throughput values.
3. Execute the AmazonDynamoDBClient.CreateTable method by providing the request object as a
parameter.

The following C# example demonstrates the preceding steps. The sample creates a table
(ProductCatalog) that uses Id as the primary key and set of provisioned throughput values.
Depending on your application requirements, you can update the provisioned throughput values by
using the UpdateTable API.

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new CreateTableRequest


{
TableName = tableName,
AttributeDefinitions = new List<AttributeDefinition>()
{
new AttributeDefinition
{
AttributeName = "Id",
AttributeType = "N"
}
},
KeySchema = new List<KeySchemaElement>()
{
new KeySchemaElement
{

API Version 2012-08-10


369
Amazon DynamoDB Developer Guide
Working with Tables: .NET

AttributeName = "Id",
KeyType = "HASH" //Partition key
}
},
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = 10,
WriteCapacityUnits = 5
}
};

var response = client.CreateTable(request);

You must wait until DynamoDB creates the table and sets its status to ACTIVE. The CreateTable
response includes the TableDescription property that provides the necessary table information.

Example

var result = response.CreateTableResult;


var tableDescription = result.TableDescription;
Console.WriteLine("{1}: {0} \t ReadCapacityUnits: {2} \t WriteCapacityUnits: {3}",
tableDescription.TableStatus,
tableDescription.TableName,
tableDescription.ProvisionedThroughput.ReadCapacityUnits,
tableDescription.ProvisionedThroughput.WriteCapacityUnits);

string status = tableDescription.TableStatus;


Console.WriteLine(tableName + " - " + status);

You can also call the DescribeTable method of the client to get table information at any time.

Example

var res = client.DescribeTable(new DescribeTableRequest{TableName = "ProductCatalog"});

Updating a Table
You can update only the provisioned throughput values of an existing table. Depending on your
application requirements, you might need to update these values.
Note
You can increase throughput capacity as often as needed, and decrease it within certain
constraints. For more information about throughput increases and decreases per day, see
Service, Account, and Table Limits in Amazon DynamoDB (p. 959).

To update a table using the AWS SDK for .NET low-level API

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the UpdateTableRequest class to provide the request information.

You must provide the table name and the new provisioned throughput values.
3. Execute the AmazonDynamoDBClient.UpdateTable method by providing the request object as a
parameter.

The following C# example demonstrates the preceding steps.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

API Version 2012-08-10


370
Amazon DynamoDB Developer Guide
Working with Tables: .NET

string tableName = "ExampleTable";

var request = new UpdateTableRequest()


{
TableName = tableName,
ProvisionedThroughput = new ProvisionedThroughput()
{
// Provide new values.
ReadCapacityUnits = 20,
WriteCapacityUnits = 10
}
};
var response = client.UpdateTable(request);

Deleting a Table
Follow these steps to delete a table using the .NET low-level API.

To delete a table using the AWS SDK for .NET low-level API

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the DeleteTableRequest class, and provide the table name that you want to
delete.
3. Execute the AmazonDynamoDBClient.DeleteTable method by providing the request object as a
parameter.

The following C# code example demonstrates the preceding steps.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ExampleTable";

var request = new DeleteTableRequest{ TableName = tableName };


var response = client.DeleteTable(request);

Listing Tables
To list tables in your account using the AWS SDK for .NET low-level API, create an instance of the
AmazonDynamoDBClient and execute the ListTables method.

The ListTables operation requires no parameters. However, you can specify optional parameters. For
example, you can set the Limit parameter if you want to use paging to limit the number of table
names per page. This requires you to create a ListTablesRequest object and provide optional
parameters as shown in the following C# example. Along with the page size, the request sets the
ExclusiveStartTableName parameter. Initially, ExclusiveStartTableName is null. However, after
fetching the first page of results, to retrieve the next page of results, you must set this parameter value
to the LastEvaluatedTableName property of the current result.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

// Initial value for the first page of table names.


string lastEvaluatedTableName = null;
do
{
// Create a request object to specify optional parameters.
var request = new ListTablesRequest

API Version 2012-08-10


371
Amazon DynamoDB Developer Guide
Working with Tables: .NET

{
Limit = 10, // Page size.
ExclusiveStartTableName = lastEvaluatedTableName
};

var response = client.ListTables(request);


ListTablesResult result = response.ListTablesResult;
foreach (string name in result.TableNames)
Console.WriteLine(name);

lastEvaluatedTableName = result.LastEvaluatedTableName;

} while (lastEvaluatedTableName != null);

Example: Create, Update, Delete, and List Tables Using the AWS
SDK for .NET Low-Level API
The following C# example creates, updates, and deletes a table (ExampleTable). It also lists all the
tables in your account and gets the description of a specific table. The table update increases the
provisioned throughput values. For step-by-step instructions to test the following example, see .NET
Code Examples (p. 333).

/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class LowLevelTableExample
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
private static string tableName = "ExampleTable";

static void Main(string[] args)


{
try
{
CreateExampleTable();
ListMyTables();
GetTableInformation();
UpdateExampleTable();

DeleteExampleTable();

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

API Version 2012-08-10


372
Amazon DynamoDB Developer Guide
Working with Tables: .NET

catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }


catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }
}

private static void CreateExampleTable()


{
Console.WriteLine("\n*** Creating table ***");
var request = new CreateTableRequest
{
AttributeDefinitions = new List<AttributeDefinition>()
{
new AttributeDefinition
{
AttributeName = "Id",
AttributeType = "N"
},
new AttributeDefinition
{
AttributeName = "ReplyDateTime",
AttributeType = "N"
}
},
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = "Id",
KeyType = "HASH" //Partition key
},
new KeySchemaElement
{
AttributeName = "ReplyDateTime",
KeyType = "RANGE" //Sort key
}
},
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = 5,
WriteCapacityUnits = 6
},
TableName = tableName
};

var response = client.CreateTable(request);

var tableDescription = response.TableDescription;


Console.WriteLine("{1}: {0} \t ReadsPerSec: {2} \t WritesPerSec: {3}",
tableDescription.TableStatus,
tableDescription.TableName,
tableDescription.ProvisionedThroughput.ReadCapacityUnits,
tableDescription.ProvisionedThroughput.WriteCapacityUnits);

string status = tableDescription.TableStatus;


Console.WriteLine(tableName + " - " + status);

WaitUntilTableReady(tableName);
}

private static void ListMyTables()


{
Console.WriteLine("\n*** listing tables ***");
string lastTableNameEvaluated = null;
do
{
var request = new ListTablesRequest

API Version 2012-08-10


373
Amazon DynamoDB Developer Guide
Working with Tables: .NET

{
Limit = 2,
ExclusiveStartTableName = lastTableNameEvaluated
};

var response = client.ListTables(request);


foreach (string name in response.TableNames)
Console.WriteLine(name);

lastTableNameEvaluated = response.LastEvaluatedTableName;
} while (lastTableNameEvaluated != null);
}

private static void GetTableInformation()


{
Console.WriteLine("\n*** Retrieving table information ***");
var request = new DescribeTableRequest
{
TableName = tableName
};

var response = client.DescribeTable(request);

TableDescription description = response.Table;


Console.WriteLine("Name: {0}", description.TableName);
Console.WriteLine("# of items: {0}", description.ItemCount);
Console.WriteLine("Provision Throughput (reads/sec): {0}",
description.ProvisionedThroughput.ReadCapacityUnits);
Console.WriteLine("Provision Throughput (writes/sec): {0}",
description.ProvisionedThroughput.WriteCapacityUnits);
}

private static void UpdateExampleTable()


{
Console.WriteLine("\n*** Updating table ***");
var request = new UpdateTableRequest()
{
TableName = tableName,
ProvisionedThroughput = new ProvisionedThroughput()
{
ReadCapacityUnits = 6,
WriteCapacityUnits = 7
}
};

var response = client.UpdateTable(request);

WaitUntilTableReady(tableName);
}

private static void DeleteExampleTable()


{
Console.WriteLine("\n*** Deleting table ***");
var request = new DeleteTableRequest
{
TableName = tableName
};

var response = client.DeleteTable(request);

Console.WriteLine("Table is being deleted...");


}

private static void WaitUntilTableReady(string tableName)


{
string status = null;

API Version 2012-08-10


374
Amazon DynamoDB Developer Guide
Working with Items

// Let us wait until table is created. Call DescribeTable.


do
{
System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
try
{
var res = client.DescribeTable(new DescribeTableRequest
{
TableName = tableName
});

Console.WriteLine("Table name: {0}, status: {1}",


res.Table.TableName,
res.Table.TableStatus);
status = res.Table.TableStatus;
}
catch (ResourceNotFoundException)
{
// DescribeTable is eventually consistent. So you might
// get resource not found. So we handle the potential exception.
}
} while (status != "ACTIVE");
}
}
}

Working with Items and Attributes


In Amazon DynamoDB, an item is a collection of attributes. Each attribute has a name and a value. An
attribute value can be a scalar, a set, or a document type. For more information, see Amazon DynamoDB:
How It Works (p. 2).

DynamoDB provides four operations for basic create, read, update, and delete (CRUD) functionality:

• PutItem — Create an item.


• GetItem — Read an item.
• UpdateItem — Update an item.
• DeleteItem — Delete an item.

Each of these operations requires that you specify the primary key of the item that you want to work
with. For example, to read an item using GetItem, you must specify the partition key and sort key (if
applicable) for that item.

In addition to the four basic CRUD operations, DynamoDB also provides the following:

• BatchGetItem — Read up to 100 items from one or more tables.


• BatchWriteItem — Create or delete up to 25 items in one or more tables.

These batch operations combine multiple CRUD operations into a single request. In addition, the batch
operations read and write items in parallel to minimize response latencies.

This section describes how to use these operations and includes related topics, such as conditional
updates and atomic counters. This section also includes example code that uses the AWS SDKs.

Topics
• Reading an Item (p. 376)
• Writing an Item (p. 376)

API Version 2012-08-10


375
Amazon DynamoDB Developer Guide
Reading an Item

• Return Values (p. 378)


• Batch Operations (p. 379)
• Atomic Counters (p. 381)
• Conditional Writes (p. 381)
• Using Expressions in DynamoDB (p. 386)
• Expiring Items Using Time to Live (TTL) (p. 409)
• Working with Items: Java (p. 415)
• Working with Items: .NET (p. 435)

Reading an Item
To read an item from a DynamoDB table, use the GetItem operation. You must provide the name of the
table, along with the primary key of the item you want.

Example
The following AWS CLI example shows how to read an item from the ProductCatalog table.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"1"}}'

Note
With GetItem, you must specify the entire primary key, not just part of it. For example, if a
table has a composite primary key (partition key and sort key), you must supply a value for the
partition key and a value for the sort key.

A GetItem request performs an eventually consistent read by default. You can use the
ConsistentRead parameter to request a strongly consistent read instead. (This consumes additional
read capacity units, but it returns the most up-to-date version of the item.)

GetItem returns all of the item's attributes. You can use a projection expression to return only some of
the attributes. For more information, see Projection Expressions (p. 389).

To return the number of read capacity units consumed by GetItem, set the ReturnConsumedCapacity
parameter to TOTAL.

Example
The following AWS Command Line Interface (AWS CLI) example shows some of the optional GetItem
parameters.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"1"}}' \
--consistent-read \
--projection-expression "Description, Price, RelatedItems" \
--return-consumed-capacity TOTAL

Writing an Item
To create, update, or delete an item in a DynamoDB table, use one of the following operations:

API Version 2012-08-10


376
Amazon DynamoDB Developer Guide
Writing an Item

• PutItem
• UpdateItem
• DeleteItem

For each of these operations, you must specify the entire primary key, not just part of it. For example, if a
table has a composite primary key (partition key and sort key), you must provide a value for the partition
key and a value for the sort key.

To return the number of write capacity units consumed by any of these operations, set the
ReturnConsumedCapacity parameter to one of the following:

• TOTAL — Returns the total number of write capacity units consumed.


• INDEXES — Returns the total number of write capacity units consumed, with subtotals for the table
and any secondary indexes that were affected by the operation.
• NONE — No write capacity details are returned. (This is the default.)

PutItem
PutItem creates a new item. If an item with the same key already exists in the table, it is replaced with
the new item.

Example

Write a new item to the Thread table. The primary key for Thread consists of ForumName (partition
key) and Subject (sort key).

aws dynamodb put-item \


--table-name Thread \
--item file://item.json

The arguments for --item are stored in the item.json file.

{
"ForumName": {"S": "Amazon DynamoDB"},
"Subject": {"S": "New discussion thread"},
"Message": {"S": "First post in this thread"},
"LastPostedBy": {"S": "[email protected]"},
"LastPostDateTime": {"S": "201603190422"}
}

UpdateItem
If an item with the specified key does not exist, UpdateItem creates a new item. Otherwise, it modifies
an existing item's attributes.

You use an update expression to specify the attributes that you want to modify and their new values. For
more information, see Update Expressions (p. 401).

Within the update expression, you use expression attribute values as placeholders for the actual values.
For more information, see Expression Attribute Values (p. 392).

API Version 2012-08-10


377
Amazon DynamoDB Developer Guide
Return Values

Example
Modify various attributes in the Thread item. The optional ReturnValues parameter shows the item as
it appears after the update. For more information, see Return Values (p. 378).

aws dynamodb update-item \


--table-name Thread \
--key file://key.json \
--update-expression "SET Answered = :zero, Replies = :zero, LastPostedBy
= :lastpostedby" \
--expression-attribute-values file://expression-attribute-values.json \
--return-values ALL_NEW

The arguments for --key are stored in the key.json file.

{
"ForumName": {"S": "Amazon DynamoDB"},
"Subject": {"S": "New discussion thread"}
}

The arguments for --expression-attribute-values are stored in the expression-attribute-


values.json file.

{
":zero": {"N":"0"},
":lastpostedby": {"S":"[email protected]"}
}

DeleteItem
DeleteItem deletes the item with the specified key.

Example
The following AWS CLI example shows how to delete the Thread item.

aws dynamodb delete-item \


--table-name Thread \
--key file://key.json

Return Values
In some cases, you might want DynamoDB to return certain attribute values as they appeared
before or after you modified them. The PutItem, UpdateItem, and DeleteItem operations have
a ReturnValues parameter that you can use to return the attribute values before or after they are
modified.

The default value for ReturnValues is NONE, meaning that DynamoDB does not return any information
about attributes that were modified.

The following are the other valid settings for ReturnValues, organized by DynamoDB API operation.

API Version 2012-08-10


378
Amazon DynamoDB Developer Guide
Batch Operations

PutItem
• ReturnValues: ALL_OLD
• If you overwrite an existing item, ALL_OLD returns the entire item as it appeared before the
overwrite.
• If you write a nonexistent item, ALL_OLD has no effect.

UpdateItem
The most common usage for UpdateItem is to update an existing item. However, UpdateItem actually
performs an upsert, meaning that it automatically creates the item if it doesn't already exist.

• ReturnValues: ALL_OLD
• If you update an existing item, ALL_OLD returns the entire item as it appeared before the update.
• If you update a nonexistent item (upsert), ALL_OLD has no effect.
• ReturnValues: ALL_NEW
• If you update an existing item, ALL_NEW returns the entire item as it appeared after the update.
• If you update a nonexistent item (upsert), ALL_NEW returns the entire item.
• ReturnValues: UPDATED_OLD
• If you update an existing item, UPDATED_OLD returns only the updated attributes, as they appeared
before the update.
• If you update a nonexistent item (upsert), UPDATED_OLD has no effect.
• ReturnValues: UPDATED_NEW
• If you update an existing item, UPDATED_NEW returns only the affected attributes, as they appeared
after the update.
• If you update a nonexistent item (upsert), UPDATED_NEW returns only the updated attributes, as
they appear after the update.

DeleteItem
• ReturnValues: ALL_OLD
• If you delete an existing item, ALL_OLD returns the entire item as it appeared before you deleted it.
• If you delete a nonexistent item, ALL_OLD doesn't return any data.

Batch Operations
For applications that need to read or write multiple items, DynamoDB provides the BatchGetItem
and BatchWriteItem operations. Using these operations can reduce the number of network round
trips from your application to DynamoDB. In addition, DynamoDB performs the individual read or
write operations in parallel. Your applications benefit from this parallelism without having to manage
concurrency or threading.

The batch operations are essentially wrappers around multiple read or write requests. For example, if
a BatchGetItem request contains five items, DynamoDB performs five GetItem operations on your
behalf. Similarly, if a BatchWriteItem request contains two put requests and four delete requests,
DynamoDB performs two PutItem and four DeleteItem requests.

In general, a batch operation does not fail unless all the requests in the batch fail. For example, suppose
that you perform a BatchGetItem operation, but one of the individual GetItem requests in the batch
API Version 2012-08-10
379
Amazon DynamoDB Developer Guide
Batch Operations

fails. In this case, BatchGetItem returns the keys and data from the GetItem request that failed. The
other GetItem requests in the batch are not affected.

BatchGetItem
A single BatchGetItem operation can contain up to 100 individual GetItem requests and can retrieve
up to 16 MB of data. In addition, a BatchGetItem operation can retrieve items from multiple tables.

Example

Retrieve two items from the Thread table, using a projection expression to return only some of the
attributes.

aws dynamodb batch-get-item \


--request-items file://request-items.json

The arguments for --request-items are stored in the request-items.json file.

{
"Thread": {
"Keys": [
{
"ForumName":{"S": "Amazon DynamoDB"},
"Subject":{"S": "DynamoDB Thread 1"}
},
{
"ForumName":{"S": "Amazon S3"},
"Subject":{"S": "S3 Thread 1"}
}
],
"ProjectionExpression":"ForumName, Subject, LastPostedDateTime, Replies"
}
}

BatchWriteItem
The BatchWriteItem operation can contain up to 25 individual PutItem and DeleteItem requests
and can write up to 16 MB of data. (The maximum size of an individual item is 400 KB.) In addition, a
BatchWriteItem operation can put or delete items in multiple tables.
Note
BatchWriteItem does not support UpdateItem requests.

Example

Write two items to the ProductCatalog table.

aws dynamodb batch-write-item \


--request-items file://request-items.json

The arguments for --request-items are stored in the request-items.json file.

{
"ProductCatalog": [

API Version 2012-08-10


380
Amazon DynamoDB Developer Guide
Atomic Counters

{
"PutRequest": {
"Item": {
"Id": { "N": "601" },
"Description": { "S": "Snowboard" },
"QuantityOnHand": { "N": "5" },
"Price": { "N": "100" }
}
}
},
{
"PutRequest": {
"Item": {
"Id": { "N": "602" },
"Description": { "S": "Snow shovel" }
}
}
}
]
}

Atomic Counters
You can use the UpdateItem operation to implement an atomic counter—a numeric attribute that
is incremented, unconditionally, without interfering with other write requests. (All write requests
are applied in the order in which they were received.) With an atomic counter, the updates are not
idempotent. In other words, the numeric value increments each time you call UpdateItem.

You might use an atomic counter to track the number of visitors to a website. In this case, your
application would increment a numeric value, regardless of its current value. If an UpdateItem
operation fails, the application could simply retry the operation. This would risk updating the counter
twice, but you could probably tolerate a slight overcounting or undercounting of website visitors.

An atomic counter would not be appropriate where overcounting or undercounting can't be tolerated
(for example, in a banking application). In this case, it is safer to use a conditional update instead of an
atomic counter.

For more information, see Incrementing and Decrementing Numeric Attributes (p. 405).

Example
The following AWS CLI example increments the Price of a product by 5. (Because UpdateItem is not
idempotent, the Price increases every time you run this example.)

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id": { "N": "601" }}' \
--update-expression "SET Price = Price + :incr" \
--expression-attribute-values '{":incr":{"N":"5"}}' \
--return-values UPDATED_NEW

Conditional Writes
By default, the DynamoDB write operations (PutItem, UpdateItem, DeleteItem) are unconditional:
Each operation overwrites an existing item that has the specified primary key.

DynamoDB optionally supports conditional writes for these operations. A conditional write succeeds only
if the item attributes meet one or more expected conditions. Otherwise, it returns an error. Conditional

API Version 2012-08-10


381
Amazon DynamoDB Developer Guide
Conditional Writes

writes are helpful in many situations. For example, you might want a PutItem operation to succeed
only if there is not already an item with the same primary key. Or you could prevent an UpdateItem
operation from modifying an item if one of its attributes has a certain value.

Conditional writes are helpful in cases where multiple users attempt to modify the same item. Consider
the following diagram, in which two users (Alice and Bob) are working with the same item from a
DynamoDB table.

Suppose that Alice uses the AWS CLI to update the Price attribute to 8.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"1"}}' \
--update-expression "SET Price = :newval" \
--expression-attribute-values file://expression-attribute-values.json

API Version 2012-08-10


382
Amazon DynamoDB Developer Guide
Conditional Writes

The arguments for --expression-attribute-values are stored in the file expression-


attribute-values.json:

{
":newval":{"N":"8"}
}

Now suppose that Bob issues a similar UpdateItem request later, but changes the Price to 12. For Bob,
the --expression-attribute-values parameter looks like the following.

{
":newval":{"N":"12"}
}

Bob's request succeeds, but Alice's earlier update is lost.

To request a conditional PutItem, DeleteItem, or UpdateItem, you specify a condition expression. A


condition expression is a string containing attribute names, conditional operators, and built-in functions.
The entire expression must evaluate to true. Otherwise, the operation fails.

Now consider the following diagram, showing how conditional writes would prevent Alice's update from
being overwritten.

API Version 2012-08-10


383
Amazon DynamoDB Developer Guide
Conditional Writes

Alice first tries to update Price to 8, but only if the current Price is 10.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"1"}}' \
--update-expression "SET Price = :newval" \
--condition-expression "Price = :currval" \
--expression-attribute-values file://expression-attribute-values.json

The arguments for --expression-attribute-values are stored in the expression-attribute-


values.json file.

{
":newval":{"N":"8"},
":currval":{"N":"10"}

API Version 2012-08-10


384
Amazon DynamoDB Developer Guide
Conditional Writes

Alice's update succeeds because the condition evaluates to true.

Next, Bob attempts to update the Price to 12, but only if the current Price is 10. For Bob, the --
expression-attribute-values parameter looks like the following.

{
":newval":{"N":"12"},
":currval":{"N":"10"}
}

Because Alice has previously changed the Price to 8, the condition expression evaluates to false, and
Bob's update fails.

For more information, see Condition Expressions (p. 393).

Conditional Write Idempotence


Conditional writes can be idempotent if the conditional check is on the same attribute that is being
updated. This means that DynamoDB performs a given write request only if certain attribute values in
the item match what you expect them to be at the time of the request.

For example, suppose that you issue an UpdateItem request to increase the Price of an item by 3,
but only if the Price is currently 20. After you send the request, but before you get the results back, a
network error occurs, and you don't know whether the request was successful. Because this conditional
write is idempotent, you can retry the same UpdateItem request, and DynamoDB updates the item only
if the Price is currently 20.

Capacity Units Consumed by Conditional Writes


If a ConditionExpression evaluates to false during a conditional write, DynamoDB still consumes
write capacity from the table:

• If the item does not currently exist in the table, DynamoDB consumes one write capacity unit.
• If the item does exist, the number of write capacity units consumed depends on the size of the item.
For example, a failed conditional write of a 1 KB item would consume one write capacity unit. If the
item were twice that size, the failed conditional write would consume two write capacity units.

Note
Write operations consume write capacity units only. They never consume read capacity units.

A failed conditional write returns a ConditionalCheckFailedException. When this occurs, you


don't receive any information in the response about the write capacity that was consumed. However, you
can view the ConsumedWriteCapacityUnits metric for the table in Amazon CloudWatch. For more
information, see DynamoDB Metrics (p. 856) in Logging and Monitoring in DynamoDB (p. 854).

To return the number of write capacity units consumed during a conditional write, you use the
ReturnConsumedCapacity parameter:

• TOTAL — Returns the total number of write capacity units consumed.


• INDEXES — Returns the total number of write capacity units consumed, with subtotals for the table
and any secondary indexes that were affected by the operation.
• NONE — No write capacity details are returned. (This is the default.)

API Version 2012-08-10


385
Amazon DynamoDB Developer Guide
Using Expressions

Note
Unlike a global secondary index, a local secondary index shares its provisioned throughput
capacity with its table. Read and write activity on a local secondary index consumes provisioned
throughput capacity from the table.

Using Expressions in DynamoDB


In Amazon DynamoDB, you use expressions to denote the attributes that you want to read from an item.
You also use expressions when writing an item to indicate any conditions that must be met (also known
as a conditional update), and to indicate how the attributes are to be updated. This section describes the
basic expression grammar and the available kinds of expressions.
Note
For backward compatibility, DynamoDB also supports conditional parameters that do not use
expressions. For more information, see Legacy Conditional Parameters (p. 1034).
New applications should use expressions rather than the legacy parameters.

Topics
• Specifying Item Attributes When Using Expressions (p. 386)
• Projection Expressions (p. 389)
• Expression Attribute Names in DynamoDB (p. 390)
• Expression Attribute Values (p. 392)
• Condition Expressions (p. 393)
• Update Expressions (p. 401)

Specifying Item Attributes When Using Expressions


This section describes how to refer to item attributes in an expression in Amazon DynamoDB. You can
work with any attribute, even if it is deeply nested within multiple lists and maps.

Topics
• Top-Level Attributes (p. 387)
• Nested Attributes (p. 388)
• Document Paths (p. 388)

A Sample Item: ProductCatalog

The following is a representation of an item in the ProductCatalog table. (This table is described in
Example Tables and Data (p. 972).)

{
"Id": 123,
"Title": "Bicycle 123",
"Description": "123 description",
"BicycleType": "Hybrid",
"Brand": "Brand-Company C",
"Price": 500,
"Color": ["Red", "Black"],
"ProductCategory": "Bicycle",
"InStock": true,
"QuantityOnHand": null,
"RelatedItems": [
341,
472,
649
],

API Version 2012-08-10


386
Amazon DynamoDB Developer Guide
Using Expressions

"Pictures": {
"FrontView": "http://example.com/products/123_front.jpg",
"RearView": "http://example.com/products/123_rear.jpg",
"SideView": "http://example.com/products/123_left_side.jpg"
},
"ProductReviews": {
"FiveStar": [
"Excellent! Can't recommend it highly enough! Buy it!",
"Do yourself a favor and buy this."
],
"OneStar": [
"Terrible product! Do not buy this."
]
},
"Comment": "This product sells out quickly during the summer",
"Safety.Warning": "Always wear a helmet"
}

Note the following:

• The partition key value (Id) is 123. There is no sort key.


• Most of the attributes have scalar data types, such as String, Number, Boolean, and Null.
• One attribute (Color) is a String Set.
• The following attributes are document data types:
• A list of RelatedItems. Each element is an Id for a related product.
• A map of Pictures. Each element is a short description of a picture, along with a URL for the
corresponding image file.
• A map of ProductReviews. Each element represents a rating and a list of reviews corresponding to
that rating. Initially, this map is populated with five-star and one-star reviews.

Top-Level Attributes
An attribute is said to be top level if it is not embedded within another attribute. For the
ProductCatalog item, the top-level attributes are as follows:

• Id
• Title
• Description
• BicycleType
• Brand
• Price
• Color
• ProductCategory
• InStock
• QuantityOnHand
• RelatedItems
• Pictures
• ProductReviews
• Comment
• Safety.Warning

All of these top-level attributes are scalars, except for Color (list), RelatedItems (list), Pictures
(map), and ProductReviews (map).

API Version 2012-08-10


387
Amazon DynamoDB Developer Guide
Using Expressions

Nested Attributes
An attribute is said to be nested if it is embedded within another attribute. To access a nested attribute,
you use dereference operators:

• [n] — for list elements


• . (dot) — for map elements

Accessing List Elements

The dereference operator for a list element is [n], where n is the element number. List elements are zero-
based, so [0] represents the first element in the list, [1] represents the second, and so on. Here are some
examples:

• MyList[0]
• AnotherList[12]
• ThisList[5][11]

The element ThisList[5] is itself a nested list. Therefore, ThisList[5][11] refers to the 12th
element in that list.

The number within the square brackets must be a non-negative integer. Therefore, the following
expressions are not valid:

• MyList[-1]
• MyList[0.4]

Accessing Map Elements

The dereference operator for a map element is . (a dot). Use a dot as a separator between elements in a
map:

• MyMap.nestedField
• MyMap.nestedField.deeplyNestedField

Document Paths
In an expression, you use a document path to tell DynamoDB where to find an attribute. For a top-level
attribute, the document path is simply the attribute name. For a nested attribute, you construct the
document path using dereference operators.

The following are some examples of document paths. (Refer to the item shown in Specifying Item
Attributes When Using Expressions (p. 386).)

• A top-level scalar attribute.

ProductDescription
• A top-level list attribute. (This returns the entire list, not just some of the elements.)

RelatedItems
• The third element from the RelatedItems list. (Remember that list elements are zero-based.)

RelatedItems[2]
• The front-view picture of the product.

API Version 2012-08-10


388
Amazon DynamoDB Developer Guide
Using Expressions

Pictures.FrontView
• All of the five-star reviews.

ProductReviews.FiveStar
• The first of the five-star reviews.

ProductReviews.FiveStar[0]

Note
The maximum depth for a document path is 32. Therefore, the number of dereferences
operators in a path cannot exceed this limit.

You can use any attribute name in a document path, provided that the first character is a-z or A-
Z and the second character (if present) is a-z, A-Z, or 0-9. If an attribute name does not meet this
requirement, you must define an expression attribute name as a placeholder. For more information, see
Expression Attribute Names in DynamoDB (p. 390).

Projection Expressions
To read data from a table, you use operations such as GetItem, Query, or Scan. Amazon DynamoDB
returns all the item attributes by default. To get only some, rather than all of the attributes, use a
projection expression.

A projection expression is a string that identifies the attributes that you want. To retrieve a single
attribute, specify its name. For multiple attributes, the names must be comma-separated.

The following are some examples of projection expressions, based on the ProductCatalog item from
Specifying Item Attributes When Using Expressions (p. 386):

• A single top-level attribute.

Title
• Three top-level attributes. DynamoDB retrieves the entire Color set.

Title, Price, Color


• Four top-level attributes. DynamoDB returns the entire contents of RelatedItems and
ProductReviews.

Title, Description, RelatedItems, ProductReviews

You can use any attribute name in a projection expression, provided that the first character is a-z or
A-Z and the second character (if present) is a-z, A-Z, or 0-9. If an attribute name does not meet this
requirement, you must define an expression attribute name as a placeholder. For more information, see
Expression Attribute Names in DynamoDB (p. 390).

The following AWS CLI example shows how to use a projection expression with a GetItem operation.
This projection expression retrieves a top-level scalar attribute (Description), the first element in a list
(RelatedItems[0]), and a list nested within a map (ProductReviews.FiveStar).

aws dynamodb get-item \


--table-name ProductCatalog \
--key file://key.json \
--projection-expression "Description, RelatedItems[0], ProductReviews.FiveStar"

The arguments for --key are stored in the key.json file.

API Version 2012-08-10


389
Amazon DynamoDB Developer Guide
Using Expressions

{
"Id": { "N": "123" }
}

For programming language-specific code examples, see Getting Started with DynamoDB and AWS
SDKs (p. 76).

Expression Attribute Names in DynamoDB


An expression attribute name is a placeholder that you use in an Amazon DynamoDB expression as an
alternative to an actual attribute name. An expression attribute name must begin with a pound sign (#),
and be followed by one or more alphanumeric characters.

This section describes several situations in which you must use expression attribute names.
Note
The examples in this section use the AWS Command Line Interface (AWS CLI). For programming
language-specific code examples, see Getting Started with DynamoDB and AWS SDKs (p. 76).

Topics
• Reserved Words (p. 390)
• Attribute Names Containing Dots (p. 391)
• Nested Attributes (p. 391)
• Repeating Attribute Names (p. 392)

Reserved Words
Sometimes you might need to write an expression containing an attribute name that conflicts
with a DynamoDB reserved word. (For a complete list of reserved words, see Reserved Words in
DynamoDB (p. 1025).)

For example, the following AWS CLI example would fail because COMMENT is a reserved word.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "Comment"

To work around this, you can replace Comment with an expression attribute name such as #c. The #
(pound sign) is required and indicates that this is a placeholder for an attribute name. The AWS CLI
example would now look like the following.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "#c" \
--expression-attribute-names '{"#c":"Comment"}'

Note
If an attribute name begins with a number or contains a space, a special character, or a reserved
word, you must use an expression attribute name to replace that attribute's name in the
expression.

API Version 2012-08-10


390
Amazon DynamoDB Developer Guide
Using Expressions

Attribute Names Containing Dots


In an expression, a dot (".") is interpreted as a separator character in a document path. However,
DynamoDB also allows you to use a dot character as part of an attribute name. This can be ambiguous
in some cases. To illustrate, suppose that you wanted to retrieve the Safety.Warning attribute from a
ProductCatalog item (see Specifying Item Attributes When Using Expressions (p. 386)).

Suppose that you wanted to access Safety.Warning using a projection expression.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "Safety.Warning"

DynamoDB would return an empty result, rather than the expected string ("Always wear a helmet").
This is because DynamoDB interprets a dot in an expression as a document path separator. In this case,
you must define an expression attribute name (such as #sw) as a substitute for Safety.Warning. You
could then use the following projection expression.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "#sw" \
--expression-attribute-names '{"#sw":"Safety.Warning"}'

DynamoDB would then return the correct result.

Nested Attributes
Suppose that you wanted to access the nested attribute ProductReviews.OneStar, using the
following projection expression.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "ProductReviews.OneStar"

The result would contain all of the one-star product reviews, which is expected.

But what if you decided to use an expression attribute name instead? For example, what would happen if
you were to define #pr1star as a substitute for ProductReviews.OneStar?

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "#pr1star" \
--expression-attribute-names '{"#pr1star":"ProductReviews.OneStar"}'

DynamoDB would return an empty result instead of the expected map of one-star reviews. This is
because DynamoDB interprets a dot in an expression attribute value as a character within an attribute's

API Version 2012-08-10


391
Amazon DynamoDB Developer Guide
Using Expressions

name. When DynamoDB evaluates the expression attribute name #pr1star, it determines that
ProductReviews.OneStar refers to a scalar attribute—which is not what was intended.

The correct approach would be to define an expression attribute name for each element in the document
path:

• #pr — ProductReviews
• #1star — OneStar

You could then use #pr.#1star for the projection expression.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "#pr.#1star" \
--expression-attribute-names '{"#pr":"ProductReviews", "#1star":"OneStar"}'

DynamoDB would then return the correct result.

Repeating Attribute Names


Expression attribute names are helpful when you need to refer to the same attribute name
repeatedly. For example, consider the following expression for retrieving some of the reviews from a
ProductCatalog item.

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "ProductReviews.FiveStar, ProductReviews.ThreeStar,
ProductReviews.OneStar"

To make this more concise, you can replace ProductReviews with an expression attribute name such as
#pr. The revised expression would now look like the following.

• #pr.FiveStar, #pr.ThreeStar, #pr.OneStar

aws dynamodb get-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"123"}}' \
--projection-expression "#pr.FiveStar, #pr.ThreeStar, #pr.OneStar" \
--expression-attribute-names '{"#pr":"ProductReviews"}'

If you define an expression attribute name, you must use it consistently throughout the entire
expression. Also, you cannot omit the # symbol.

Expression Attribute Values


If you need to compare an attribute with a value, define an expression attribute value as a placeholder.
Expression attribute values in Amazon DynamoDB are substitutes for the actual values that you want to

API Version 2012-08-10


392
Amazon DynamoDB Developer Guide
Using Expressions

compare—values that you might not know until runtime. An expression attribute value must begin with
a colon (:) and be followed by one or more alphanumeric characters.

For example, suppose that you wanted to return all of the ProductCatalog items that are available
in Black and cost 500 or less. You could use a Scan operation with a filter expression, as in this AWS
Command Line Interface (AWS CLI) example.

aws dynamodb scan \


--table-name ProductCatalog \
--filter-expression "contains(Color, :c) and Price <= :p" \
--expression-attribute-values file://values.json

The arguments for --expression-attribute-values are stored in the values.json file.

{
":c": { "S": "Black" },
":p": { "N": "500" }
}

Note
A Scan operation reads every item in a table. So you should avoid using Scan with large tables.
The filter expression is applied to the Scan results, and items that don't match the filter
expression are discarded.

If you define an expression attribute value, you must use it consistently throughout the entire expression.
Also, you can't omit the : symbol.

Expression attribute values are used with condition expressions, update expressions, and filter
expressions.
Note
For programming language-specific code examples, see Getting Started with DynamoDB and
AWS SDKs (p. 76).

Condition Expressions
To manipulate data in an Amazon DynamoDB table, you use the PutItem, UpdateItem, and
DeleteItem operations. (You can also use BatchWriteItem to perform multiple PutItem or
DeleteItem operations in a single call.)

For these data manipulation operations, you can specify a condition expression to determine which items
should be modified. If the condition expression evaluates to true, the operation succeeds; otherwise, the
operation fails.

The following are some AWS Command Line Interface (AWS CLI) examples of using condition
expressions. These examples are based on the ProductCatalog table, which was introduced in
Specifying Item Attributes When Using Expressions (p. 386). The partition key for this table is Id;
there is no sort key. The following PutItem operation creates a sample ProductCatalog item that the
examples refer to.

aws dynamodb put-item \


--table-name ProductCatalog \
--item file://item.json

The arguments for --item are stored in the item.json file. (For simplicity, only a few item attributes
are used.)

API Version 2012-08-10


393
Amazon DynamoDB Developer Guide
Using Expressions

{
"Id": {"N": "456" },
"ProductCategory": {"S": "Sporting Goods" },
"Price": {"N": "650" }
}

Topics
• Preventing Overwrites of an Existing Item (p. 394)
• Checking for Attributes in an Item (p. 394)
• Conditional Deletes (p. 395)
• Conditional Updates (p. 396)
• Comparison Operator and Function Reference (p. 396)

Preventing Overwrites of an Existing Item


The PutItem operation overwrites an item with the same key (if it exists). If you want to avoid this, use a
condition expression. This allows the write to proceed only if the item in question does not already have
the same key.

aws dynamodb put-item \


--table-name ProductCatalog \
--item file://item.json \
--condition-expression "attribute_not_exists(Id)"

If the condition expression evaluates to false, DynamoDB returns the following error message: The
conditional request failed.
Note
For more information about attribute_not_exists and other functions, see Comparison
Operator and Function Reference (p. 396).

Checking for Attributes in an Item


You can check for the existence (or nonexistence) of any attribute. If the condition expression evaluates
to true, the operation succeeds; otherwise, it fails.

The following example uses attribute_not_exists to delete a product only if it does not have a
Price attribute.

aws dynamodb delete-item \


--table-name ProductCatalog \
--key '{"Id": {"N": "456"}}' \
--condition-expression "attribute_not_exists(Price)"

DynamoDB also provides an attribute_exists function. The following example deletes a product
only if it has received poor reviews.

aws dynamodb delete-item \


--table-name ProductCatalog \
--key '{"Id": {"N": "456"}}' \

API Version 2012-08-10


394
Amazon DynamoDB Developer Guide
Using Expressions

--condition-expression "attribute_exists(ProductReviews.OneStar)"

Note
For more information about attribute_not_exists, attribute_exists, and other
functions, see Comparison Operator and Function Reference (p. 396).

Conditional Deletes
To perform a conditional delete, you use a DeleteItem operation with a condition expression. The
condition expression must evaluate to true in order for the operation to succeed; otherwise, the
operation fails.

Consider the item from Condition Expressions (p. 393).

{
"Id": {
"N": "456"
},
"Price": {
"N": "650"
},
"ProductCategory": {
"S": "Sporting Goods"
}
}

Suppose that you wanted to delete the item, but only under the following conditions:

• The ProductCategory is either "Sporting Goods" or "Gardening Supplies."


• The Price is between 500 and 600.

The following example tries to delete the item.

aws dynamodb delete-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"456"}}' \
--condition-expression "(ProductCategory IN (:cat1, :cat2)) and (Price between :lo
and :hi)" \
--expression-attribute-values file://values.json

The arguments for --expression-attribute-values are stored in the values.json file.

{
":cat1": {"S": "Sporting Goods"},
":cat2": {"S": "Gardening Supplies"},
":lo": {"N": "500"},
":hi": {"N": "600"}
}

Note
In the condition expression, the : (colon character) indicates an expression attribute value—a
placeholder for an actual value. For more information, see Expression Attribute Values (p. 392).
For more information about IN, AND, and other keywords, see Comparison Operator and
Function Reference (p. 396).

API Version 2012-08-10


395
Amazon DynamoDB Developer Guide
Using Expressions

In this example, the ProductCategory comparison evaluates to true, but the Price comparison
evaluates to false. This causes the condition expression to evaluate to false and the DeleteItem
operation to fail.

Conditional Updates
To perform a conditional update, you use an UpdateItem operation with a condition expression.
The condition expression must evaluate to true in order for the operation to succeed; otherwise, the
operation fails.
Note
UpdateItem also supports update expressions, where you specify the modifications you want to
make to an item. For more information, see Update Expressions (p. 401).

Suppose that you started with the item shown in Condition Expressions (p. 393).

{
"Id": { "N": "456"},
"Price": {"N": "650"},
"ProductCategory": {"S": "Sporting Goods"}
}

The following example performs an UpdateItem operation. It tries to reduce the Price of a product by
75—but the condition expression prevents the update if the current Price is below 500.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id": {"N": "456"}}' \
--update-expression "SET Price = Price - :discount" \
--condition-expression "Price > :limit" \
--expression-attribute-values file://values.json

The arguments for --item are stored in the values.json file.

{
":discount": { "N": "75"},
":limit": {"N": "500"}
}

If the starting Price is 650, the UpdateItem operation reduces the Price to 575. If you run the
UpdateItem operation again, the Price is reduced to 500. If you run it a third time, the condition
expression evaluates to false, and the update fails.
Note
In the condition expression, the : (colon character) indicates an expression attribute value—a
placeholder for an actual value. For more information, see Expression Attribute Values (p. 392).
For more information about ">" and other operators, see Comparison Operator and Function
Reference (p. 396).

Comparison Operator and Function Reference


This section covers the built-in functions and keywords for writing condition expressions in Amazon
DynamoDB.

Topics
• Syntax for Condition Expressions (p. 397)
• Making Comparisons (p. 397)

API Version 2012-08-10


396
Amazon DynamoDB Developer Guide
Using Expressions

• Functions (p. 398)


• Logical Evaluations (p. 400)
• Parentheses (p. 401)
• Precedence in Conditions (p. 401)

Syntax for Condition Expressions

In the following syntax summary, an operand can be the following:

• A top-level attribute name, such as Id, Title, Description, or ProductCategory


• A document path that references a nested attribute

condition-expression ::=
operand comparator operand
| operand BETWEEN operand AND operand
| operand IN ( operand (',' operand (, ...) ))
| function
| condition AND condition
| condition OR condition
| NOT condition
| ( condition )

comparator ::=
=
| <>
| <
| <=
| >
| >=

function ::=
attribute_exists (path)
| attribute_not_exists (path)
| attribute_type (path, type)
| begins_with (path, substr)
| contains (path, operand)
| size (path)

Making Comparisons

Use these comparators to compare an operand against a range of values or an enumerated list of values:

• a = b — true if a is equal to b
• a <> b — true if a is not equal to b
• a < b — true if a is less than b
• a <= b — true if a is less than or equal to b
• a > b — true if a is greater than b
• a >= b — true if a is greater than or equal to b

Use the BETWEEN and IN keywords to compare an operand against a range of values or an enumerated
list of values:

• a BETWEEN b AND c - true if a is greater than or equal to b, and less than or equal to c.
• a IN (b, c, d) — true if a is equal to any value in the list — for example, any of b, c or d. The list
can contain up to 100 values, separated by commas.

API Version 2012-08-10


397
Amazon DynamoDB Developer Guide
Using Expressions

Functions

Use the following functions to determine whether an attribute exists in an item, or to evaluate the value
of an attribute. These function names are case sensitive. For a nested attribute, you must provide its full
document path.

Function Description

attribute_exists (path) True if the item contains the attribute specified by


path.

Example: Check whether an item in the Product


table has a side view picture.

• attribute_exists (Pictures.SideView)

attribute_not_exists (path) True if the attribute specified by path does not


exist in the item.

Example: Check whether an item has a


Manufacturer attribute.

• attribute_not_exists (Manufacturer)

attribute_type (path, type) True if the attribute at the specified path is of a


particular data type. The type parameter must be
one of the following:

• S — String
• SS — String Set
• N — Number
• NS — Number Set
• B — Binary
• BS — Binary Set
• BOOL — Boolean
• NULL — Null
• L — List
• M — Map

You must use an expression attribute value for the


type parameter.

Example: Check whether the QuantityOnHand


attribute is of type List. In this example, :v_sub is
a placeholder for the string L.

• attribute_type
(ProductReviews.FiveStar, :v_sub)

You must use an expression attribute value for the


type parameter.

begins_with (path, substr) True if the attribute specified by path begins with
a particular substring.

API Version 2012-08-10


398
Amazon DynamoDB Developer Guide
Using Expressions

Function Description
Example: Check whether the first few characters
of the front view picture URL are http://.

• begins_with
(Pictures.FrontView, :v_sub)

The expression attribute value :v_sub is a


placeholder for http://.

contains (path, operand) True if the attribute specified by path is one of


the following:

• A String that contains a particular substring.


• A Set that contains a particular element within
the set.

In either case, operand must be a String.

The path and the operand must be distinct; that


is, contains (a, a) returns an error.

Example: Check whether the Brand attribute


contains the substring Company.

• contains (Brand, :v_sub)

The expression attribute value :v_sub is a


placeholder for Company.

Example: Check whether the product is available


in red.

• contains (Color, :v_sub)

The expression attribute value :v_sub is a


placeholder for Red.

API Version 2012-08-10


399
Amazon DynamoDB Developer Guide
Using Expressions

Function Description

size (path) Returns a number representing an attribute's size.


The following are valid data types for use with
size.

If the attribute is of type String, size returns


the length of the string.

Example: Check whether the string Brand is less


than or equal to 20 characters. The expression
attribute value :v_sub is a placeholder for 20.

• size (Brand) <= :v_sub

If the attribute is of type Binary, size returns


the number of bytes in the attribute value.

Example: Suppose that the ProductCatalog


item has a binary attribute named VideoClip,
which contains a short video of the product in
use. The following expression checks whether
VideoClip exceeds 64,000 bytes. The expression
attribute value :v_sub is a placeholder for
64000.

• size(VideoClip) > :v_sub

If the attribute is a Set data type, size returns


the number of elements in the set.

Example: Check whether the product is available


in more than one color. The expression attribute
value :v_sub is a placeholder for 1.

• size (Color) < :v_sub

If the attribute is of type List or Map, size


returns the number of child elements.

Example: Check whether the number of OneStar


reviews has exceeded a certain threshold.
The expression attribute value :v_sub is a
placeholder for 3.

• size(ProductReviews.OneStar)
> :v_sub

Logical Evaluations

Use the AND, OR, and NOT keywords to perform logical evaluations. In the list following, a and b
represent conditions to be evaluated.

• a AND b — true if a and b are both true.


• a OR b — true if either a or b (or both) are true.

API Version 2012-08-10


400
Amazon DynamoDB Developer Guide
Using Expressions

• NOT a — true if a is false; false if a is true.

Parentheses

Use parentheses to change the precedence of a logical evaluation. For example, suppose that conditions
a and b are true, and that condition c is false. The following expression evaluates to true:

• a OR b AND c

However, if you enclose a condition in parentheses, it is evaluated first. For example, the following
evaluates to false:

• (a OR b) AND c

Note
You can nest parentheses in an expression. The innermost ones are evaluated first.

Precedence in Conditions

DynamoDB evaluates conditions from left to right using the following precedence rules:

• = <> < <= > >=


• IN
• BETWEEN
• attribute_exists attribute_not_exists begins_with contains
• Parentheses
• NOT
• AND
• OR

Update Expressions
To update an existing item in an Amazon DynamoDB table, you use the UpdateItem operation. You
must provide the key of the item that you want to update. You must also provide an update expression,
indicating the attributes that you want to modify and the values that you want to assign to them.

An update expression specifies how UpdateItem will modify the attributes of an item—for example,
setting a scalar value or removing elements from a list or a map.

The following is a syntax summary for update expressions.

update-expression ::=
[ SET action [, action] ... ]
[ REMOVE action [, action] ...]
[ ADD action [, action] ... ]
[ DELETE action [, action] ...]

An update expression consists of one or more clauses. Each clause begins with a SET, REMOVE, ADD, or
DELETE keyword. You can include any of these clauses in an update expression, in any order. However,
each action keyword can appear only once.

Within each clause, there are one or more actions separated by commas. Each action represents a data
modification.

API Version 2012-08-10


401
Amazon DynamoDB Developer Guide
Using Expressions

The examples in this section are based on the ProductCatalog item shown in Projection
Expressions (p. 389).

Topics
• SET—Modifying or Adding Item Attributes (p. 402)
• REMOVE—Deleting Attributes from an Item (p. 406)
• ADD—Updating Numbers and Sets (p. 407)
• DELETE—Removing Elements from a Set (p. 409)

SET—Modifying or Adding Item Attributes


Use the SET action in an update expression to add one or more attributes to an item. If any of these
attributes already exists, they are overwritten by the new values.

You can also use SET to add or subtract from an attribute that is of type Number. To perform multiple
SET actions, separate them with commas.

In the following syntax summary:

• The path element is the document path to the item.


• An operand element can be either a document path to an item or a function.

set-action ::=
path = value

value ::=
operand
| operand '+' operand
| operand '-' operand

operand ::=
path | function

The following PutItem operation creates a sample item that the examples refer to.

aws dynamodb put-item \


--table-name ProductCatalog \
--item file://item.json

The arguments for --item are stored in the item.json file. (For simplicity, only a few item attributes
are used.)

{
"Id": {"N": "789"},
"ProductCategory": {"S": "Home Improvement"},
"Price": {"N": "52"},
"InStock": {"BOOL": true},
"Brand": {"S": "Acme"}
}

Topics
• Modifying Attributes (p. 403)

API Version 2012-08-10


402
Amazon DynamoDB Developer Guide
Using Expressions

• Adding Lists and Maps (p. 403)


• Adding Elements to a List (p. 404)
• Adding Nested Map Attributes (p. 404)
• Incrementing and Decrementing Numeric Attributes (p. 405)
• Appending Elements to a List (p. 405)
• Preventing Overwrites of an Existing Attribute (p. 406)

Modifying Attributes

Example
Update the ProductCategory and Price attributes.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET ProductCategory = :c, Price = :p" \
--expression-attribute-values file://values.json \
--return-values ALL_NEW

The arguments for --expression-attribute-values are stored in the values.json file.

{
":c": { "S": "Hardware" },
":p": { "N": "60" }
}

Note
In the UpdateItem operation, --return-values ALL_NEW causes DynamoDB to return the
item as it appears after the update.

Adding Lists and Maps

Example
Add a new list and a new map.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET RelatedItems = :ri, ProductReviews = :pr" \
--expression-attribute-values file://values.json \
--return-values ALL_NEW

The arguments for --expression-attribute-values are stored in the values.json file.

{
":ri": {
"L": [
{ "S": "Hammer" }
]
},
":pr": {
"M": {

API Version 2012-08-10


403
Amazon DynamoDB Developer Guide
Using Expressions

"FiveStar": {
"L": [
{ "S": "Best product ever!" }
]
}
}
}
}

Adding Elements to a List

Example
Add a new attribute to the RelatedItems list. (Remember that list elements are zero-based, so [0]
represents the first element in the list, [1] represents the second, and so on.)

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET RelatedItems[1] = :ri" \
--expression-attribute-values file://values.json \
--return-values ALL_NEW

The arguments for --expression-attribute-values are stored in the values.json file.

{
":ri": { "S": "Nails" }
}

Note
When you use SET to update a list element, the contents of that element are replaced with the
new data that you specify. If the element doesn't already exist, SET appends the new element at
the end of the list.
If you add multiple elements in a single SET operation, the elements are sorted in order by
element number.

Adding Nested Map Attributes

Example
Add some nested map attributes.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET #pr.#5star[1] = :r5, #pr.#3star = :r3" \
--expression-attribute-names file://names.json \
--expression-attribute-values file://values.json \
--return-values ALL_NEW

The arguments for --expression-attribute-names are stored in the names.json file.

{
"#pr": "ProductReviews",
"#5star": "FiveStar",
"#3star": "ThreeStar"

API Version 2012-08-10


404
Amazon DynamoDB Developer Guide
Using Expressions

The arguments for --expression-attribute-values are stored in the values.json file.

{
":r5": { "S": "Very happy with my purchase" },
":r3": {
"L": [
{ "S": "Just OK - not that great" }
]
}
}

Incrementing and Decrementing Numeric Attributes


You can add to or subtract from an existing numeric attribute. To do this, use the + (plus) and - (minus)
operators.

Example
Decrease the Price of an item.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET Price = Price - :p" \
--expression-attribute-values '{":p": {"N":"15"}}' \
--return-values ALL_NEW

To increase the Price, you would use the + operator in the update expression.

Appending Elements to a List


You can add elements to the end of a list. To do this, use SET with the list_append function. (The
function name is case sensitive.) The list_append function is specific to the SET action and can only be
used in an update expression. The syntax is as follows.

• list_append (list1, list2)

The function takes two lists as input and appends list2 to list1.

Example
In Adding Elements to a List (p. 404), you create the RelatedItems list and populate it with two
elements: Hammer and Nails. Now you append two more elements to the end of RelatedItems.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET #ri = list_append(#ri, :vals)" \
--expression-attribute-names '{"#ri": "RelatedItems"}' \
--expression-attribute-values file://values.json \
--return-values ALL_NEW

The arguments for --expression-attribute-values are stored in the values.json file.

API Version 2012-08-10


405
Amazon DynamoDB Developer Guide
Using Expressions

{
":vals": {
"L": [
{ "S": "Screwdriver" },
{"S": "Hacksaw" }
]
}
}

Finally, you append one more element to the beginning of RelatedItems. To do this, swap the order of
the list_append elements. (Remember that list_append takes two lists as input and appends the
second list to the first.)

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET #ri = list_append(:vals, #ri)" \
--expression-attribute-names '{"#ri": "RelatedItems"}' \
--expression-attribute-values '{":vals": {"L": [ { "S": "Chisel" }]}}' \
--return-values ALL_NEW

The resulting RelatedItems attribute now contains five elements, in the following order: Chisel,
Hammer, Nails, Screwdriver, Hacksaw.

Preventing Overwrites of an Existing Attribute

If you want to avoid overwriting an existing attribute, you can use SET with the if_not_exists
function. (The function name is case sensitive.) The if_not_exists function is specific to the SET
action and can only be used in an update expression. The syntax is as follows.

• if_not_exists (path, value)

If the item does not contain an attribute at the specified path, if_not_exists evaluates to value;
otherwise, it evaluates to path.

Example

Set the Price of an item, but only if the item does not already have a Price attribute. (If Price already
exists, nothing happens.)

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "SET Price = if_not_exists(Price, :p)" \
--expression-attribute-values '{":p": {"N": "100"}}' \
--return-values ALL_NEW

REMOVE—Deleting Attributes from an Item


Use the REMOVE action in an update expression to remove one or more attributes from an item in
Amazon DynamoDB. To perform multiple REMOVE actions, separate them with commas.

The following is a syntax summary for REMOVE in an update expression. The only operand is the
document path for the attribute that you want to remove.

API Version 2012-08-10


406
Amazon DynamoDB Developer Guide
Using Expressions

remove-action ::=
path

Example

Remove some attributes from an item. (If the attributes don't exist, nothing happens.)

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "REMOVE Brand, InStock, QuantityOnHand" \
--return-values ALL_NEW

Removing Elements from a List

You can use REMOVE to delete individual elements from a list.

Example

In Appending Elements to a List (p. 405), you modify a list attribute (RelatedItems) so that it
contained five elements:

• [0]—Chisel
• [1]—Hammer
• [2]—Nails
• [3]—Screwdriver
• [4]—Hacksaw

The following AWS Command Line Interface (AWS CLI) example deletes Hammer and Nails from the list.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "REMOVE RelatedItems[1], RelatedItems[2]" \
--return-values ALL_NEW

After Hammer and Nails are removed, the remaining elements are shifted. The list now contains the
following:

• [0]—Chisel
• [1]—Screwdriver
• [2]—Hacksaw

ADD—Updating Numbers and Sets


Note
In general, we recommend using SET rather than ADD.

Use the ADD action in an update expression to add a new attribute and its values to an item.

API Version 2012-08-10


407
Amazon DynamoDB Developer Guide
Using Expressions

If the attribute already exists, the behavior of ADD depends on the attribute's data type:

• If the attribute is a number, and the value you are adding is also a number, the value is mathematically
added to the existing attribute. (If the value is a negative number, it is subtracted from the existing
attribute.)
• If the attribute is a set, and the value you are adding is also a set, the value is appended to the existing
set.

Note
The ADD action supports only number and set data types.

To perform multiple ADD actions, separate them with commas.

In the following syntax summary:

• The path element is the document path to an attribute. The attribute must be either a Number or a
set data type.
• The value element is a number that you want to add to the attribute (for Number data types), or a set
to append to the attribute (for set types).

add-action ::=
path value

Adding a Number

Assume that the QuantityOnHand attribute does not exist. The following AWS CLI example sets
QuantityOnHand to 5.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "ADD QuantityOnHand :q" \
--expression-attribute-values '{":q": {"N": "5"}}' \
--return-values ALL_NEW

Now that QuantityOnHand exists, you can rerun the example to increment QuantityOnHand by 5 each
time.

Adding Elements to a Set

Assume that the Color attribute does not exist. The following AWS CLI example sets Color to a string
set with two elements.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "ADD Color :c" \
--expression-attribute-values '{":c": {"SS":["Orange", "Purple"]}}' \
--return-values ALL_NEW

Now that Color exists, you can add more elements to it.

API Version 2012-08-10


408
Amazon DynamoDB Developer Guide
Expiring Items with Time to Live

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "ADD Color :c" \
--expression-attribute-values '{":c": {"SS":["Yellow", "Green", "Blue"]}}' \
--return-values ALL_NEW

DELETE—Removing Elements from a Set


Important
The DELETE action supports only Set data types.

Use the DELETE action in an update expression to remove one or more elements from a set. To perform
multiple DELETE actions, separate them with commas.

In the following syntax summary:

• The path element is the document path to an attribute. The attribute must be a set data type.
• The subset is one or more elements that you want to delete from path. You must specify subset as
a set type.

delete-action ::=
path value

Example

In Adding Elements to a Set (p. 408), you create the Colors string set. This example removes some of
the elements from that set.

aws dynamodb update-item \


--table-name ProductCatalog \
--key '{"Id":{"N":"789"}}' \
--update-expression "DELETE Color :p" \
--expression-attribute-values '{":p": {"SS": ["Yellow", "Purple"]}}' \
--return-values ALL_NEW

Expiring Items Using Time to Live (TTL)


Time to Live (TTL) for Amazon DynamoDB lets you define when items in a table expire so that they can
be automatically deleted from the database. With TTL enabled on a table, you can set a timestamp for
deletion on a per-item basis, allowing you to limit storage usage to only those records that are relevant.

TTL is useful if you have continuously accumulating data that loses relevance after a specific time period
(for example, session data, event logs, usage patterns, and other temporary data). If you have sensitive
data that must be retained only for a certain amount of time according to contractual or regulatory
obligations, TTL helps you ensure that it is removed promptly and as scheduled.

To get started with TTL:

1. Understand Time to Live: How It Works (p. 410).

API Version 2012-08-10


409
Amazon DynamoDB Developer Guide
Expiring Items with Time to Live

2. Read the Before You Begin Using Time to Live (p. 411) section.
3. Enable TTL on a specific table, and choose the name of an attribute to hold the expiration timestamp.
Then, you can add or update items in the table with timestamps in the attribute that you chose. For
more information, see Enabling Time to Live (TTL) (p. 411).

Time to Live: How It Works


When Time to Live (TTL) is enabled on a table in Amazon DynamoDB, a background job checks the TTL
attribute of items to determine whether they are expired.

DynamoDB compares the current time, in epoch time format, to the value stored in the user-defined
Number attribute of an item. If the attribute’s value is in the epoch time format, is less than the current
time, and is not older than 5 years, the item is deleted. Processing takes place automatically, in the
background, and doesn't affect read or write traffic to the table. In addition, deletes performed via TTL
are not counted towards capacity units or request units. TTL deletes are available at no additional cost.
Note
The epoch time format is the number of seconds elapsed since 12:00:00 AM January 1, 1970
UTC. For example, if you needed to represent the date 15 January 2020 19:26:52 GMT, you
would put 1579116412 as the value of a number attribute on an item.
Important
DynamoDB typically deletes expired items within 48 hours of expiration. The exact duration
within which an item truly gets deleted after expiration is specific to the nature of the workload
and the size of the table. Items that have expired and have not been deleted still appear in
reads, queries, and scans. These items can still be updated, and successful updates to change or
remove the expiration attribute are honored.

As items are deleted, they are removed from any local secondary index and global secondary index in the
same eventually consistent way as a standard delete operation.

For example, consider a table named SessionData that tracks the session history of users. Each item
in SessionData is identified by a partition key (UserName) and a sort key (SessionId). Additional
attributes like UserName, SessionId, CreationTime, and ExpirationTime track the session
information. The ExpirationTime attribute is set as the TTL attribute (not all of the attributes are
shown).

SessionData

UserName SessionId CreationTime ExpirationTime SessionInfo …


(TTL)

user1 746865726527731461931200 1461938400 {JSON ...


Document}

user2 6e6f7468696e671461920400 1461927600 {JSON ...


Document}

user3 746f20736565201461922200 1461929400 {JSON ...


Document}

user4 686572652121211461925380 1461932580 {JSON …


Document}

user5 6e6572642e2e2e1461920400 1461927600 {JSON ...


Document}

... ... ... ... ... …

API Version 2012-08-10


410
Amazon DynamoDB Developer Guide
Expiring Items with Time to Live

In this example, each item has an ExpirationTime attribute value set when it is created. Consider the
following record.

SessionData

UserName SessionId CreationTime ExpirationTime SessionInfo …


(TTL)

user1 746865726527731461931200 1461938400 {JSON ...


Document}

In this example, the item CreationTime is set to Friday, April 29 12:00 PM UTC 2016, and the
ExpirationTime is set 2 hours later at Friday, April 29 2:00 PM UTC 2016. The item expires when the
current time, in epoch format, is greater than the time in the ExpirationTime attribute. In this case,
the item with the key { Username: user1, SessionId: 74686572652773 } expires after 2:00 PM
(1461938400).
Note
Due to the potential delay between expiration and deletion time, you might get expired items
when you query for items. If you don’t want to view expired items when you issue a read
request, you must filter them out. To do this, use a filter expression that returns only items
where the Time to Live expiration value is greater than the current time in epoch format.
For more information, see Filter Expressions for Query (p. 461) and Filter Expressions for
Scan (p. 476).

Before You Begin Using Time to Live


Before you enable Time to Live (TTL) on an Amazon DynamoDB table, consider the following:

• Ensure that any existing timestamp values in the specified Time to Live attribute are correct and in the
right format. TTL attributes must use the Number data type, and values must use the Unix epoch time
format.
• Items with no TTL attribute, or with an expiration time more than 5 years in the past, are not deleted.
• If data recovery is a concern, we recommend that you back up your table.
• For a 24-hour recovery window, you can use Amazon DynamoDB Streams. For more information, see
DynamoDB Streams and Time to Live (p. 579).
• For a full backup, you can use on-demand backups or point-in-time recovery. For more information,
see On-Demand Backup and Restore for DynamoDB (p. 604) and Point-in-Time Recovery for
DynamoDB (p. 620).
• You can set Time to Live when creating a DynamoDB table using AWS CloudFormation. For more
information, see the AWS CloudFormation User Guide.
• You can use AWS Identity and Access Management (IAM) policies to prevent unauthorized updates
to the TTL attribute or configuration of the Time to Live feature. If you only allow access to
specified actions in your existing IAM policies, ensure that your policies are updated to allow
dynamodb:UpdateTimeToLive for roles that need to enable or disable Time to Live on tables. For
more information, see Using Identity-Based Policies (IAM Policies) for Amazon DynamoDB (p. 827).
• Consider whether you need to do any post-processing of deleted items. The streams records of TTL
deletes are marked, and you can monitor them using an AWS Lambda function. For more information
about the additions to the streams record, see DynamoDB Streams and Time to Live (p. 579).

Enabling Time to Live (TTL)


You can use the Amazon DynamoDB console or the AWS Command Line Interface (AWS CLI) to enable
Time to Live. To use the API instead, see Amazon DynamoDB API Reference.

API Version 2012-08-10


411
Amazon DynamoDB Developer Guide
Expiring Items with Time to Live

Topics
• Enable Time to Live (Console) (p. 412)
• Enable Time to Live (AWS CLI) (p. 414)

Enable Time to Live (Console)


Follow these steps to enable Time to Live 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. Choose Tables, and then choose the table that you want to modify.
3. In Table details, next to TTL attribute, choose Manage TTL.

4. In the Manage TTL dialog box, choose Enable TTL, and then enter the TTL attribute name.

API Version 2012-08-10


412
Amazon DynamoDB Developer Guide
Expiring Items with Time to Live

There are three settings in Manage TTL:

API Version 2012-08-10


413
Amazon DynamoDB Developer Guide
Expiring Items with Time to Live

• Enable TTL – Choose this to either enable or disable TTL on the table. It can take up to one hour
for the change to fully process.
• TTL Attribute – The name of the DynamoDB attribute to store the TTL timestamp for items.
• 24-hour backup streams – Choose this setting to enable Amazon DynamoDB Streams on
the table. For more information about how you can use DynamoDB Streams for backup, see
DynamoDB Streams and Time to Live (p. 579).
5. (Optional) To preview some of the items that will be deleted when TTL is enabled, choose Run
preview.
Warning
This provides you with a sample list of items. It does not provide you with a complete list of
items that will be deleted by TTL.
6. Choose Continue to save the settings and enable TTL.

Now that TTL is enabled, the TTL attribute is marked TTL when you view items on the DynamoDB
console.

You can view the date and time that an item expires by hovering your pointer over the attribute.

Enable Time to Live (AWS CLI)


1. Enable TTL on the TTLExample table.

aws dynamodb update-time-to-live --table-name TTLExample --time-to-live-specification


"Enabled=true, AttributeName=ttl"

2. Describe TTL on the TTLExample table.

aws dynamodb describe-time-to-live --table-name TTLExample


{
"TimeToLiveDescription": {
"AttributeName": "ttl",
"TimeToLiveStatus": "ENABLED"
}
}

3. Add an item to the TTLExample table with the Time to Live attribute set using the BASH shell and
the AWS CLI.

EXP=`date -d '+5 days' +%s`

API Version 2012-08-10


414
Amazon DynamoDB Developer Guide
Working with Items: Java

aws dynamodb put-item --table-name "TTLExample" --item '{"id": {"N": "1"}, "ttl": {"N":
"'$EXP'"}}'

This example starts with the current date and adds 5 days to it to create an expiration time. Then, it
converts the expiration time to epoch time format to finally add an item to the "TTLExample" table.
Note
One way to set expiration values for Time to Live is to calculate the number of seconds to add
to the expiration time. For example, 5 days is 432,000 seconds. However, it is often preferable to
start with a date and work from there.

It is fairly simple to get the current time in epoch time format, as in the following examples.

• Linux Terminal: date +%s


• Python: import time; long(time.time())
• Java: System.currentTimeMillis() / 1000L
• JavaScript: Math.floor(Date.now() / 1000)

Working with Items: Java


You can use the AWS SDK for Java Document API to perform typical create, read, update, and delete
(CRUD) operations on Amazon DynamoDB items in a table.
Note
The SDK for Java also provides an object persistence model, allowing you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code that you have to
write. For more information, see Java: DynamoDBMapper (p. 229).

This section contains Java examples to perform several Java Document API item actions and several
complete working examples.

Topics
• Putting an Item (p. 415)
• Getting an Item (p. 418)
• Batch Write: Putting and Deleting Multiple Items (p. 420)
• Batch Get: Getting Multiple Items (p. 421)
• Updating an Item (p. 422)
• Deleting an Item (p. 424)
• Example: CRUD Operations Using the AWS SDK for Java Document API (p. 424)
• Example: Batch Operations Using AWS SDK for Java Document API (p. 428)
• Example: Handling Binary Type Attributes Using the AWS SDK for Java Document API (p. 432)

Putting an Item
The putItem method stores an item in a table. If the item exists, it replaces the entire item. Instead of
replacing the entire item, if you want to update only specific attributes, you can use the updateItem
method. For more information, see Updating an Item (p. 422).

Follow these steps:

1. Create an instance of the DynamoDB class.

API Version 2012-08-10


415
Amazon DynamoDB Developer Guide
Working with Items: Java

2. Create an instance of the Table class to represent the table you want to work with.
3. Create an instance of the Item class to represent the new item. You must specify the new item's
primary key and its attributes.
4. Call the putItem method of the Table object, using the Item that you created in the preceding
step.

The following Java code example demonstrates the preceding tasks. The code writes a new item to the
ProductCatalog table.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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

// Build a list of related items


List<Number> relatedItems = new ArrayList<Number>();
relatedItems.add(341);
relatedItems.add(472);
relatedItems.add(649);

//Build a map of product pictures


Map<String, String> pictures = new HashMap<String, String>();
pictures.put("FrontView", "http://example.com/products/123_front.jpg");
pictures.put("RearView", "http://example.com/products/123_rear.jpg");
pictures.put("SideView", "http://example.com/products/123_left_side.jpg");

//Build a map of product reviews


Map<String, List<String>> reviews = new HashMap<String, List<String>>();

List<String> fiveStarReviews = new ArrayList<String>();


fiveStarReviews.add("Excellent! Can't recommend it highly enough! Buy it!");
fiveStarReviews.add("Do yourself a favor and buy this");
reviews.put("FiveStar", fiveStarReviews);

List<String> oneStarReviews = new ArrayList<String>();


oneStarReviews.add("Terrible product! Do not buy this.");
reviews.put("OneStar", oneStarReviews);

// Build the item


Item item = new Item()
.withPrimaryKey("Id", 123)
.withString("Title", "Bicycle 123")
.withString("Description", "123 description")
.withString("BicycleType", "Hybrid")
.withString("Brand", "Brand-Company C")
.withNumber("Price", 500)
.withStringSet("Color", new HashSet<String>(Arrays.asList("Red", "Black")))
.withString("ProductCategory", "Bicycle")
.withBoolean("InStock", true)
.withNull("QuantityOnHand")
.withList("RelatedItems", relatedItems)
.withMap("Pictures", pictures)
.withMap("Reviews", reviews);

// Write the item to the table


PutItemOutcome outcome = table.putItem(item);

In the preceding example, the item has attributes that are scalars (String, Number, Boolean, Null),
sets (String Set), and document types (List, Map).

API Version 2012-08-10


416
Amazon DynamoDB Developer Guide
Working with Items: Java

Specifying Optional Parameters


Along with the required parameters, you can also specify optional parameters to the putItem
method. For example, the following Java code example uses an optional parameter to specify a
condition for uploading the item. If the condition you specify is not met, the AWS SDK for Java throws a
ConditionalCheckFailedException. The code example specifies the following optional parameters
in the putItem method:

• A ConditionExpression that defines the conditions for the request. The code defines the condition
that the existing item with the same primary key is replaced only if it has an ISBN attribute that equals
a specific value.
• A map for ExpressionAttributeValues that is used in the condition. In this case, there is only one
substitution required: The placeholder :val in the condition expression is replaced at runtime with the
actual ISBN value to be checked.

The following example adds a new book item using these optional parameters.

Example

Item item = new Item()


.withPrimaryKey("Id", 104)
.withString("Title", "Book 104 Title")
.withString("ISBN", "444-4444444444")
.withNumber("Price", 20)
.withStringSet("Authors",
new HashSet<String>(Arrays.asList("Author1", "Author2")));

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


expressionAttributeValues.put(":val", "444-4444444444");

PutItemOutcome outcome = table.putItem(


item,
"ISBN = :val", // ConditionExpression parameter
null, // ExpressionAttributeNames parameter - we're not using it for this
example
expressionAttributeValues);

PutItem and JSON Documents


You can store a JSON document as an attribute in a DynamoDB table. To do this, use the withJSON
method of Item. This method parses the JSON document and maps each element to a native DynamoDB
data type.

Suppose that you wanted to store the following JSON document, containing vendors that can fulfill
orders for a particular product.

Example

{
"V01": {
"Name": "Acme Books",
"Offices": [ "Seattle" ]
},
"V02": {
"Name": "New Publishers, Inc.",
"Offices": ["London", "New York"
]
},
"V03": {

API Version 2012-08-10


417
Amazon DynamoDB Developer Guide
Working with Items: Java

"Name": "Better Buy Books",


"Offices": [ "Tokyo", "Los Angeles", "Sydney"
]
}
}

You can use the withJSON method to store this in the ProductCatalog table, in a Map attribute
named VendorInfo. The following Java code example demonstrates how to do this.

// Convert the document into a String. Must escape all double-quotes.


String vendorDocument = "{"
+ " \"V01\": {"
+ " \"Name\": \"Acme Books\","
+ " \"Offices\": [ \"Seattle\" ]"
+ " },"
+ " \"V02\": {"
+ " \"Name\": \"New Publishers, Inc.\","
+ " \"Offices\": [ \"London\", \"New York\"" + "]" + "},"
+ " \"V03\": {"
+ " \"Name\": \"Better Buy Books\","
+ "\"Offices\": [ \"Tokyo\", \"Los Angeles\", \"Sydney\""
+ " ]"
+ " }"
+ " }";

Item item = new Item()


.withPrimaryKey("Id", 210)
.withString("Title", "Book 210 Title")
.withString("ISBN", "210-2102102102")
.withNumber("Price", 30)
.withJSON("VendorInfo", vendorDocument);

PutItemOutcome outcome = table.putItem(item);

Getting an Item
To retrieve a single item, use the getItem method of a Table object. Follow these steps:

1. Create an instance of the DynamoDB class.


2. Create an instance of the Table class to represent the table you want to work with.
3. Call the getItem method of the Table instance. You must specify the primary key of the item that
you want to retrieve.

The following Java code example demonstrates the preceding steps. The code gets the item that has the
specified partition key.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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

Item item = table.getItem("Id", 101);

Specifying Optional Parameters


Along with the required parameters, you can also specify optional parameters for the getItem method.
For example, the following Java code example uses an optional method to retrieve only a specific list
of attributes and to specify strongly consistent reads. (To learn more about read consistency, see Read
Consistency (p. 16).)

API Version 2012-08-10


418
Amazon DynamoDB Developer Guide
Working with Items: Java

You can use a ProjectionExpression to retrieve only specific attributes or elements, rather than
an entire item. A ProjectionExpression can specify top-level or nested attributes using document
paths. For more information, see Projection Expressions (p. 389).

The parameters of the getItem method don't let you specify read consistency. However, you can create
a GetItemSpec, which provides full access to all of the inputs to the low-level GetItem operation. The
following code example creates a GetItemSpec and uses that spec as input to the getItem method.

Example

GetItemSpec spec = new GetItemSpec()


.withPrimaryKey("Id", 206)
.withProjectionExpression("Id, Title, RelatedItems[0], Reviews.FiveStar")
.withConsistentRead(true);

Item item = table.getItem(spec);

System.out.println(item.toJSONPretty());

To print an Item in a human-readable format, use the toJSONPretty method. The output from the
previous example looks like the following.

{
"RelatedItems" : [ 341 ],
"Reviews" : {
"FiveStar" : [ "Excellent! Can't recommend it highly enough! Buy it!", "Do yourself a
favor and buy this" ]
},
"Id" : 123,
"Title" : "20-Bicycle 123"
}

GetItem and JSON Documents


In the PutItem and JSON Documents (p. 417) section, you store a JSON document in a Map attribute
named VendorInfo. You can use the getItem method to retrieve the entire document in JSON format.
Or you can use document path notation to retrieve only some of the elements in the document. The
following Java code example demonstrates these techniques.

GetItemSpec spec = new GetItemSpec()


.withPrimaryKey("Id", 210);

System.out.println("All vendor info:");


spec.withProjectionExpression("VendorInfo");
System.out.println(table.getItem(spec).toJSON());

System.out.println("A single vendor:");


spec.withProjectionExpression("VendorInfo.V03");
System.out.println(table.getItem(spec).toJSON());

System.out.println("First office location for this vendor:");


spec.withProjectionExpression("VendorInfo.V03.Offices[0]");
System.out.println(table.getItem(spec).toJSON());

The output from the previous example looks like the following.

All vendor info:

API Version 2012-08-10


419
Amazon DynamoDB Developer Guide
Working with Items: Java

{"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los


Angeles","Sydney"]},"V02":{"Name":"New Publishers, Inc.","Offices":["London","New
York"]},"V01":{"Name":"Acme Books","Offices":["Seattle"]}}}
A single vendor:
{"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los
Angeles","Sydney"]}}}
First office location for a single vendor:
{"VendorInfo":{"V03":{"Offices":["Tokyo"]}}}

Note
You can use the toJSON method to convert any item (or its attributes) to a JSON-formatted
string. The following code retrieves several top-level and nested attributes and prints the results
as JSON.

GetItemSpec spec = new GetItemSpec()


.withPrimaryKey("Id", 210)
.withProjectionExpression("VendorInfo.V01, Title, Price");

Item item = table.getItem(spec);


System.out.println(item.toJSON());

The output looks like the following.

{"VendorInfo":{"V01":{"Name":"Acme Books","Offices":
["Seattle"]}},"Price":30,"Title":"Book 210 Title"}

Batch Write: Putting and Deleting Multiple Items


Batch write refers to putting and deleting multiple items in a batch. The batchWriteItem method
enables you to put and delete multiple items from one or more tables in a single call. The following are
the steps to put or delete multiple items using the AWS SDK for Java Document API.

1. Create an instance of the DynamoDB class.


2. Create an instance of the TableWriteItems class that describes all the put and delete operations
for a table. If you want to write to multiple tables in a single batch write operation, you must create
one TableWriteItems instance per table.
3. Call the batchWriteItem method by providing the TableWriteItems objects that you created in
the preceding step.
4. Process the response. You should check if there were any unprocessed request items returned in the
response. This could happen if you reach the provisioned throughput limit or some other transient
error. Also, DynamoDB limits the request size and the number of operations you can specify in a
request. If you exceed these limits, DynamoDB rejects the request. For more information, see Service,
Account, and Table Limits in Amazon DynamoDB (p. 959).

The following Java code example demonstrates the preceding steps. The example performs a
batchWriteItem operation on two tables: Forum and Thread. The corresponding TableWriteItems
objects define the following actions:

• Put an item in the Forum table.


• Put and delete an item in the Thread table.

The code then calls batchWriteItem to perform the operation.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

API Version 2012-08-10


420
Amazon DynamoDB Developer Guide
Working with Items: Java

TableWriteItems forumTableWriteItems = new TableWriteItems("Forum")


.withItemsToPut(
new Item()
.withPrimaryKey("Name", "Amazon RDS")
.withNumber("Threads", 0));

TableWriteItems threadTableWriteItems = new TableWriteItems("Thread")


.withItemsToPut(
new Item()
.withPrimaryKey("ForumName","Amazon RDS","Subject","Amazon RDS Thread 1")
.withHashAndRangeKeysToDelete("ForumName","Some partition key value", "Amazon S3",
"Some sort key value");

BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems,


threadTableWriteItems);

// Code for checking unprocessed items is omitted in this example

For a working example, see Example: Batch Write Operation Using the AWS SDK for Java Document
API (p. 428).

Batch Get: Getting Multiple Items


The batchGetItem method enables you to retrieve multiple items from one or more tables. To retrieve
a single item, you can use the getItem method.

Follow these steps:

1. Create an instance of the DynamoDB class.


2. Create an instance of the TableKeysAndAttributes class that describes a list of primary key
values to retrieve from a table. If you want to read from multiple tables in a single batch get
operation, you must create one TableKeysAndAttributes instance per table.
3. Call the batchGetItem method by providing the TableKeysAndAttributes objects that you
created in the preceding step.

The following Java code example demonstrates the preceding steps. The example retrieves two items
from the Forum table and three items from the Thread table.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

TableKeysAndAttributes forumTableKeysAndAttributes = new


TableKeysAndAttributes(forumTableName);
forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name",
"Amazon S3",
"Amazon DynamoDB");

TableKeysAndAttributes threadTableKeysAndAttributes = new


TableKeysAndAttributes(threadTableName);
threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject",
"Amazon DynamoDB","DynamoDB Thread 1",
"Amazon DynamoDB","DynamoDB Thread 2",
"Amazon S3","S3 Thread 1");

BatchGetItemOutcome outcome = dynamoDB.batchGetItem(


forumTableKeysAndAttributes, threadTableKeysAndAttributes);

for (String tableName : outcome.getTableItems().keySet()) {


System.out.println("Items in table " + tableName);
List<Item> items = outcome.getTableItems().get(tableName);

API Version 2012-08-10


421
Amazon DynamoDB Developer Guide
Working with Items: Java

for (Item item : items) {


System.out.println(item);
}
}

Specifying Optional Parameters


Along with the required parameters, you can also specify optional parameters when using
batchGetItem. For example, you can provide a ProjectionExpression with each
TableKeysAndAttributes you define. This allows you to specify the attributes that you want to
retrieve from the table.

The following code example retrieves two items from the Forum table. The
withProjectionExpression parameter specifies that only the Threads attribute is to be retrieved.

Example

TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes("Forum")


.withProjectionExpression("Threads");

forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name",
"Amazon S3",
"Amazon DynamoDB");

BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes);

Updating an Item
The updateItem method of a Table object can update existing attribute values, add new attributes, or
delete attributes from an existing item.

The updateItem method behaves as follows:

• If an item does not exist (no item in the table with the specified primary key), updateItem adds a new
item to the table.
• If an item exists, updateItem performs the update as specified by the UpdateExpression
parameter.

Note
It is also possible to "update" an item using putItem. For example, if you call putItem to
add an item to the table, but there is already an item with the specified primary key, putItem
replaces the entire item. If there are attributes in the existing item that are not specified in the
input, putItem removes those attributes from the item.
In general, we recommend that you use updateItem whenever you want to modify any item
attributes. The updateItem method only modifies the item attributes that you specify in the
input, and the other attributes in the item remain unchanged.

Follow these steps:

1. Create an instance of the Table class to represent the table that you want to work with.
2. Call the updateTable method of the Table instance. You must specify the primary key of the item
that you want to retrieve, along with an UpdateExpression that describes the attributes to modify
and how to modify them.

The following Java code example demonstrates the preceding tasks. The code updates a book item in
the ProductCatalog table. It adds a new author to the set of Authors and deletes the existing ISBN
attribute. It also reduces the price by one.

API Version 2012-08-10


422
Amazon DynamoDB Developer Guide
Working with Items: Java

An ExpressionAttributeValues map is used in the UpdateExpression. The placeholders :val1


and :val2 are replaced at runtime with the actual values for Authors and Price.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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

Map<String, String> expressionAttributeNames = new HashMap<String, String>();


expressionAttributeNames.put("#A", "Authors");
expressionAttributeNames.put("#P", "Price");
expressionAttributeNames.put("#I", "ISBN");

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


expressionAttributeValues.put(":val1",
new HashSet<String>(Arrays.asList("Author YY","Author ZZ")));
expressionAttributeValues.put(":val2", 1); //Price

UpdateItemOutcome outcome = table.updateItem(


"Id", // key attribute name
101, // key attribute value
"add #A :val1 set #P = #P - :val2 remove #I", // UpdateExpression
expressionAttributeNames,
expressionAttributeValues);

Specifying Optional Parameters


Along with the required parameters, you can also specify optional parameters for the updateItem
method, including a condition that must be met in order for the update is to occur. If the condition
you specify is not met, the AWS SDK for Java throws a ConditionalCheckFailedException. For
example, the following Java code example conditionally updates a book item price to 25. It specifies a
ConditionExpression stating that the price should be updated only if the existing price is 20.

Example

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

Map<String, String> expressionAttributeNames = new HashMap<String, String>();


expressionAttributeNames.put("#P", "Price");

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


expressionAttributeValues.put(":val1", 25); // update Price to 25...
expressionAttributeValues.put(":val2", 20); //...but only if existing Price is 20

UpdateItemOutcome outcome = table.updateItem(


new PrimaryKey("Id",101),
"set #P = :val1", // UpdateExpression
"#P = :val2", // ConditionExpression
expressionAttributeNames,
expressionAttributeValues);

Atomic Counter
You can use updateItem to implement an atomic counter, where you increment or decrement the value
of an existing attribute without interfering with other write requests. To increment an atomic counter,
use an UpdateExpression with a set action to add a numeric value to an existing attribute of type
Number.

The following example demonstrates this, incrementing the Quantity attribute by one. It also
demonstrates the use of the ExpressionAttributeNames parameter in an UpdateExpression.

API Version 2012-08-10


423
Amazon DynamoDB Developer Guide
Working with Items: Java

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

Map<String,String> expressionAttributeNames = new HashMap<String,String>();


expressionAttributeNames.put("#p", "PageCount");

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


expressionAttributeValues.put(":val", 1);

UpdateItemOutcome outcome = table.updateItem(


"Id", 121,
"set #p = #p + :val",
expressionAttributeNames,
expressionAttributeValues);

Deleting an Item
The deleteItem method deletes an item from a table. You must provide the primary key of the item
that you want to delete.

Follow these steps:

1. Create an instance of the DynamoDB client.


2. Call the deleteItem method by providing the key of the item you want to delete.

The following Java example demonstrates these tasks.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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

DeleteItemOutcome outcome = table.deleteItem("Id", 101);

Specifying Optional Parameters


You can specify optional parameters for deleteItem. For example, the following Java code example
specifies a ConditionExpression, stating that a book item in ProductCatalog can only be deleted if
the book is no longer in publication (the InPublication attribute is false).

Example

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


expressionAttributeValues.put(":val", false);

DeleteItemOutcome outcome = table.deleteItem("Id",103,


"InPublication = :val",
null, // ExpressionAttributeNames - not used in this example
expressionAttributeValues);

Example: CRUD Operations Using the AWS SDK for Java


Document API
The following code example illustrates CRUD operations on an Amazon DynamoDB item. The example
creates an item, retrieves it, performs various updates, and finally deletes the item.

API Version 2012-08-10


424
Amazon DynamoDB Developer Guide
Working with Items: Java

Note
The SDK for Java also provides an object persistence model, enabling you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code that you have to
write. For more information, see Java: DynamoDBMapper (p. 229).
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.
*/

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
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.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class DocumentAPIItemCRUDExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

static String tableName = "ProductCatalog";

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

createItems();

retrieveItem();

// Perform various updates.


updateMultipleAttributes();
updateAddNewAttribute();
updateExistingAttributeConditionally();

API Version 2012-08-10


425
Amazon DynamoDB Developer Guide
Working with Items: Java

// Delete the item.


deleteItem();

private static void createItems() {

Table table = dynamoDB.getTable(tableName);


try {

Item item = new Item().withPrimaryKey("Id", 120).withString("Title", "Book 120


Title")
.withString("ISBN", "120-1111111111")
.withStringSet("Authors", new HashSet<String>(Arrays.asList("Author12",
"Author22")))
.withNumber("Price", 20).withString("Dimensions",
"8.5x11.0x.75").withNumber("PageCount", 500)
.withBoolean("InPublication", false).withString("ProductCategory", "Book");
table.putItem(item);

item = new Item().withPrimaryKey("Id", 121).withString("Title", "Book 121


Title")
.withString("ISBN", "121-1111111111")
.withStringSet("Authors", new HashSet<String>(Arrays.asList("Author21",
"Author 22")))
.withNumber("Price", 20).withString("Dimensions",
"8.5x11.0x.75").withNumber("PageCount", 500)
.withBoolean("InPublication", true).withString("ProductCategory", "Book");
table.putItem(item);

}
catch (Exception e) {
System.err.println("Create items failed.");
System.err.println(e.getMessage());

}
}

private static void retrieveItem() {


Table table = dynamoDB.getTable(tableName);

try {

Item item = table.getItem("Id", 120, "Id, ISBN, Title, Authors", null);

System.out.println("Printing item after retrieving it....");


System.out.println(item.toJSONPretty());

}
catch (Exception e) {
System.err.println("GetItem failed.");
System.err.println(e.getMessage());
}

private static void updateAddNewAttribute() {


Table table = dynamoDB.getTable(tableName);

try {

UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 121)


.withUpdateExpression("set #na = :val1").withNameMap(new
NameMap().with("#na", "NewAttribute"))

API Version 2012-08-10


426
Amazon DynamoDB Developer Guide
Working with Items: Java

.withValueMap(new ValueMap().withString(":val1", "Some


value")).withReturnValues(ReturnValue.ALL_NEW);

UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

// Check the response.


System.out.println("Printing item after adding new attribute...");
System.out.println(outcome.getItem().toJSONPretty());

}
catch (Exception e) {
System.err.println("Failed to add new attribute in " + tableName);
System.err.println(e.getMessage());
}
}

private static void updateMultipleAttributes() {

Table table = dynamoDB.getTable(tableName);

try {

UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 120)


.withUpdateExpression("add #a :val1 set #na=:val2")
.withNameMap(new NameMap().with("#a", "Authors").with("#na",
"NewAttribute"))
.withValueMap(
new ValueMap().withStringSet(":val1", "Author YY", "Author
ZZ").withString(":val2", "someValue"))
.withReturnValues(ReturnValue.ALL_NEW);

UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

// Check the response.


System.out.println("Printing item after multiple attribute update...");
System.out.println(outcome.getItem().toJSONPretty());

}
catch (Exception e) {
System.err.println("Failed to update multiple attributes in " + tableName);
System.err.println(e.getMessage());

}
}

private static void updateExistingAttributeConditionally() {

Table table = dynamoDB.getTable(tableName);

try {

// Specify the desired price (25.00) and also the condition (price =
// 20.00)

UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 120)


.withReturnValues(ReturnValue.ALL_NEW).withUpdateExpression("set #p
= :val1")
.withConditionExpression("#p = :val2").withNameMap(new NameMap().with("#p",
"Price"))
.withValueMap(new ValueMap().withNumber(":val1", 25).withNumber(":val2",
20));

UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

// Check the response.

API Version 2012-08-10


427
Amazon DynamoDB Developer Guide
Working with Items: Java

System.out.println("Printing item after conditional update to new


attribute...");
System.out.println(outcome.getItem().toJSONPretty());

}
catch (Exception e) {
System.err.println("Error updating item in " + tableName);
System.err.println(e.getMessage());
}
}

private static void deleteItem() {

Table table = dynamoDB.getTable(tableName);

try {

DeleteItemSpec deleteItemSpec = new DeleteItemSpec().withPrimaryKey("Id", 120)


.withConditionExpression("#ip = :val").withNameMap(new
NameMap().with("#ip", "InPublication"))
.withValueMap(new ValueMap().withBoolean(":val",
false)).withReturnValues(ReturnValue.ALL_OLD);

DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec);

// Check the response.


System.out.println("Printing item that was deleted...");
System.out.println(outcome.getItem().toJSONPretty());

}
catch (Exception e) {
System.err.println("Error deleting item in " + tableName);
System.err.println(e.getMessage());
}
}
}

Example: Batch Operations Using AWS SDK for Java Document


API
This section provides examples of batch write and batch get operations in Amazon DynamoDB using the
AWS SDK for Java Document API.
Note
The SDK for Java also provides an object persistence model, enabling you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code that you have to
write. For more information, see Java: DynamoDBMapper (p. 229).

Topics
• Example: Batch Write Operation Using the AWS SDK for Java Document API (p. 428)
• Example: Batch Get Operation Using the AWS SDK for Java Document API (p. 430)

Example: Batch Write Operation Using the AWS SDK for Java Document API
The following Java code example uses the batchWriteItem method to perform the following put and
delete operations:

• Put one item in the Forum table.


• Put one item and delete one item from the Thread table.

API Version 2012-08-10


428
Amazon DynamoDB Developer Guide
Working with Items: Java

You can specify any number of put and delete requests against one or more tables when creating your
batch write request. However, batchWriteItem limits the size of a batch write request and the number
of put and delete operations in a single batch write operation. If your request exceeds these limits, your
request is rejected. If your table does not have sufficient provisioned throughput to serve this request,
the unprocessed request items are returned in the response.

The following example checks the response to see if it has any unprocessed request items. If it does,
it loops back and resends the batchWriteItem request with unprocessed items in the request. If you
followed the Creating Tables and Loading Data for Code Examples in DynamoDB (p. 326) section, you
should already have created the Forum and Thread tables. You can also create these tables and upload
sample data programmatically. For more information, see Creating Example Tables and Uploading Data
Using the AWS SDK for Java (p. 981).

For step-by-step instructions for testing the following sample, 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.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.BatchWriteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableWriteItems;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;

public class DocumentAPIBatchWrite {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

static String forumTableName = "Forum";


static String threadTableName = "Thread";

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

writeMultipleItemsBatchWrite();

private static void writeMultipleItemsBatchWrite() {

API Version 2012-08-10


429
Amazon DynamoDB Developer Guide
Working with Items: Java

try {

// Add a new item to Forum


TableWriteItems forumTableWriteItems = new TableWriteItems(forumTableName) //
Forum
.withItemsToPut(new Item().withPrimaryKey("Name", "Amazon
RDS").withNumber("Threads", 0));

// Add a new item, and delete an existing item, from Thread


// This table has a partition key and range key, so need to specify
// both of them
TableWriteItems threadTableWriteItems = new TableWriteItems(threadTableName)
.withItemsToPut(new Item().withPrimaryKey("ForumName", "Amazon RDS",
"Subject", "Amazon RDS Thread 1")
.withString("Message", "ElastiCache Thread 1 message")
.withStringSet("Tags", new HashSet<String>(Arrays.asList("cache", "in-
memory"))))
.withHashAndRangeKeysToDelete("ForumName", "Subject", "Amazon S3", "S3
Thread 100");

System.out.println("Making the request.");


BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems,
threadTableWriteItems);

do {

// Check for unprocessed keys which could happen if you exceed


// provisioned throughput

Map<String, List<WriteRequest>> unprocessedItems =


outcome.getUnprocessedItems();

if (outcome.getUnprocessedItems().size() == 0) {
System.out.println("No unprocessed items found");
}
else {
System.out.println("Retrieving the unprocessed items");
outcome = dynamoDB.batchWriteItemUnprocessed(unprocessedItems);
}

} while (outcome.getUnprocessedItems().size() > 0);

}
catch (Exception e) {
System.err.println("Failed to retrieve items: ");
e.printStackTrace(System.err);
}

Example: Batch Get Operation Using the AWS SDK for Java Document API
The following Java code example uses the batchGetItem method to retrieve multiple items from the
Forum and the Thread tables. The BatchGetItemRequest specifies the table names and a list of keys
for each item to get. The example processes the response by printing the items retrieved.
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).

API Version 2012-08-10


430
Amazon DynamoDB Developer Guide
Working with Items: Java

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.document;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.BatchGetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableKeysAndAttributes;
import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes;

public class DocumentAPIBatchGet {


static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
static DynamoDB dynamoDB = new DynamoDB(client);

static String forumTableName = "Forum";


static String threadTableName = "Thread";

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


retrieveMultipleItemsBatchGet();
}

private static void retrieveMultipleItemsBatchGet() {

try {

TableKeysAndAttributes forumTableKeysAndAttributes = new


TableKeysAndAttributes(forumTableName);
// Add a partition key
forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon
DynamoDB");

TableKeysAndAttributes threadTableKeysAndAttributes = new


TableKeysAndAttributes(threadTableName);
// Add a partition key and a sort key
threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject",
"Amazon DynamoDB",
"DynamoDB Thread 1", "Amazon DynamoDB", "DynamoDB Thread 2", "Amazon S3",
"S3 Thread 1");

System.out.println("Making the request.");

BatchGetItemOutcome outcome =
dynamoDB.batchGetItem(forumTableKeysAndAttributes,
threadTableKeysAndAttributes);

API Version 2012-08-10


431
Amazon DynamoDB Developer Guide
Working with Items: Java

Map<String, KeysAndAttributes> unprocessed = null;

do {
for (String tableName : outcome.getTableItems().keySet()) {
System.out.println("Items in table " + tableName);
List<Item> items = outcome.getTableItems().get(tableName);
for (Item item : items) {
System.out.println(item.toJSONPretty());
}
}

// Check for unprocessed keys which could happen if you exceed


// provisioned
// throughput or reach the limit on response size.
unprocessed = outcome.getUnprocessedKeys();

if (unprocessed.isEmpty()) {
System.out.println("No unprocessed keys found");
}
else {
System.out.println("Retrieving the unprocessed keys");
outcome = dynamoDB.batchGetItemUnprocessed(unprocessed);
}

} while (!unprocessed.isEmpty());

}
catch (Exception e) {
System.err.println("Failed to retrieve items.");
System.err.println(e.getMessage());
}

Example: Handling Binary Type Attributes Using the AWS SDK


for Java Document API
The following Java code example illustrates handling binary type attributes. The example adds an
item to the Reply table. The item includes a binary type attribute (ExtendedMessage) that stores
compressed data. The example then retrieves the item and prints all the attribute values. For illustration,
the example uses the GZIPOutputStream class to compress a sample stream and assign it to the
ExtendedMessage attribute. When the binary attribute is retrieved, it is decompressed using the
GZIPInputStream class.
Note
The SDK for Java also provides an object persistence model, enabling you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code that you have to
write. For more information, see Java: DynamoDBMapper (p. 229).

If you followed the Creating Tables and Loading Data for Code Examples in DynamoDB (p. 326) section,
you should already have created the Reply table. You can also create this table programmatically.
For more information, see Creating Example Tables and Uploading Data Using the AWS SDK for
Java (p. 981).

For step-by-step instructions for testing the following sample, see Java Code Examples (p. 331).

API Version 2012-08-10


432
Amazon DynamoDB Developer Guide
Working with Items: Java

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.document;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

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

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

static String tableName = "Reply";


static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-
dd'T'HH:mm:ss.SSS'Z'");

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


try {

// Format the primary key values


String threadId = "Amazon DynamoDB#DynamoDB Thread 2";

dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String replyDateTime = dateFormatter.format(new Date());

// Add a new reply with a binary attribute type


createItem(threadId, replyDateTime);

// Retrieve the reply with a binary attribute type


retrieveItem(threadId, replyDateTime);

// clean up by deleting the item


deleteItem(threadId, replyDateTime);
}
catch (Exception e) {
System.err.println("Error running the binary attribute type example: " + e);

API Version 2012-08-10


433
Amazon DynamoDB Developer Guide
Working with Items: Java

e.printStackTrace(System.err);
}
}

public static void createItem(String threadId, String replyDateTime) throws IOException


{

Table table = dynamoDB.getTable(tableName);

// Craft a long message


String messageInput = "Long message to be compressed in a lengthy forum reply";

// Compress the long message


ByteBuffer compressedMessage = compressString(messageInput.toString());

table.putItem(new Item().withPrimaryKey("Id", threadId).withString("ReplyDateTime",


replyDateTime)
.withString("Message", "Long message follows").withBinary("ExtendedMessage",
compressedMessage)
.withString("PostedBy", "User A"));
}

public static void retrieveItem(String threadId, String replyDateTime) throws


IOException {

Table table = dynamoDB.getTable(tableName);

GetItemSpec spec = new GetItemSpec().withPrimaryKey("Id", threadId,


"ReplyDateTime", replyDateTime)
.withConsistentRead(true);

Item item = table.getItem(spec);

// Uncompress the reply message and print


String uncompressed =
uncompressString(ByteBuffer.wrap(item.getBinary("ExtendedMessage")));

System.out.println("Reply message:\n" + " Id: " + item.getString("Id") + "\n" + "


ReplyDateTime: "
+ item.getString("ReplyDateTime") + "\n" + " PostedBy: " +
item.getString("PostedBy") + "\n" + " Message: "
+ item.getString("Message") + "\n" + " ExtendedMessage (uncompressed): " +
uncompressed + "\n");
}

public static void deleteItem(String threadId, String replyDateTime) {

Table table = dynamoDB.getTable(tableName);


table.deleteItem("Id", threadId, "ReplyDateTime", replyDateTime);
}

private static ByteBuffer compressString(String input) throws IOException {


// Compress the UTF-8 encoded String into a byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream os = new GZIPOutputStream(baos);
os.write(input.getBytes("UTF-8"));
os.close();
baos.close();
byte[] compressedBytes = baos.toByteArray();

// The following code writes the compressed bytes to a ByteBuffer.


// A simpler way to do this is by simply calling
// ByteBuffer.wrap(compressedBytes);
// However, the longer form below shows the importance of resetting the
// position of the buffer
// back to the beginning of the buffer if you are writing bytes directly

API Version 2012-08-10


434
Amazon DynamoDB Developer Guide
Working with Items: .NET

// to it, since the SDK


// will consider only the bytes after the current position when sending
// data to DynamoDB.
// Using the "wrap" method automatically resets the position to zero.
ByteBuffer buffer = ByteBuffer.allocate(compressedBytes.length);
buffer.put(compressedBytes, 0, compressedBytes.length);
buffer.position(0); // Important: reset the position of the ByteBuffer
// to the beginning
return buffer;
}

private static String uncompressString(ByteBuffer input) throws IOException {


byte[] bytes = input.array();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPInputStream is = new GZIPInputStream(bais);

int chunkSize = 1024;


byte[] buffer = new byte[chunkSize];
int length = 0;
while ((length = is.read(buffer, 0, chunkSize)) != -1) {
baos.write(buffer, 0, length);
}

String result = new String(baos.toByteArray(), "UTF-8");

is.close();
baos.close();
bais.close();

return result;
}
}

Working with Items: .NET


You can use the AWS SDK for .NET low-level API to perform typical create, read, update, and delete
(CRUD) operations on an item in a table. The following are the common steps that you follow to perform
data CRUD operations using the .NET low-level API:

1. Create an instance of the AmazonDynamoDBClient class (the client).


2. Provide the operation-specific required parameters in a corresponding request object.

For example, use the PutItemRequest request object when uploading an item and use the
GetItemRequest request object when retrieving an existing item.

You can use the request object to provide both the required and optional parameters.
3. Execute the appropriate method provided by the client by passing in the request object that you
created in the preceding step.

The AmazonDynamoDBClient client provides PutItem, GetItem, UpdateItem, and DeleteItem


methods for the CRUD operations.

Topics
• Putting an Item (p. 436)
• Getting an Item (p. 437)
• Updating an Item (p. 438)
• Atomic Counter (p. 440)

API Version 2012-08-10


435
Amazon DynamoDB Developer Guide
Working with Items: .NET

• Deleting an Item (p. 441)


• Batch Write: Putting and Deleting Multiple Items (p. 442)
• Batch Get: Getting Multiple Items (p. 443)
• Example: CRUD Operations Using the AWS SDK for .NET Low-Level API (p. 446)
• Example: Batch Operations Using the AWS SDK for .NET Low-Level API (p. 450)
• Example: Handling Binary Type Attributes Using the AWS SDK for .NET Low-Level API (p. 456)

Putting an Item
The PutItem method uploads an item to a table. If the item exists, it replaces the entire item.
Note
Instead of replacing the entire item, if you want to update only specific attributes, you can use
the UpdateItem method. For more information, see Updating an Item (p. 438).

The following are the steps to upload an item using the low-level .NET SDK API:

1. Create an instance of the AmazonDynamoDBClient class.


2. Provide the required parameters by creating an instance of the PutItemRequest class.

To put an item, you must provide the table name and the item.
3. Execute the PutItem method by providing the PutItemRequest object that you created in the
preceding step.

The following C# example demonstrates the preceding steps. The example uploads an item to the
ProductCatalog table.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new PutItemRequest


{
TableName = tableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue { N = "201" }},
{ "Title", new AttributeValue { S = "Book 201 Title" }},
{ "ISBN", new AttributeValue { S = "11-11-11-11" }},
{ "Price", new AttributeValue { S = "20.00" }},
{
"Authors",
new AttributeValue
{ SS = new List<string>{"Author1", "Author2"} }
}
}
};
client.PutItem(request);

In the preceding example, you upload a book item that has the Id, Title, ISBN, and Authors
attributes. Note that Id is a numeric type attribute, and all other attributes are of the string type.
Authors is a String set.

Specifying Optional Parameters


You can also provide optional parameters using the PutItemRequest object as shown in the following
C# example. The example specifies the following optional parameters:

API Version 2012-08-10


436
Amazon DynamoDB Developer Guide
Working with Items: .NET

• ExpressionAttributeNames, ExpressionAttributeValues, and ConditionExpression


specify that the item can be replaced only if the existing item has the ISBN attribute with a specific
value.
• ReturnValues parameter to request the old item in the response.

Example

var request = new PutItemRequest


{
TableName = tableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue { N = "104" }},
{ "Title", new AttributeValue { S = "Book 104 Title" }},
{ "ISBN", new AttributeValue { S = "444-4444444444" }},
{ "Authors",
new AttributeValue { SS = new List<string>{"Author3"}}}
},
// Optional parameters.
ExpressionAttributeNames = new Dictionary<string,string>()
{
{"#I", "ISBN"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":isbn",new AttributeValue {S = "444-4444444444"}}
},
ConditionExpression = "#I = :isbn"

};
var response = client.PutItem(request);

For more information, see PutItem.

Getting an Item
The GetItem method retrieves an item.
Note
To retrieve multiple items, you can use the BatchGetItem method. For more information, see
Batch Get: Getting Multiple Items (p. 443).

The following are the steps to retrieve an existing item using the low-level AWS SDK for .NET API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Provide the required parameters by creating an instance of the GetItemRequest class.

To get an item, you must provide the table name and primary key of the item.
3. Execute the GetItem method by providing the GetItemRequest object that you created in the
preceding step.

The following C# example demonstrates the preceding steps. The example retrieves an item from the
ProductCatalog table.

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

API Version 2012-08-10


437
Amazon DynamoDB Developer Guide
Working with Items: .NET

var request = new GetItemRequest


{
TableName = tableName,
Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N =
"202" } } },
};
var response = client.GetItem(request);

// Check the response.


var result = response.GetItemResult;
var attributeMap = result.Item; // Attribute list in the response.

Specifying Optional Parameters


You can also provide optional parameters using the GetItemRequest object, as shown in the following
C# example. The sample specifies the following optional parameters:

• ProjectionExpression parameter to specify the attributes to retrieve.


• ConsistentRead parameter to perform a strongly consistent read. To learn more read consistency,
see Read Consistency (p. 16).

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new GetItemRequest


{
TableName = tableName,
Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N =
"202" } } },
// Optional parameters.
ProjectionExpression = "Id, ISBN, Title, Authors",
ConsistentRead = true
};

var response = client.GetItem(request);

// Check the response.


var result = response.GetItemResult;
var attributeMap = result.Item;

For more information, see GetItem.

Updating an Item
The UpdateItem method updates an existing item if it is present. You can use the UpdateItem
operation to update existing attribute values, add new attributes, or delete attributes from the existing
collection. If the item that has the specified primary key is not found, it adds a new item.

The UpdateItem operation uses the following guidelines:

• If the item does not exist, UpdateItem adds a new item using the primary key that is specified in the
input.
• If the item exists, UpdateItem applies the updates as follows:
• Replaces the existing attribute values by the values in the update.
• If the attribute that you provide in the input does not exist, it adds a new attribute to the item.

API Version 2012-08-10


438
Amazon DynamoDB Developer Guide
Working with Items: .NET

• If the input attribute is null, it deletes the attribute, if it is present.


• If you use ADD for the Action, you can add values to an existing set (string or number set), or
mathematically add (use a positive number) or subtract (use a negative number) from the existing
numeric attribute value.

Note
The PutItem operation also can perform an update. For more information, see Putting an
Item (p. 436). For example, if you call PutItem to upload an item and the primary key exists,
the PutItem operation replaces the entire item. If there are attributes in the existing item and
those attributes are not specified in the input, the PutItem operation deletes those attributes.
However, UpdateItem updates only the specified input attributes. Any other existing attributes
of that item remain unchanged.

The following are the steps to update an existing item using the low-level .NET SDK API:

1. Create an instance of the AmazonDynamoDBClient class.


2. Provide the required parameters by creating an instance of the UpdateItemRequest class.

This is the request object in which you describe all the updates, such as add attributes, update
existing attributes, or delete attributes. To delete an existing attribute, specify the attribute name
with null value.
3. Execute the UpdateItem method by providing the UpdateItemRequest object that you created in
the preceding step.

The following C# code example demonstrates the preceding steps. The example updates a book item in
the ProductCatalog table. It adds a new author to the Authors collection, and deletes the existing
ISBN attribute. It also reduces the price by one.

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new UpdateItemRequest


{
TableName = tableName,
Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N =
"202" } } },
ExpressionAttributeNames = new Dictionary<string,string>()
{
{"#A", "Authors"},
{"#P", "Price"},
{"#NA", "NewAttribute"},
{"#I", "ISBN"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":auth",new AttributeValue { SS = {"Author YY","Author ZZ"}}},
{":p",new AttributeValue {N = "1"}},
{":newattr",new AttributeValue {S = "someValue"}},
},

// This expression does the following:


// 1) Adds two new authors to the list
// 2) Reduces the price
// 3) Adds a new attribute to the item
// 4) Removes the ISBN attribute from the item
UpdateExpression = "ADD #A :auth SET #P = #P - :p, #NA = :newattr REMOVE #I"
};
var response = client.UpdateItem(request);

API Version 2012-08-10


439
Amazon DynamoDB Developer Guide
Working with Items: .NET

Specifying Optional Parameters


You can also provide optional parameters using the UpdateItemRequest object, as shown in the
following C# example. It specifies the following optional parameters:

• ExpressionAttributeValues and ConditionExpression to specify that the price can be


updated only if the existing price is 20.00.
• ReturnValues parameter to request the updated item in the response.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new UpdateItemRequest


{
Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N =
"202" } } },

// Update price only if the current price is 20.00.


ExpressionAttributeNames = new Dictionary<string,string>()
{
{"#P", "Price"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":newprice",new AttributeValue {N = "22"}},
{":currprice",new AttributeValue {N = "20"}}
},
UpdateExpression = "SET #P = :newprice",
ConditionExpression = "#P = :currprice",
TableName = tableName,
ReturnValues = "ALL_NEW" // Return all the attributes of the updated item.
};

var response = client.UpdateItem(request);

For more information, see UpdateItem.

Atomic Counter
You can use updateItem to implement an atomic counter, where you increment or decrement the value
of an existing attribute without interfering with other write requests. To update an atomic counter, use
updateItem with an attribute of type Number in the UpdateExpression parameter, and ADD as the
Action.

The following example demonstrates this, incrementing the Quantity attribute by one.

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new UpdateItemRequest


{
Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N =
"121" } } },
ExpressionAttributeNames = new Dictionary<string, string>()
{
{"#Q", "Quantity"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()

API Version 2012-08-10


440
Amazon DynamoDB Developer Guide
Working with Items: .NET

{
{":incr",new AttributeValue {N = "1"}}
},
UpdateExpression = "SET #Q = #Q + :incr",
TableName = tableName
};

var response = client.UpdateItem(request);

Deleting an Item
The DeleteItem method deletes an item from a table.

The following are the steps to delete an item using the low-level .NET SDK API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Provide the required parameters by creating an instance of the DeleteItemRequest class.

To delete an item, the table name and item's primary key are required.
3. Execute the DeleteItem method by providing the DeleteItemRequest object that you created in
the preceding step.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();


string tableName = "ProductCatalog";

var request = new DeleteItemRequest


{
TableName = tableName,
Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N =
"201" } } },
};

var response = client.DeleteItem(request);

Specifying Optional Parameters


You can also provide optional parameters using the DeleteItemRequest object as shown in the
following C# code example. It specifies the following optional parameters:

• ExpressionAttributeValues and ConditionExpression to specify that the book item can be


deleted only if it is no longer in publication (the InPublication attribute value is false).
• ReturnValues parameter to request the deleted item in the response.

Example

var request = new DeleteItemRequest


{
TableName = tableName,
Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N =
"201" } } },

// Optional parameters.
ReturnValues = "ALL_OLD",
ExpressionAttributeNames = new Dictionary<string, string>()
{
{"#IP", "InPublication"}

API Version 2012-08-10


441
Amazon DynamoDB Developer Guide
Working with Items: .NET

},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":inpub",new AttributeValue {BOOL = false}}
},
ConditionExpression = "#IP = :inpub"
};

var response = client.DeleteItem(request);

For more information, see DeleteItem.

Batch Write: Putting and Deleting Multiple Items


Batch write refers to putting and deleting multiple items in a batch. The BatchWriteItem method
enables you to put and delete multiple items from one or more tables in a single call. The following are
the steps to retrieve multiple items using the low-level .NET SDK API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Describe all the put and delete operations by creating an instance of the BatchWriteItemRequest
class.
3. Execute the BatchWriteItem method by providing the BatchWriteItemRequest object that you
created in the preceding step.
4. Process the response. You should check if there were any unprocessed request items returned in the
response. This could happen if you reach the provisioned throughput limit or some other transient
error. Also, DynamoDB limits the request size and the number of operations you can specify in
a request. If you exceed these limits, DynamoDB rejects the request. For more information, see
BatchWriteItem.

The following C# code example demonstrates the preceding steps. The example creates a
BatchWriteItemRequest to perform the following write operations:

• Put an item in Forum table.


• Put and delete an item from Thread table.

The code then executes BatchWriteItem to perform a batch operation.

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";


string table2Name = "Thread";

var request = new BatchWriteItemRequest


{
RequestItems = new Dictionary<string, List<WriteRequest>>
{
{
table1Name, new List<WriteRequest>
{
new WriteRequest
{
PutRequest = new PutRequest
{
Item = new Dictionary<string,AttributeValue>
{
{ "Name", new AttributeValue { S = "Amazon S3 forum" } },
{ "Threads", new AttributeValue { N = "0" }}
}

API Version 2012-08-10


442
Amazon DynamoDB Developer Guide
Working with Items: .NET

}
}
}
} ,
{
table2Name, new List<WriteRequest>
{
new WriteRequest
{
PutRequest = new PutRequest
{
Item = new Dictionary<string,AttributeValue>
{
{ "ForumName", new AttributeValue { S = "Amazon S3 forum" } },
{ "Subject", new AttributeValue { S = "My sample question" } },
{ "Message", new AttributeValue { S = "Message Text." } },
{ "KeywordTags", new AttributeValue { SS = new List<string> { "Amazon S3",
"Bucket" } } }
}
}
},
new WriteRequest
{
DeleteRequest = new DeleteRequest
{
Key = new Dictionary<string,AttributeValue>()
{
{ "ForumName", new AttributeValue { S = "Some forum name" } },
{ "Subject", new AttributeValue { S = "Some subject" } }
}
}
}
}
}
}
};
response = client.BatchWriteItem(request);

For a working example, see Example: Batch Operations Using the AWS SDK for .NET Low-Level
API (p. 450).

Batch Get: Getting Multiple Items


The BatchGetItem method enables you to retrieve multiple items from one or more tables.
Note
To retrieve a single item, you can use the GetItem method.

The following are the steps to retrieve multiple items using the low-level AWS SDK for .NET API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Provide the required parameters by creating an instance of the BatchGetItemRequest class.

To retrieve multiple items, the table name and a list of primary key values are required.
3. Execute the BatchGetItem method by providing the BatchGetItemRequest object that you
created in the preceding step.
4. Process the response. You should check if there were any unprocessed keys, which could happen if
you reach the provisioned throughput limit or some other transient error.

The following C# code example demonstrates the preceding steps. The example retrieves items from two
tables, Forum and Thread. The request specifies two items in the Forum and three items in the Thread

API Version 2012-08-10


443
Amazon DynamoDB Developer Guide
Working with Items: .NET

table. The response includes items from both of the tables. The code shows how you can process the
response.

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";


string table2Name = "Thread";

var request = new BatchGetItemRequest


{
RequestItems = new Dictionary<string, KeysAndAttributes>()
{
{ table1Name,
new KeysAndAttributes
{
Keys = new List<Dictionary<string, AttributeValue>>()
{
new Dictionary<string, AttributeValue>()
{
{ "Name", new AttributeValue { S = "DynamoDB" } }
},
new Dictionary<string, AttributeValue>()
{
{ "Name", new AttributeValue { S = "Amazon S3" } }
}
}
}
},
{
table2Name,
new KeysAndAttributes
{
Keys = new List<Dictionary<string, AttributeValue>>()
{
new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue { S = "DynamoDB" } },
{ "Subject", new AttributeValue { S = "DynamoDB Thread 1" } }
},
new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue { S = "DynamoDB" } },
{ "Subject", new AttributeValue { S = "DynamoDB Thread 2" } }
},
new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue { S = "Amazon S3" } },
{ "Subject", new AttributeValue { S = "Amazon S3 Thread 1" } }
}
}
}
}
}
};

var response = client.BatchGetItem(request);

// Check the response.


var result = response.BatchGetItemResult;
var responses = result.Responses; // The attribute list in the response.

var table1Results = responses[table1Name];


Console.WriteLine("Items in table {0}" + table1Name);
foreach (var item1 in table1Results.Items)
{

API Version 2012-08-10


444
Amazon DynamoDB Developer Guide
Working with Items: .NET

PrintItem(item1);
}

var table2Results = responses[table2Name];


Console.WriteLine("Items in table {1}" + table2Name);
foreach (var item2 in table2Results.Items)
{
PrintItem(item2);
}
// Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other
error.
Dictionary<string, KeysAndAttributes> unprocessedKeys = result.UnprocessedKeys;
foreach (KeyValuePair<string, KeysAndAttributes> pair in unprocessedKeys)
{
Console.WriteLine(pair.Key, pair.Value);
}

Specifying Optional Parameters


You can also provide optional parameters using the BatchGetItemRequest object as shown in the
following C# code example. The example retrieves two items from the Forum table. It specifies the
following optional parameter:

• ProjectionExpression parameter to specify the attributes to retrieve.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";

var request = new BatchGetItemRequest


{
RequestItems = new Dictionary<string, KeysAndAttributes>()
{
{ table1Name,
new KeysAndAttributes
{
Keys = new List<Dictionary<string, AttributeValue>>()
{
new Dictionary<string, AttributeValue>()
{
{ "Name", new AttributeValue { S = "DynamoDB" } }
},
new Dictionary<string, AttributeValue>()
{
{ "Name", new AttributeValue { S = "Amazon S3" } }
}
}
},
// Optional - name of an attribute to retrieve.
ProjectionExpression = "Title"
}
}
};

var response = client.BatchGetItem(request);

For more information, see BatchGetItem.

API Version 2012-08-10


445
Amazon DynamoDB Developer Guide
Working with Items: .NET

Example: CRUD Operations Using the AWS SDK for .NET Low-
Level API
The following C# code example illustrates CRUD operations on an Amazon DynamoDB item. The
example adds an item to the ProductCatalog table, retrieves it, performs various updates, and finally
deletes the item. If you followed the steps in Creating Tables and Loading Data for Code Examples in
DynamoDB (p. 326), you already have the ProductCatalog table created. You can also create these
sample tables programmatically. For more information, see Creating Example Tables and Uploading Data
Using the AWS SDK for .NET (p. 988).

For step-by-step instructions for testing the following sample, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
class LowLevelItemCRUDExample
{
private static string tableName = "ProductCatalog";
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
CreateItem();
RetrieveItem();

// Perform various updates.


UpdateMultipleAttributes();
UpdateExistingAttributeConditionally();

// Delete item.
DeleteItem();
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();

API Version 2012-08-10


446
Amazon DynamoDB Developer Guide
Working with Items: .NET

}
}

private static void CreateItem()


{
var request = new PutItemRequest
{
TableName = tableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
N = "1000"
}},
{ "Title", new AttributeValue {
S = "Book 201 Title"
}},
{ "ISBN", new AttributeValue {
S = "11-11-11-11"
}},
{ "Authors", new AttributeValue {
SS = new List<string>{"Author1", "Author2" }
}},
{ "Price", new AttributeValue {
N = "20.00"
}},
{ "Dimensions", new AttributeValue {
S = "8.5x11.0x.75"
}},
{ "InPublication", new AttributeValue {
BOOL = false
} }
}
};
client.PutItem(request);
}

private static void RetrieveItem()


{
var request = new GetItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
N = "1000"
} }
},
ProjectionExpression = "Id, ISBN, Title, Authors",
ConsistentRead = true
};
var response = client.GetItem(request);

// Check the response.


var attributeList = response.Item; // attribute list in the response.
Console.WriteLine("\nPrinting item after retrieving it ............");
PrintItem(attributeList);
}

private static void UpdateMultipleAttributes()


{
var request = new UpdateItemRequest
{
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
N = "1000"

API Version 2012-08-10


447
Amazon DynamoDB Developer Guide
Working with Items: .NET

} }
},
// Perform the following updates:
// 1) Add two new authors to the list
// 1) Set a new attribute
// 2) Remove the ISBN attribute
ExpressionAttributeNames = new Dictionary<string, string>()
{
{"#A","Authors"},
{"#NA","NewAttribute"},
{"#I","ISBN"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":auth",new AttributeValue {
SS = {"Author YY", "Author ZZ"}
}},
{":new",new AttributeValue {
S = "New Value"
}}
},

UpdateExpression = "ADD #A :auth SET #NA = :new REMOVE #I",

TableName = tableName,
ReturnValues = "ALL_NEW" // Give me all attributes of the updated item.
};
var response = client.UpdateItem(request);

// Check the response.


var attributeList = response.Attributes; // attribute list in the response.
// print attributeList.
Console.WriteLine("\nPrinting item after multiple attribute
update ............");
PrintItem(attributeList);
}

private static void UpdateExistingAttributeConditionally()


{
var request = new UpdateItemRequest
{
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
N = "1000"
} }
},
ExpressionAttributeNames = new Dictionary<string, string>()
{
{"#P", "Price"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":newprice",new AttributeValue {
N = "22.00"
}},
{":currprice",new AttributeValue {
N = "20.00"
}}
},
// This updates price only if current price is 20.00.
UpdateExpression = "SET #P = :newprice",
ConditionExpression = "#P = :currprice",

TableName = tableName,
ReturnValues = "ALL_NEW" // Give me all attributes of the updated item.

API Version 2012-08-10


448
Amazon DynamoDB Developer Guide
Working with Items: .NET

};
var response = client.UpdateItem(request);

// Check the response.


var attributeList = response.Attributes; // attribute list in the response.
Console.WriteLine("\nPrinting item after updating price value
conditionally ............");
PrintItem(attributeList);
}

private static void DeleteItem()


{
var request = new DeleteItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
N = "1000"
} }
},

// Return the entire item as it appeared before the update.


ReturnValues = "ALL_OLD",
ExpressionAttributeNames = new Dictionary<string, string>()
{
{"#IP", "InPublication"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":inpub",new AttributeValue {
BOOL = false
}}
},
ConditionExpression = "#IP = :inpub"
};

var response = client.DeleteItem(request);

// Check the response.


var attributeList = response.Attributes; // Attribute list in the response.
// Print item.
Console.WriteLine("\nPrinting item that was just deleted ............");
PrintItem(attributeList);
}

private static void PrintItem(Dictionary<string, AttributeValue> attributeList)


{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;

Console.WriteLine(
attributeName + " " +
(value.S == null ? "" : "S=[" + value.S + "]") +
(value.N == null ? "" : "N=[" + value.N + "]") +
(value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray())
+ "]") +
(value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray())
+ "]")
);
}
Console.WriteLine("************************************************");
}
}

API Version 2012-08-10


449
Amazon DynamoDB Developer Guide
Working with Items: .NET

Example: Batch Operations Using the AWS SDK for .NET Low-
Level API
Topics
• Example: Batch Write Operation Using the AWS SDK for .NET Low-Level API (p. 450)
• Example: Batch Get Operation Using the AWS SDK for .NET Low-Level API (p. 453)

This section provides examples of batch operations, batch write and batch get, that Amazon DynamoDB
supports.

Example: Batch Write Operation Using the AWS SDK for .NET Low-Level API
The following C# code example uses the BatchWriteItem method to perform the following put and
delete operations:

• Put one item in the Forum table.


• Put one item and delete one item from the Thread table.

You can specify any number of put and delete requests against one or more tables when creating your
batch write request. However, DynamoDB BatchWriteItem limits the size of a batch write request and
the number of put and delete operations in a single batch write operation. For more information, see
BatchWriteItem. If your request exceeds these limits, your request is rejected. If your table does not have
sufficient provisioned throughput to serve this request, the unprocessed request items are returned in
the response.

The following example checks the response to see if it has any unprocessed request items. If it does,
it loops back and resends the BatchWriteItem request with unprocessed items in the request. If you
followed the steps in Creating Tables and Loading Data for Code Examples in DynamoDB (p. 326), you
already have the Forum and Thread tables created. You can also create these sample tables and upload
sample data programmatically. For more information, see Creating Example Tables and Uploading Data
Using the AWS SDK for .NET (p. 988).

For step-by-step instructions for testing the following sample, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

API Version 2012-08-10


450
Amazon DynamoDB Developer Guide
Working with Items: .NET

namespace com.amazonaws.codesamples
{
class LowLevelBatchWrite
{
private static string table1Name = "Forum";
private static string table2Name = "Thread";
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
TestBatchWrite();
}
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void TestBatchWrite()


{
var request = new BatchWriteItemRequest
{
ReturnConsumedCapacity = "TOTAL",
RequestItems = new Dictionary<string, List<WriteRequest>>
{
{
table1Name, new List<WriteRequest>
{
new WriteRequest
{
PutRequest = new PutRequest
{
Item = new Dictionary<string, AttributeValue>
{
{ "Name", new AttributeValue {
S = "S3 forum"
} },
{ "Threads", new AttributeValue {
N = "0"
}}
}
}
}
}
},
{
table2Name, new List<WriteRequest>
{
new WriteRequest
{
PutRequest = new PutRequest
{
Item = new Dictionary<string, AttributeValue>
{
{ "ForumName", new AttributeValue {
S = "S3 forum"
} },
{ "Subject", new AttributeValue {
S = "My sample question"
} },
{ "Message", new AttributeValue {
S = "Message Text."

API Version 2012-08-10


451
Amazon DynamoDB Developer Guide
Working with Items: .NET

} },
{ "KeywordTags", new AttributeValue {
SS = new List<string> { "S3", "Bucket" }
} }
}
}
},
new WriteRequest
{
// For the operation to delete an item, if you provide a
primary key value
// that does not exist in the table, there is no error, it is
just a no-op.
DeleteRequest = new DeleteRequest
{
Key = new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue {
S = "Some partition key value"
} },
{ "Subject", new AttributeValue {
S = "Some sort key value"
} }
}
}
}
}
}
}
};

CallBatchWriteTillCompletion(request);
}

private static void CallBatchWriteTillCompletion(BatchWriteItemRequest request)


{
BatchWriteItemResponse response;

int callCount = 0;
do
{
Console.WriteLine("Making request");
response = client.BatchWriteItem(request);
callCount++;

// Check the response.

var tableConsumedCapacities = response.ConsumedCapacity;


var unprocessed = response.UnprocessedItems;

Console.WriteLine("Per-table consumed capacity");


foreach (var tableConsumedCapacity in tableConsumedCapacities)
{
Console.WriteLine("{0} - {1}", tableConsumedCapacity.TableName,
tableConsumedCapacity.CapacityUnits);
}

Console.WriteLine("Unprocessed");
foreach (var unp in unprocessed)
{
Console.WriteLine("{0} - {1}", unp.Key, unp.Value.Count);
}
Console.WriteLine();

// For the next iteration, the request will have unprocessed items.
request.RequestItems = unprocessed;

API Version 2012-08-10


452
Amazon DynamoDB Developer Guide
Working with Items: .NET

} while (response.UnprocessedItems.Count > 0);

Console.WriteLine("Total # of batch write API calls made: {0}", callCount);


}
}
}

Example: Batch Get Operation Using the AWS SDK for .NET Low-Level API
The following C# code example uses the BatchGetItem method to retrieve multiple items from the
Forum and the Thread tables in Amazon DynamoDB. The BatchGetItemRequest specifies the table
names and a list of primary keys for each table. The example processes the response by printing the
items retrieved.

If you followed the steps in Creating Tables and Loading Data for Code Examples in DynamoDB (p. 326),
you already have these tables created with sample data. You can also create these sample tables
and upload sample data programmatically. For more information, see Creating Example Tables and
Uploading Data Using the AWS SDK for .NET (p. 988).

For step-by-step instructions for testing the following sample, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class LowLevelBatchGet
{
private static string table1Name = "Forum";
private static string table2Name = "Thread";
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
RetrieveMultipleItemsBatchGet();

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }

API Version 2012-08-10


453
Amazon DynamoDB Developer Guide
Working with Items: .NET

catch (Exception e) { Console.WriteLine(e.Message); }


}

private static void RetrieveMultipleItemsBatchGet()


{
var request = new BatchGetItemRequest
{
RequestItems = new Dictionary<string, KeysAndAttributes>()
{
{ table1Name,
new KeysAndAttributes
{
Keys = new List<Dictionary<string, AttributeValue> >()
{
new Dictionary<string, AttributeValue>()
{
{ "Name", new AttributeValue {
S = "Amazon DynamoDB"
} }
},
new Dictionary<string, AttributeValue>()
{
{ "Name", new AttributeValue {
S = "Amazon S3"
} }
}
}
}},
{
table2Name,
new KeysAndAttributes
{
Keys = new List<Dictionary<string, AttributeValue> >()
{
new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue {
S = "Amazon DynamoDB"
} },
{ "Subject", new AttributeValue {
S = "DynamoDB Thread 1"
} }
},
new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue {
S = "Amazon DynamoDB"
} },
{ "Subject", new AttributeValue {
S = "DynamoDB Thread 2"
} }
},
new Dictionary<string, AttributeValue>()
{
{ "ForumName", new AttributeValue {
S = "Amazon S3"
} },
{ "Subject", new AttributeValue {
S = "S3 Thread 1"
} }
}
}
}
}
}
};

API Version 2012-08-10


454
Amazon DynamoDB Developer Guide
Working with Items: .NET

BatchGetItemResponse response;
do
{
Console.WriteLine("Making request");
response = client.BatchGetItem(request);

// Check the response.


var responses = response.Responses; // Attribute list in the response.

foreach (var tableResponse in responses)


{
var tableResults = tableResponse.Value;
Console.WriteLine("Items retrieved from table {0}", tableResponse.Key);
foreach (var item1 in tableResults)
{
PrintItem(item1);
}
}

// Any unprocessed keys? could happen if you exceed ProvisionedThroughput


or some other error.
Dictionary<string, KeysAndAttributes> unprocessedKeys =
response.UnprocessedKeys;
foreach (var unprocessedTableKeys in unprocessedKeys)
{
// Print table name.
Console.WriteLine(unprocessedTableKeys.Key);
// Print unprocessed primary keys.
foreach (var key in unprocessedTableKeys.Value.Keys)
{
PrintItem(key);
}
}

request.RequestItems = unprocessedKeys;
} while (response.UnprocessedKeys.Count > 0);
}

private static void PrintItem(Dictionary<string, AttributeValue> attributeList)


{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;

Console.WriteLine(
attributeName + " " +
(value.S == null ? "" : "S=[" + value.S + "]") +
(value.N == null ? "" : "N=[" + value.N + "]") +
(value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray())
+ "]") +
(value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray())
+ "]")
);
}
Console.WriteLine("************************************************");
}
}

API Version 2012-08-10


455
Amazon DynamoDB Developer Guide
Working with Items: .NET

Example: Handling Binary Type Attributes Using the AWS SDK


for .NET Low-Level API
The following C# code example illustrates the handling of binary type attributes. The example adds
an item to the Reply table. The item includes a binary type attribute (ExtendedMessage) that
stores compressed data. The example then retrieves the item and prints all the attribute values. For
illustration, the example uses the GZipStream class to compress a sample stream and assigns it to the
ExtendedMessage attribute, and decompresses it when printing the attribute value.

If you followed the steps in Creating Tables and Loading Data for Code Examples in DynamoDB (p. 326),
you already have the Reply table created. You can also create these sample tables programmatically.
For more information, see Creating Example Tables and Uploading Data Using the AWS SDK
for .NET (p. 988).

For step-by-step instructions for testing the following example, see .NET Code Examples (p. 333).

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.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class LowLevelItemBinaryExample
{
private static string tableName = "Reply";
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
// Reply table primary key.
string replyIdPartitionKey = "Amazon DynamoDB#DynamoDB Thread 1";
string replyDateTimeSortKey = Convert.ToString(DateTime.UtcNow);

try
{
CreateItem(replyIdPartitionKey, replyDateTimeSortKey);
RetrieveItem(replyIdPartitionKey, replyDateTimeSortKey);
// Delete item.
DeleteItem(replyIdPartitionKey, replyDateTimeSortKey);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }

API Version 2012-08-10


456
Amazon DynamoDB Developer Guide
Working with Items: .NET

catch (AmazonServiceException e) { Console.WriteLine(e.Message); }


catch (Exception e) { Console.WriteLine(e.Message); }
}

private static void CreateItem(string partitionKey, string sortKey)


{
MemoryStream compressedMessage = ToGzipMemoryStream("Some long extended message
to compress.");
var request = new PutItemRequest
{
TableName = tableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
S = partitionKey
}},
{ "ReplyDateTime", new AttributeValue {
S = sortKey
}},
{ "Subject", new AttributeValue {
S = "Binary type "
}},
{ "Message", new AttributeValue {
S = "Some message about the binary type"
}},
{ "ExtendedMessage", new AttributeValue {
B = compressedMessage
}}
}
};
client.PutItem(request);
}

private static void RetrieveItem(string partitionKey, string sortKey)


{
var request = new GetItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {
S = partitionKey
} },
{ "ReplyDateTime", new AttributeValue {
S = sortKey
} }
},
ConsistentRead = true
};
var response = client.GetItem(request);

// Check the response.


var attributeList = response.Item; // attribute list in the response.
Console.WriteLine("\nPrinting item after retrieving it ............");

PrintItem(attributeList);
}

private static void DeleteItem(string partitionKey, string sortKey)


{
var request = new DeleteItemRequest
{
TableName = tableName,
Key = new Dictionary<string, AttributeValue>()
{
{ "Id", new AttributeValue {

API Version 2012-08-10


457
Amazon DynamoDB Developer Guide
Working with Queries

S = partitionKey
} },
{ "ReplyDateTime", new AttributeValue {
S = sortKey
} }
}
};
var response = client.DeleteItem(request);
}

private static void PrintItem(Dictionary<string, AttributeValue> attributeList)


{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;

Console.WriteLine(
attributeName + " " +
(value.S == null ? "" : "S=[" + value.S + "]") +
(value.N == null ? "" : "N=[" + value.N + "]") +
(value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray())
+ "]") +
(value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray())
+ "]") +
(value.B == null ? "" : "B=[" + FromGzipMemoryStream(value.B) + "]")
);
}
Console.WriteLine("************************************************");
}

private static MemoryStream ToGzipMemoryStream(string value)


{
MemoryStream output = new MemoryStream();
using (GZipStream zipStream = new GZipStream(output, CompressionMode.Compress,
true))
using (StreamWriter writer = new StreamWriter(zipStream))
{
writer.Write(value);
}
return output;
}

private static string FromGzipMemoryStream(MemoryStream stream)


{
using (GZipStream zipStream = new GZipStream(stream,
CompressionMode.Decompress))
using (StreamReader reader = new StreamReader(zipStream))
{
return reader.ReadToEnd();
}
}
}
}

Working with Queries in DynamoDB


The Query operation in Amazon DynamoDB finds items based on primary key values.

You must provide the name of the partition key attribute and a single value for that attribute. Query
returns all items with that partition key value. Optionally, you can provide a sort key attribute and use a
comparison operator to refine the search results.

API Version 2012-08-10


458
Amazon DynamoDB Developer Guide
Key Condition Expression

Topics
• Key Condition Expression (p. 459)
• Filter Expressions for Query (p. 461)
• Limiting the Number of Items in the Result Set (p. 461)
• Paginating Table Query Results (p. 462)
• Counting the Items in the Results (p. 463)
• Capacity Units Consumed by Query (p. 463)
• Read Consistency for Query (p. 464)
• Querying Tables and Indexes: Java (p. 464)
• Querying Tables and Indexes: .NET (p. 470)

Key Condition Expression


To specify the search criteria, you use a key condition expression—a string that determines the items to
be read from the table or index.

You must specify the partition key name and value as an equality condition.

You can optionally provide a second condition for the sort key (if present). The sort key condition must
use one of the following comparison operators:

• a = b — true if the attribute a is equal to the value b


• a < b — true if a is less than b
• a <= b — true if a is less than or equal to b
• a > b — true if a is greater than b
• a >= b — true if a is greater than or equal to b
• a BETWEEN b AND c — true if a is greater than or equal to b, and less than or equal to c.

The following function is also supported:

• begins_with (a, substr)— true if the value of attribute a begins with a particular substring.

The following AWS Command Line Interface (AWS CLI) examples demonstrate the use of key condition
expressions. These expressions use placeholders (such as :name and :sub) instead of actual values. For
more information, see Expression Attribute Names in DynamoDB (p. 390) and Expression Attribute
Values (p. 392).

Example

Query the Thread table for a particular ForumName (partition key). All of the items with that
ForumName value are read by the query because the sort key (Subject) is not included in
KeyConditionExpression.

aws dynamodb query \


--table-name Thread \
--key-condition-expression "ForumName = :name" \
--expression-attribute-values '{":name":{"S":"Amazon DynamoDB"}}'

API Version 2012-08-10


459
Amazon DynamoDB Developer Guide
Key Condition Expression

Example

Query the Thread table for a particular ForumName (partition key), but this time return only the items
with a given Subject (sort key).

aws dynamodb query \


--table-name Thread \
--key-condition-expression "ForumName = :name and Subject = :sub" \
--expression-attribute-values file://values.json

The arguments for --expression-attribute-values are stored in the values.json file.

{
":name":{"S":"Amazon DynamoDB"},
":sub":{"S":"DynamoDB Thread 1"}
}

Example

Query the Reply table for a particular Id (partition key), but return only those items whose
ReplyDateTime (sort key) begins with certain characters.

aws dynamodb query \


--table-name Reply \
--key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
--expression-attribute-values file://values.json

The arguments for --expression-attribute-values are stored in the values.json file.

{
":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
":dt":{"S":"2015-09"}
}

You can use any attribute name in a key condition expression, provided that the first character
is a-z or A-Z and the second character (if present) is a-z, A-Z, or 0-9. In addition, the attribute
name must not be a DynamoDB reserved word. (For a complete list of these, see Reserved Words in
DynamoDB (p. 1025).) If an attribute name does not meet these requirements, you must define an
expression attribute name as a placeholder. For more information, see Expression Attribute Names in
DynamoDB (p. 390).

For items with a given partition key value, DynamoDB stores these items close together, in sorted
order by sort key value. In a Query operation, DynamoDB retrieves the items in sorted order, and then
processes the items using KeyConditionExpression and any FilterExpression that might be
present. Only then are the Query results sent back to the client.

A Query operation always returns a result set. If no matching items are found, the result set is empty.

Query results are always sorted by the sort key value. If the data type of the sort key is Number, the
results are returned in numeric order. Otherwise, the results are returned in order of UTF-8 bytes. By
default, the sort order is ascending. To reverse the order, set the ScanIndexForward parameter to
false.

API Version 2012-08-10


460
Amazon DynamoDB Developer Guide
Filter Expressions for Query

A single Query operation can retrieve a maximum of 1 MB of data. This limit applies before any
FilterExpression is applied to the results. If LastEvaluatedKey is present in the response and is
non-null, you must paginate the result set (see Paginating Table Query Results (p. 462)).

Filter Expressions for Query


If you need to further refine the Query results, you can optionally provide a filter expression. A filter
expression determines which items within the Query results should be returned to you. All of the other
results are discarded.

A filter expression is applied after a Query finishes, but before the results are returned. Therefore, a
Query consumes the same amount of read capacity, regardless of whether a filter expression is present.

A Query operation can retrieve a maximum of 1 MB of data. This limit applies before the filter
expression is evaluated.

A filter expression cannot contain partition key or sort key attributes. You need to specify those
attributes in the key condition expression, not the filter expression.

The syntax for a filter expression is identical to that of a condition expression. Filter expressions can use
the same comparators, functions, and logical operators as a condition expression. For more information,
Condition Expressions (p. 393).

Example
The following AWS CLI example queries the Thread table for a particular ForumName (partition key) and
Subject (sort key). Of the items that are found, only the most popular discussion threads are returned
—in other words, only those threads with more than a certain number of Views.

aws dynamodb query \


--table-name Thread \
--key-condition-expression "ForumName = :fn and Subject = :sub" \
--filter-expression "#v >= :num" \
--expression-attribute-names '{"#v": "Views"}' \
--expression-attribute-values file://values.json

The arguments for --expression-attribute-values are stored in the values.json file.

{
":fn":{"S":"Amazon DynamoDB"},
":sub":{"S":"DynamoDB Thread 1"},
":num":{"N":"3"}
}

Note that Views is a reserved word in DynamoDB (see Reserved Words in DynamoDB (p. 1025)),
so this example uses #v as a placeholder. For more information, see Expression Attribute Names in
DynamoDB (p. 390).
Note
A filter expression removes items from the Query result set. If possible, avoid using Query
where you expect to retrieve a large number of items but also need to discard most of those
items.

Limiting the Number of Items in the Result Set


The Query operation allows you to limit the number of items that it returns in the result. To do this, set
the Limit parameter to the maximum number of items that you want.

API Version 2012-08-10


461
Amazon DynamoDB Developer Guide
Paginating Query Results

For example, suppose that you Query a table, with a Limit value of 6, and without a filter expression.
The Query result contains the first six items from the table that match the key condition expression from
the request.

Now suppose that you add a filter expression to the Query. In this case, DynamoDB applies the filter
expression to the six items that were returned, discarding those that do not match. The final Query
result contains six items or fewer, depending on the number of items that were filtered.

Paginating Table Query Results


DynamoDB paginates the results from Query operations. With pagination, the Query results are divided
into "pages" of data that are 1 MB in size (or less). An application can process the first page of results,
then the second page, and so on.

A single Query only returns a result set that fits within the 1 MB size limit. To determine whether there
are more results, and to retrieve them one page at a time, applications should do the following:

1. Examine the low-level Query result:


• If the result contains a LastEvaluatedKey element, proceed to step 2.
• If there is not a LastEvaluatedKey in the result, there are no more items to be retrieved.
2. Construct a new Query request, with the same parameters as the previous one. However, this time,
take the LastEvaluatedKey value from step 1 and use it as the ExclusiveStartKey parameter in
the new Query request.
3. Run the new Query request.
4. Go to step 1.

In other words, the LastEvaluatedKey from a Query response should be used as the
ExclusiveStartKey for the next Query request. If there is not a LastEvaluatedKey element in a
Query response, then you have retrieved the final page of results. If LastEvaluatedKey is not empty, it
does not necessarily mean that there is more data in the result set. The only way to know when you have
reached the end of the result set is when LastEvaluatedKey is empty.

You can use the AWS CLI to view this behavior. The AWS CLI sends low-level Query requests to
DynamoDB repeatedly, until LastEvaluatedKey is no longer present in the results. Consider the
following AWS CLI example that retrieves movie titles from a particular year.

aws dynamodb query --table-name Movies \


--projection-expression "title" \
--key-condition-expression "#y = :yyyy" \
--expression-attribute-names '{"#y":"year"}' \
--expression-attribute-values '{":yyyy":{"N":"1993"}}' \
--page-size 5 \
--debug

Ordinarily, the AWS CLI handles pagination automatically. However, in this example, the AWS CLI --
page-size parameter limits the number of items per page. The --debug parameter prints low-level
information about requests and responses.

If you run the example, the first response from DynamoDB looks similar to the following.

2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body:


b'{"Count":5,"Items":[{"title":{"S":"A Bronx Tale"}},
{"title":{"S":"A Perfect World"}},{"title":{"S":"Addams Family Values"}},
{"title":{"S":"Alive"}},{"title":{"S":"Benny & Joon"}}],
"LastEvaluatedKey":{"year":{"N":"1993"},"title":{"S":"Benny & Joon"}},
"ScannedCount":5}'

API Version 2012-08-10


462
Amazon DynamoDB Developer Guide
Counting the Items in the Results

The LastEvaluatedKey in the response indicates that not all of the items have been retrieved. The
AWS CLI then issues another Query request to DynamoDB. This request and response pattern continues,
until the final response.

2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body:


b'{"Count":1,"Items":[{"title":{"S":"What\'s Eating Gilbert Grape"}}],"ScannedCount":1}'

The absence of LastEvaluatedKey indicates that there are no more items to retrieve.
Note
The AWS SDKs handle the low-level DynamoDB responses (including the presence or absence
of LastEvaluatedKey) and provide various abstractions for paginating Query results. For
example, the SDK for Java document interface provides java.util.Iterator support so that
you can walk through the results one at a time.
For code examples in various programming languages, see the Amazon DynamoDB Getting
Started Guide and the AWS SDK documentation for your language.

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

Counting the Items in the Results


In addition to the items that match your criteria, the Query response contains the following elements:

• ScannedCount — The number of items that matched the key condition expression before a filter
expression (if present) was applied.
• Count — The number of items that remain after a filter expression (if present) was applied.

Note
If you don't use a filter expression, ScannedCount and Count have the same value.

If the size of the Query result set is larger than 1 MB, ScannedCount and Count represent only a partial
count of the total items. You need to perform multiple Query operations to retrieve all the results (see
Paginating Table Query Results (p. 462)).

Each Query response contains the ScannedCount and Count for the items that were processed by that
particular Query request. To obtain grand totals for all of the Query requests, you could keep a running
tally of both ScannedCount and Count.

Capacity Units Consumed by Query


You can Query any table or secondary index, provided that it has a composite primary key (partition key
and sort key). Query operations consume read capacity units, as follows.

If you Query a... DynamoDB consumes read capacity units from...

Table The table's provisioned read capacity.

Global secondary index The index's provisioned read capacity.

Local secondary index The base table's provisioned read capacity.

By default, a Query operation does not return any data on how much read capacity it consumes.
However, you can specify the ReturnConsumedCapacity parameter in a Query request to obtain this
information. The following are the valid settings for ReturnConsumedCapacity:

API Version 2012-08-10


463
Amazon DynamoDB Developer Guide
Read Consistency for Query

• NONE — No consumed capacity data is returned. (This is the default.)


• TOTAL — The response includes the aggregate number of read capacity units consumed.
• INDEXES — The response shows the aggregate number of read capacity units consumed, together
with the consumed capacity for each table and index that was accessed.

DynamoDB calculates the number of read capacity units consumed based on item size, not on the
amount of data that is returned to an application. For this reason, the number of capacity units
consumed is the same whether you request all of the attributes (the default behavior) or just some
of them (using a projection expression). The number is also the same whether or not you use a filter
expression.

Read Consistency for Query


A Query operation performs eventually consistent reads, by default. This means that the Query results
might not reflect changes due to recently completed PutItem or UpdateItem operations. For more
information, see Read Consistency (p. 16).

If you require strongly consistent reads, set the ConsistentRead parameter to true in the Query
request.

Querying Tables and Indexes: Java


The Query operation enables you to query a table or a secondary index in Amazon DynamoDB. You must
provide a partition key value and an equality condition. If the table or index has a sort key, you can refine
the results by providing a sort key value and a condition.
Note
The AWS SDK for Java also provides an object persistence model, enabling you to map your
client-side classes to DynamoDB tables. This approach can reduce the amount of code you have
to write. For more information, see Java: DynamoDBMapper (p. 229).

The following are the steps to retrieve an item using the AWS SDK for Java Document API.

1. Create an instance of the DynamoDB class.


2. Create an instance of the Table class to represent the table you want to work with.
3. Call the query method of the Table instance. You must specify the partition key value of the items
that you want to retrieve, along with any optional query parameters.

The response includes an ItemCollection object that provides all items returned by the query.

The following Java code example demonstrates the preceding tasks. The example assumes that you
have a Reply table that stores replies for forum threads. For more information, see Creating Tables and
Loading Data for Code Examples in DynamoDB (p. 326).

Reply ( Id, ReplyDateTime, ... )

Each forum thread has a unique ID and can have zero or more replies. Therefore, the Id attribute
of the Reply table is composed of both the forum name and forum subject. Id (partition key) and
ReplyDateTime (sort key) make up the composite primary key for the table.

The following query retrieves all replies for a specific thread subject. The query requires both the table
name and the Subject value.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()

API Version 2012-08-10


464
Amazon DynamoDB Developer Guide
Querying: Java

.withRegion(Regions.US_WEST_2).build();
DynamoDB dynamoDB = new DynamoDB(client);

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

QuerySpec spec = new QuerySpec()


.withKeyConditionExpression("Id = :v_id")
.withValueMap(new ValueMap()
.withString(":v_id", "Amazon DynamoDB#DynamoDB Thread 1"));

ItemCollection<QueryOutcome> items = table.query(spec);

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


Item item = null;
while (iterator.hasNext()) {
item = iterator.next();
System.out.println(item.toJSONPretty());
}

Specifying Optional Parameters


The query method supports several optional parameters. For example, you can optionally narrow the
results from the preceding query to return replies in the past two weeks by specifying a condition. The
condition is called a sort key condition, because DynamoDB evaluates the query condition that you
specify against the sort key of the primary key. You can specify other optional parameters to retrieve
only a specific list of attributes from items in the query result.

The following Java code example retrieves forum thread replies posted in the past 15 days. The example
specifies optional parameters using the following:

• A KeyConditionExpression to retrieve the replies from a specific discussion forum (partition key)
and, within that set of items, replies that were posted within the last 15 days (sort key).
• A FilterExpression to return only the replies from a specific user. The filter is applied after the
query is processed, but before the results are returned to the user.
• A ValueMap to define the actual values for the KeyConditionExpression placeholders.
• A ConsistentRead setting of true, to request a strongly consistent read.

This example uses a QuerySpec object that gives access to all of the low-level Query input parameters.

Example

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

long twoWeeksAgoMilli = (new Date()).getTime() - (15L*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);

QuerySpec spec = new QuerySpec()


.withKeyConditionExpression("Id = :v_id and ReplyDateTime > :v_reply_dt_tm")
.withFilterExpression("PostedBy = :v_posted_by")
.withValueMap(new ValueMap()
.withString(":v_id", "Amazon DynamoDB#DynamoDB Thread 1")
.withString(":v_reply_dt_tm", twoWeeksAgoStr)
.withString(":v_posted_by", "User B"))
.withConsistentRead(true);

API Version 2012-08-10


465
Amazon DynamoDB Developer Guide
Querying: Java

ItemCollection<QueryOutcome> items = table.query(spec);

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


while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}

You can also optionally limit the number of items per page by using the withMaxPageSize method.
When you call the query method, you get an ItemCollection that contains the resulting items. You
can then step through the results, processing one page at a time, until there are no more pages.

The following Java code example modifies the query specification shown previously. This time, the query
spec uses the withMaxPageSize method. The Page class provides an iterator that allows the code to
process the items on each page.

Example

spec.withMaxPageSize(10);

ItemCollection<QueryOutcome> items = table.query(spec);

// Process each page of results


int pageNum = 0;
for (Page<Item, QueryOutcome> page : items.pages()) {

System.out.println("\nPage: " + ++pageNum);

// Process each item on the current page


Iterator<Item> item = page.iterator();
while (item.hasNext()) {
System.out.println(item.next().toJSONPretty());
}
}

Example - Query Using Java


The following tables store information about a collection of forums. For more information, see Creating
Tables and Loading Data for Code Examples in DynamoDB (p. 326).
Note
The SDK for Java also provides an object persistence model, enabling you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code you have to
write. For more information, see Java: DynamoDBMapper (p. 229).

Example

Forum ( Name, ... )


Thread ( ForumName, Subject, Message, LastPostedBy, LastPostDateTime, ...)
Reply ( Id, ReplyDateTime, Message, PostedBy, ...)

In this Java code example, you execute variations of finding replies for a thread "DynamoDB Thread 1" in
forum "DynamoDB".

• Find replies for a thread.


• Find replies for a thread, specifying a limit on the number of items per page of results. If the number
of items in the result set exceeds the page size, you get only the first page of results. This coding
pattern ensures that your code processes all the pages in the query result.

API Version 2012-08-10


466
Amazon DynamoDB Developer Guide
Querying: Java

• Find replies in the last 15 days.


• Find replies in a specific date range.

The preceding two queries show how you can specify sort key conditions to narrow the query results
and use other optional query parameters.

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

package com.amazonaws.codesamples.document;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

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.Page;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class DocumentAPIQuery {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

static String tableName = "Reply";

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

String forumName = "Amazon DynamoDB";


String threadSubject = "DynamoDB Thread 1";

findRepliesForAThread(forumName, threadSubject);
findRepliesForAThreadSpecifyOptionalLimit(forumName, threadSubject);
findRepliesInLast15DaysWithConfig(forumName, threadSubject);
findRepliesPostedWithinTimePeriod(forumName, threadSubject);
findRepliesUsingAFilterExpression(forumName, threadSubject);
}

API Version 2012-08-10


467
Amazon DynamoDB Developer Guide
Querying: Java

private static void findRepliesForAThread(String forumName, String threadSubject) {

Table table = dynamoDB.getTable(tableName);

String replyId = forumName + "#" + threadSubject;

QuerySpec spec = new QuerySpec().withKeyConditionExpression("Id = :v_id")


.withValueMap(new ValueMap().withString(":v_id", replyId));

ItemCollection<QueryOutcome> items = table.query(spec);

System.out.println("\nfindRepliesForAThread results:");

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


while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}

private static void findRepliesForAThreadSpecifyOptionalLimit(String forumName, String


threadSubject) {

Table table = dynamoDB.getTable(tableName);

String replyId = forumName + "#" + threadSubject;

QuerySpec spec = new QuerySpec().withKeyConditionExpression("Id = :v_id")


.withValueMap(new ValueMap().withString(":v_id", replyId)).withMaxPageSize(1);

ItemCollection<QueryOutcome> items = table.query(spec);

System.out.println("\nfindRepliesForAThreadSpecifyOptionalLimit results:");

// Process each page of results


int pageNum = 0;
for (Page<Item, QueryOutcome> page : items.pages()) {

System.out.println("\nPage: " + ++pageNum);

// Process each item on the current page


Iterator<Item> item = page.iterator();
while (item.hasNext()) {
System.out.println(item.next().toJSONPretty());
}
}
}

private static void findRepliesInLast15DaysWithConfig(String forumName, String


threadSubject) {

Table table = dynamoDB.getTable(tableName);

long twoWeeksAgoMilli = (new Date()).getTime() - (15L * 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);

String replyId = forumName + "#" + threadSubject;

QuerySpec spec = new QuerySpec().withProjectionExpression("Message, ReplyDateTime,


PostedBy")
.withKeyConditionExpression("Id = :v_id and ReplyDateTime <= :v_reply_dt_tm")
.withValueMap(new ValueMap().withString(":v_id",
replyId).withString(":v_reply_dt_tm", twoWeeksAgoStr));

API Version 2012-08-10


468
Amazon DynamoDB Developer Guide
Querying: Java

ItemCollection<QueryOutcome> items = table.query(spec);

System.out.println("\nfindRepliesInLast15DaysWithConfig results:");
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}

private static void findRepliesPostedWithinTimePeriod(String forumName, String


threadSubject) {

Table table = dynamoDB.getTable(tableName);

long startDateMilli = (new Date()).getTime() - (15L * 24L * 60L * 60L * 1000L);


long endDateMilli = (new Date()).getTime() - (5L * 24L * 60L * 60L * 1000L);
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-
dd'T'HH:mm:ss.SSS'Z'");
String startDate = df.format(startDateMilli);
String endDate = df.format(endDateMilli);

String replyId = forumName + "#" + threadSubject;

QuerySpec spec = new QuerySpec().withProjectionExpression("Message, ReplyDateTime,


PostedBy")
.withKeyConditionExpression("Id = :v_id and ReplyDateTime between :v_start_dt
and :v_end_dt")
.withValueMap(new ValueMap().withString(":v_id",
replyId).withString(":v_start_dt", startDate)
.withString(":v_end_dt", endDate));

ItemCollection<QueryOutcome> items = table.query(spec);

System.out.println("\nfindRepliesPostedWithinTimePeriod results:");
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
}

private static void findRepliesUsingAFilterExpression(String forumName, String


threadSubject) {

Table table = dynamoDB.getTable(tableName);

String replyId = forumName + "#" + threadSubject;

QuerySpec spec = new QuerySpec().withProjectionExpression("Message, ReplyDateTime,


PostedBy")
.withKeyConditionExpression("Id = :v_id").withFilterExpression("PostedBy
= :v_postedby")
.withValueMap(new ValueMap().withString(":v_id",
replyId).withString(":v_postedby", "User B"));

ItemCollection<QueryOutcome> items = table.query(spec);

System.out.println("\nfindRepliesUsingAFilterExpression results:");
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
}

API Version 2012-08-10


469
Amazon DynamoDB Developer Guide
Querying: .NET

Querying Tables and Indexes: .NET


The Query operation enables you to query a table or a secondary index in Amazon DynamoDB. You must
provide a partition key value and an equality condition. If the table or index has a sort key, you can refine
the results by providing a sort key value and a condition.

The following are the steps to query a table using the low-level AWS SDK for .NET API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the QueryRequest class and provide query operation parameters.
3. Execute the Query method and provide the QueryRequest object that you created in the preceding
step.

The response includes the QueryResult object that provides all items returned by the query.

The following C# code example demonstrates the preceding tasks. The code assumes that you have
a Reply table that stores replies for forum threads. For more information, see Creating Tables and
Loading Data for Code Examples in DynamoDB (p. 326).

Example

Reply Id, ReplyDateTime, ... )

Each forum thread has a unique ID and can have zero or more replies. Therefore, the primary key is
composed of both the Id (partition key) and ReplyDateTime (sort key).

The following query retrieves all replies for a specific thread subject. The query requires both the table
name and the Subject value.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

var request = new QueryRequest


{
TableName = "Reply",
KeyConditionExpression = "Id = :v_Id",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 1" }}}
};

var response = client.Query(request);

foreach (Dictionary<string, AttributeValue> item in response.Items)


{
// Process the result.
PrintItem(item);
}

Specifying Optional Parameters


The Query method supports several optional parameters. For example, you can optionally narrow the
query result in the preceding query to return replies in the past two weeks by specifying a condition.
The condition is called a sort key condition, because DynamoDB evaluates the query condition that you

API Version 2012-08-10


470
Amazon DynamoDB Developer Guide
Querying: .NET

specify against the sort key of the primary key. You can specify other optional parameters to retrieve
only a specific list of attributes from items in the query result. For more information, see Query.

The following C# code example retrieves forum thread replies posted in the past 15 days. The example
specifies the following optional parameters:

• A KeyConditionExpression to retrieve only the replies in the past 15 days.


• A ProjectionExpression parameter to specify a list of attributes to retrieve for items in the query
result.
• A ConsistentRead parameter to perform a strongly consistent read.

Example

DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);


string twoWeeksAgoString = twoWeeksAgoDate.ToString(AWSSDKUtils.ISO8601DateFormat);

var request = new QueryRequest


{
TableName = "Reply",
KeyConditionExpression = "Id = :v_Id and ReplyDateTime > :v_twoWeeksAgo",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 2" }},
{":v_twoWeeksAgo", new AttributeValue { S = twoWeeksAgoString }}
},
ProjectionExpression = "Subject, ReplyDateTime, PostedBy",
ConsistentRead = true
};

var response = client.Query(request);

foreach (Dictionary<string, AttributeValue> item in response.Items)


{
// Process the result.
PrintItem(item);
}

You can also optionally limit the page size, or the number of items per page, by adding the optional
Limit parameter. Each time you execute the Query method, you get one page of results that has the
specified number of items. To fetch the next page, you execute the Query method again by providing
the primary key value of the last item in the previous page so that the method can return the next set
of items. You provide this information in the request by setting the ExclusiveStartKey property.
Initially, this property can be null. To retrieve subsequent pages, you must update this property value to
the primary key of the last item in the preceding page.

The following C# example queries the Reply table. In the request, it specifies the Limit and
ExclusiveStartKey optional parameters. The do/while loop continues to scan one page at time
until the LastEvaluatedKey returns a null value.

Example

Dictionary<string,AttributeValue> lastKeyEvaluated = null;

do
{
var request = new QueryRequest
{
TableName = "Reply",
KeyConditionExpression = "Id = :v_Id",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {

API Version 2012-08-10


471
Amazon DynamoDB Developer Guide
Querying: .NET

{":v_Id", new AttributeValue { S = "Amazon DynamoDB#DynamoDB Thread 2" }}


},

// Optional parameters.
Limit = 1,
ExclusiveStartKey = lastKeyEvaluated
};

var response = client.Query(request);

// Process the query result.


foreach (Dictionary<string, AttributeValue> item in response.Items)
{
PrintItem(item);
}

lastKeyEvaluated = response.LastEvaluatedKey;

} while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0);

Example - Querying Using the AWS SDK for .NET


The following tables store information about a collection of forums. For more information, see Creating
Tables and Loading Data for Code Examples in DynamoDB (p. 326).

Example

Forum ( Name, ... )


Thread ( ForumName, Subject, Message, LastPostedBy, LastPostDateTime, ...)
Reply ( Id, ReplyDateTime, Message, PostedBy, ...)

In this example, you execute variations of "Find replies for a thread "DynamoDB Thread 1" in forum
"DynamoDB".

• Find replies for a thread.


• Find replies for a thread. Specify the Limit query parameter to set page size.

This function illustrates the use of pagination to process multipage result. DynamoDB has a page size
limit and if your result exceeds the page size, you get only the first page of results. This coding pattern
ensures your code processes all the pages in the query result.
• Find replies in the last 15 days.
• Find replies in a specific date range.

The preceding two queries show how you can specify sort key conditions to narrow query results and
use other optional query parameters.

For step-by-step instructions for testing the following example, see .NET Code Examples (p. 333).

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


472
Amazon DynamoDB Developer Guide
Querying: .NET

* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.Util;

namespace com.amazonaws.codesamples
{
class LowLevelQuery
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
// Query a specific forum and thread.
string forumName = "Amazon DynamoDB";
string threadSubject = "DynamoDB Thread 1";

FindRepliesForAThread(forumName, threadSubject);
FindRepliesForAThreadSpecifyOptionalLimit(forumName, threadSubject);
FindRepliesInLast15DaysWithConfig(forumName, threadSubject);
FindRepliesPostedWithinTimePeriod(forumName, threadSubject);

Console.WriteLine("Example complete. To continue, press Enter");


Console.ReadLine();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message);
Console.ReadLine(); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message);
Console.ReadLine(); }
catch (Exception e) { Console.WriteLine(e.Message); Console.ReadLine(); }
}

private static void FindRepliesPostedWithinTimePeriod(string forumName, string


threadSubject)
{
Console.WriteLine("*** Executing FindRepliesPostedWithinTimePeriod() ***");
string replyId = forumName + "#" + threadSubject;
// You must provide date value based on your test data.
DateTime startDate = DateTime.UtcNow - TimeSpan.FromDays(21);
string start = startDate.ToString(AWSSDKUtils.ISO8601DateFormat);

// You provide date value based on your test data.


DateTime endDate = DateTime.UtcNow - TimeSpan.FromDays(5);
string end = endDate.ToString(AWSSDKUtils.ISO8601DateFormat);

var request = new QueryRequest


{
TableName = "Reply",
ReturnConsumedCapacity = "TOTAL",
KeyConditionExpression = "Id = :v_replyId and ReplyDateTime
between :v_start and :v_end",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_replyId", new AttributeValue {
S = replyId
}},
{":v_start", new AttributeValue {
S = start
}},
{":v_end", new AttributeValue {

API Version 2012-08-10


473
Amazon DynamoDB Developer Guide
Querying: .NET

S = end
}}
}
};

var response = client.Query(request);

Console.WriteLine("\nNo. of reads used (by query in


FindRepliesPostedWithinTimePeriod) {0}",
response.ConsumedCapacity.CapacityUnits);
foreach (Dictionary<string, AttributeValue> item
in response.Items)
{
PrintItem(item);
}
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}

private static void FindRepliesInLast15DaysWithConfig(string forumName, string


threadSubject)
{
Console.WriteLine("*** Executing FindRepliesInLast15DaysWithConfig() ***");
string replyId = forumName + "#" + threadSubject;

DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15);


string twoWeeksAgoString =
twoWeeksAgoDate.ToString(AWSSDKUtils.ISO8601DateFormat);

var request = new QueryRequest


{
TableName = "Reply",
ReturnConsumedCapacity = "TOTAL",
KeyConditionExpression = "Id = :v_replyId and ReplyDateTime > :v_interval",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_replyId", new AttributeValue {
S = replyId
}},
{":v_interval", new AttributeValue {
S = twoWeeksAgoString
}}
},

// Optional parameter.
ProjectionExpression = "Id, ReplyDateTime, PostedBy",
// Optional parameter.
ConsistentRead = true
};

var response = client.Query(request);

Console.WriteLine("No. of reads used (by query in


FindRepliesInLast15DaysWithConfig) {0}",
response.ConsumedCapacity.CapacityUnits);
foreach (Dictionary<string, AttributeValue> item
in response.Items)
{
PrintItem(item);
}
Console.WriteLine("To continue, press Enter");
Console.ReadLine();
}

private static void FindRepliesForAThreadSpecifyOptionalLimit(string forumName,


string threadSubject)
{

API Version 2012-08-10


474
Amazon DynamoDB Developer Guide
Querying: .NET

Console.WriteLine("*** Executing FindRepliesForAThreadSpecifyOptionalLimit()


***");
string replyId = forumName + "#" + threadSubject;

Dictionary<string, AttributeValue> lastKeyEvaluated = null;


do
{
var request = new QueryRequest
{
TableName = "Reply",
ReturnConsumedCapacity = "TOTAL",
KeyConditionExpression = "Id = :v_replyId",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_replyId", new AttributeValue {
S = replyId
}}
},
Limit = 2, // The Reply table has only a few sample items. So the page
size is smaller.
ExclusiveStartKey = lastKeyEvaluated
};

var response = client.Query(request);

Console.WriteLine("No. of reads used (by query in


FindRepliesForAThreadSpecifyLimit) {0}\n",
response.ConsumedCapacity.CapacityUnits);
foreach (Dictionary<string, AttributeValue> item
in response.Items)
{
PrintItem(item);
}
lastKeyEvaluated = response.LastEvaluatedKey;
} while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0);

Console.WriteLine("To continue, press Enter");

Console.ReadLine();
}

private static void FindRepliesForAThread(string forumName, string threadSubject)


{
Console.WriteLine("*** Executing FindRepliesForAThread() ***");
string replyId = forumName + "#" + threadSubject;

var request = new QueryRequest


{
TableName = "Reply",
ReturnConsumedCapacity = "TOTAL",
KeyConditionExpression = "Id = :v_replyId",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_replyId", new AttributeValue {
S = replyId
}}
}
};

var response = client.Query(request);


Console.WriteLine("No. of reads used (by query in FindRepliesForAThread)
{0}\n",
response.ConsumedCapacity.CapacityUnits);
foreach (Dictionary<string, AttributeValue> item in response.Items)
{
PrintItem(item);
}

API Version 2012-08-10


475
Amazon DynamoDB Developer Guide
Working with Scans

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void PrintItem(


Dictionary<string, AttributeValue> attributeList)
{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;

Console.WriteLine(
attributeName + " " +
(value.S == null ? "" : "S=[" + value.S + "]") +
(value.N == null ? "" : "N=[" + value.N + "]") +
(value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray())
+ "]") +
(value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray())
+ "]")
);
}
Console.WriteLine("************************************************");
}
}
}

Working with Scans in DynamoDB


A Scan operation in Amazon DynamoDB reads every item in a table or a secondary index. By default,
a Scan operation returns all of the data attributes for every item in the table or index. You can use the
ProjectionExpression parameter so that Scan only returns some of the attributes, rather than all of
them.

Scan always returns a result set. If no matching items are found, the result set is empty.

A single Scan request can retrieve a maximum of 1 MB of data. Optionally, DynamoDB can apply a filter
expression to this data, narrowing the results before they are returned to the user.

Topics
• Filter Expressions for Scan (p. 476)
• Limiting the Number of Items in the Result Set (p. 477)
• Paginating the Results (p. 477)
• Counting the Items in the Results (p. 478)
• Capacity Units Consumed by Scan (p. 479)
• Read Consistency for Scan (p. 479)
• Parallel Scan (p. 480)
• Scanning Tables and Indexes: Java (p. 482)
• Scanning Tables and Indexes: .NET (p. 489)

Filter Expressions for Scan


If you need to further refine the Scan results, you can optionally provide a filter expression. A filter
expression determines which items within the Scan results should be returned to you. All of the other
results are discarded.

API Version 2012-08-10


476
Amazon DynamoDB Developer Guide
Limiting the Number of Items in the Result Set

A filter expression is applied after a Scan finishes but before the results are returned. Therefore, a Scan
consumes the same amount of read capacity, regardless of whether a filter expression is present.

A Scan operation can retrieve a maximum of 1 MB of data. This limit applies before the filter expression
is evaluated.

With Scan, you can specify any attributes in a filter expression—including partition key and sort key
attributes.

The syntax for a filter expression is identical to that of a condition expression. Filter expressions can use
the same comparators, functions, and logical operators as a condition expression. For more information,
Condition Expressions (p. 393).

Example

The following AWS Command Line Interface (AWS CLI) example scans the Thread table and returns only
the items that were last posted to by a particular user.

aws dynamodb scan \


--table-name Thread \
--filter-expression "LastPostedBy = :name" \
--expression-attribute-values '{":name":{"S":"User A"}}'

Limiting the Number of Items in the Result Set


The Scan operation enables you to limit the number of items that it returns in the result. To do this, set
the Limit parameter to the maximum number of items that you want the Scan operation to return,
prior to filter expression evaluation.

For example, suppose that you Scan a table with a Limit value of 6 and without a filter expression. The
Scan result contains the first six items from the table that match the key condition expression from the
request.

Now suppose that you add a filter expression to the Scan. In this case, DynamoDB applies the filter
expression to the six items that were returned, discarding those that do not match. The final Scan result
contains six items or fewer, depending on the number of items that were filtered.

Paginating the Results


DynamoDB paginates the results from Scan operations. With pagination, the Scan results are divided
into "pages" of data that are 1 MB in size (or less). An application can process the first page of results,
then the second page, and so on.

A single Scan only returns a result set that fits within the 1 MB size limit. To determine whether there
are more results and to retrieve them one page at a time, applications should do the following:

1. Examine the low-level Scan result:

• If the result contains a LastEvaluatedKey element, proceed to step 2.


• If there is not a LastEvaluatedKey in the result, then there are no more items to be retrieved.
2. Construct a new Scan request, with the same parameters as the previous one. However, this time,
take the LastEvaluatedKey value from step 1 and use it as the ExclusiveStartKey parameter
in the new Scan request.
3. Run the new Scan request.
4. Go to step 1.

API Version 2012-08-10


477
Amazon DynamoDB Developer Guide
Counting the Items in the Results

In other words, the LastEvaluatedKey from a Scan response should be used as the
ExclusiveStartKey for the next Scan request. If there is not a LastEvaluatedKey element in a
Scan response, you have retrieved the final page of results. (The absence of LastEvaluatedKey is the
only way to know that you have reached the end of the result set.)

You can use the AWS CLI to view this behavior. The AWS CLI sends low-level Scan requests to
DynamoDB, repeatedly, until LastEvaluatedKey is no longer present in the results. Consider the
following AWS CLI example that scans the entire Movies table but returns only the movies from a
particular genre.

aws dynamodb scan \


--table-name Movies \
--projection-expression "title" \
--filter-expression 'contains(info.genres,:gen)' \
--expression-attribute-values '{":gen":{"S":"Sci-Fi"}}' \
--page-size 100 \
--debug

Ordinarily, the AWS CLI handles pagination automatically. However, in this example, the AWS CLI --
page-size parameter limits the number of items per page. The --debug parameter prints low-level
information about requests and responses.

If you run the example, the first response from DynamoDB looks similar to the following.

2017-07-07 12:19:14,389 - MainThread - botocore.parsers - DEBUG - Response body:


b'{"Count":7,"Items":[{"title":{"S":"Monster on the Campus"}},{"title":{"S":"+1"}},
{"title":{"S":"100 Degrees Below Zero"}},{"title":{"S":"About Time"}},{"title":{"S":"After
Earth"}},
{"title":{"S":"Age of Dinosaurs"}},{"title":{"S":"Cloudy with a Chance of Meatballs 2"}}],
"LastEvaluatedKey":{"year":{"N":"2013"},"title":{"S":"Curse of
Chucky"}},"ScannedCount":100}'

The LastEvaluatedKey in the response indicates that not all of the items have been retrieved. The
AWS CLI then issues another Scan request to DynamoDB. This request and response pattern continues,
until the final response.

2017-07-07 12:19:17,830 - MainThread - botocore.parsers - DEBUG - Response body:


b'{"Count":1,"Items":[{"title":{"S":"WarGames"}}],"ScannedCount":6}'

The absence of LastEvaluatedKey indicates that there are no more items to retrieve.
Note
The AWS SDKs handle the low-level DynamoDB responses (including the presence or absence
of LastEvaluatedKey) and provide various abstractions for paginating Scan results. For
example, the SDK for Java document interface provides java.util.Iterator support so that
you can walk through the results one at a time.
For code examples in various programming languages, see the Amazon DynamoDB Getting
Started Guide and the AWS SDK documentation for your language.

Counting the Items in the Results


In addition to the items that match your criteria, the Scan response contains the following elements:

• ScannedCount — The number of items evaluated, before any ScanFilter is applied. A high
ScannedCount value with few, or no, Count results indicates an inefficient Scan operation. If you did
not use a filter in the request, ScannedCount is the same as Count.
• Count — The number of items that remain, after a filter expression (if present) was applied.

API Version 2012-08-10


478
Amazon DynamoDB Developer Guide
Capacity Units Consumed by Scan

Note
If you do not use a filter expression, ScannedCount and Count have the same value.

If the size of the Scan result set is larger than 1 MB, ScannedCount and Count represent only a partial
count of the total items. You need to perform multiple Scan operations to retrieve all the results (see
Paginating the Results (p. 477)).

Each Scan response contains the ScannedCount and Count for the items that were processed by that
particular Scan request. To get grand totals for all of the Scan requests, you could keep a running tally
of both ScannedCount and Count.

Capacity Units Consumed by Scan


You can Scan any table or secondary index. Scan operations consume read capacity units, as follows.

If you Scan a... DynamoDB consumes read capacity units from...

Table The table's provisioned read capacity.

Global secondary index The index's provisioned read capacity.

Local secondary index The base table's provisioned read capacity.

By default, a Scan operation does not return any data on how much read capacity it consumes. However,
you can specify the ReturnConsumedCapacity parameter in a Scan request to obtain this information.
The following are the valid settings for ReturnConsumedCapacity:

• NONE — No consumed capacity data is returned. (This is the default.)


• TOTAL — The response includes the aggregate number of read capacity units consumed.
• INDEXES — The response shows the aggregate number of read capacity units consumed, together
with the consumed capacity for each table and index that was accessed.

DynamoDB calculates the number of read capacity units consumed based on item size, not on the
amount of data that is returned to an application. For this reason, the number of capacity units
consumed is the same whether you request all of the attributes (the default behavior) or just some
of them (using a projection expression). The number is also the same whether or not you use a filter
expression.

Read Consistency for Scan


A Scan operation performs eventually consistent reads, by default. This means that the Scan results
might not reflect changes due to recently completed PutItem or UpdateItem operations. For more
information, see Read Consistency (p. 16).

If you require strongly consistent reads, as of the time that the Scan begins, set the ConsistentRead
parameter to true in the Scan request. This ensures that all of the write operations that completed
before the Scan began are included in the Scan response.

Setting ConsistentRead to true can be useful in table backup or replication scenarios, in conjunction
with DynamoDB Streams. You first use Scan with ConsistentRead set to true to obtain a consistent
copy of the data in the table. During the Scan, DynamoDB Streams records any additional write activity
that occurs on the table. After the Scan is complete, you can apply the write activity from the stream to
the table.

API Version 2012-08-10


479
Amazon DynamoDB Developer Guide
Parallel Scan

Note
A Scan operation with ConsistentRead set to true consumes twice as many read capacity
units as compared to leaving ConsistentRead at its default value (false).

Parallel Scan
By default, the Scan operation processes data sequentially. Amazon DynamoDB returns data to the
application in 1 MB increments, and an application performs additional Scan operations to retrieve the
next 1 MB of data.

The larger the table or index being scanned, the more time the Scan takes to complete. In addition, a
sequential Scan might not always be able to fully use the provisioned read throughput capacity: Even
though DynamoDB distributes a large table's data across multiple physical partitions, a Scan operation
can only read one partition at a time. For this reason, the throughput of a Scan is constrained by the
maximum throughput of a single partition.

To address these issues, the Scan operation can logically divide a table or secondary index into multiple
segments, with multiple application workers scanning the segments in parallel. Each worker can be a
thread (in programming languages that support multithreading) or an operating system process. To
perform a parallel scan, each worker issues its own Scan request with the following parameters:

• Segment — A segment to be scanned by a particular worker. Each worker should use a different value
for Segment.
• TotalSegments — The total number of segments for the parallel scan. This value must be the same
as the number of workers that your application will use.

The following diagram shows how a multithreaded application performs a parallel Scan with three
degrees of parallelism.

API Version 2012-08-10


480
Amazon DynamoDB Developer Guide
Parallel Scan

In this diagram, the application spawns three threads and assigns each thread a number. (Segments
are zero-based, so the first number is always 0.) Each thread issues a Scan request, setting Segment
to its designated number and setting TotalSegments to 3. Each thread scans its designated segment,
retrieving data 1 MB at a time, and returns the data to the application's main thread.

The values for Segment and TotalSegments apply to individual Scan requests, and you can use
different values at any time. You might need to experiment with these values, and the number of
workers you use, until your application achieves its best performance.
Note
A parallel scan with a large number of workers can easily consume all of the provisioned
throughput for the table or index being scanned. It is best to avoid such scans if the table or
index is also incurring heavy read or write activity from other applications.

API Version 2012-08-10


481
Amazon DynamoDB Developer Guide
Scanning: Java

To control the amount of data returned per request, use the Limit parameter. This can help
prevent situations where one worker consumes all of the provisioned throughput, at the
expense of all other workers.

Scanning Tables and Indexes: Java


The Scan operation reads all of the items in a table or index in Amazon DynamoDB.

The following are the steps to scan a table using the AWS SDK for Java Document API.

1. Create an instance of the AmazonDynamoDB class.


2. Create an instance of the ScanRequest class and provide scan parameter.

The only required parameter is the table name.


3. Execute the scan method and provide the ScanRequest object that you created in the preceding
step.

The following Reply table stores replies for forum threads.

Example

Reply ( Id, ReplyDateTime, Message, PostedBy )

The table maintains all the replies for various forum threads. Therefore, the primary key is composed of
both the Id (partition key) and ReplyDateTime (sort key). The following Java code example scans the
entire table. The ScanRequest instance specifies the name of the table to scan.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

ScanRequest scanRequest = new ScanRequest()


.withTableName("Reply");

ScanResult result = client.scan(scanRequest);


for (Map<String, AttributeValue> item : result.getItems()){
printItem(item);
}

Specifying Optional Parameters


The scan method supports several optional parameters. For example, you can optionally use a filter
expression to filter the scan result. In a filter expression, you can specify a condition and attribute names
and values on which you want the condition evaluated. For more information, see Scan.

The following Java example scans the ProductCatalog table to find items that are priced less than 0.
The example specifies the following optional parameters:

• A filter expression to retrieve only the items priced less than 0 (error condition).
• A list of attributes to retrieve for items in the query results.

Example

Map<String, AttributeValue> expressionAttributeValues =


new HashMap<String, AttributeValue>();
expressionAttributeValues.put(":val", new AttributeValue().withN("0"));

API Version 2012-08-10


482
Amazon DynamoDB Developer Guide
Scanning: Java

ScanRequest scanRequest = new ScanRequest()


.withTableName("ProductCatalog")
.withFilterExpression("Price < :val")
.withProjectionExpression("Id")
.withExpressionAttributeValues(expressionAttributeValues);

ScanResult result = client.scan(scanRequest);


for (Map<String, AttributeValue> item : result.getItems()) {
printItem(item);
}

You can also optionally limit the page size, or the number of items per page, by using the withLimit
method of the scan request. Each time you execute the scan method, you get one page of results
that has the specified number of items. To fetch the next page, you execute the scan method
again by providing the primary key value of the last item in the previous page so that the scan
method can return the next set of items. You provide this information in the request by using the
withExclusiveStartKey method. Initially, the parameter of this method can be null. To retrieve
subsequent pages, you must update this property value to the primary key of the last item in the
preceding page.

The following Java code example scans the ProductCatalog table. In the request, the withLimit and
withExclusiveStartKey methods are used. The do/while loop continues to scan one page at time
until the getLastEvaluatedKey method of the result returns a value of null.

Example

Map<String, AttributeValue> lastKeyEvaluated = null;


do {
ScanRequest scanRequest = new ScanRequest()
.withTableName("ProductCatalog")
.withLimit(10)
.withExclusiveStartKey(lastKeyEvaluated);

ScanResult result = client.scan(scanRequest);


for (Map<String, AttributeValue> item : result.getItems()){
printItem(item);
}
lastKeyEvaluated = result.getLastEvaluatedKey();
} while (lastKeyEvaluated != null);

Example - Scan Using Java


The following Java code example provides a working sample that scans the ProductCatalog table to
find items that are priced less than 100.
Note
The SDK for Java also provides an object persistence model, enabling you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code that you have to
write. For more information, see Java: DynamoDBMapper (p. 229).
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.
*

API Version 2012-08-10


483
Amazon DynamoDB Developer Guide
Scanning: Java

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

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

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;

public class DocumentAPIScan {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);
static String tableName = "ProductCatalog";

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

findProductsForPriceLessThanOneHundred();
}

private static void findProductsForPriceLessThanOneHundred() {

Table table = dynamoDB.getTable(tableName);

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


expressionAttributeValues.put(":pr", 100);

ItemCollection<ScanOutcome> items = table.scan("Price < :pr", // FilterExpression


"Id, Title, ProductCategory, Price", // ProjectionExpression
null, // ExpressionAttributeNames - not used in this example
expressionAttributeValues);

System.out.println("Scan of " + tableName + " for items with a price less than
100.");
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
}

Example - Parallel Scan Using Java


The following Java code example demonstrates a parallel scan. The program deletes and re-creates a
table named ParallelScanTest, and then loads the table with data. When the data load is finished,

API Version 2012-08-10


484
Amazon DynamoDB Developer Guide
Scanning: Java

the program spawns multiple threads and issues parallel Scan requests. The program prints runtime
statistics for each parallel request.
Note
The SDK for Java also provides an object persistence model, enabling you to map your client-
side classes to DynamoDB tables. This approach can reduce the amount of code that you have to
write. For more information, see Java: DynamoDBMapper (p. 229).
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.
*/

package com.amazonaws.codesamples.document;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import com.amazonaws.AmazonServiceException;
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.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;

public class DocumentAPIParallelScan {

// total number of sample items


static int scanItemCount = 300;

// number of items each scan request should return


static int scanItemLimit = 10;

// number of logical segments for parallel scan


static int parallelScanThreads = 16;

API Version 2012-08-10


485
Amazon DynamoDB Developer Guide
Scanning: Java

// table that will be used for scanning


static String parallelScanTestTableName = "ParallelScanTest";

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

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


try {

// Clean up the table


deleteTable(parallelScanTestTableName);
createTable(parallelScanTestTableName, 10L, 5L, "Id", "N");

// Upload sample data for scan


uploadSampleProducts(parallelScanTestTableName, scanItemCount);

// Scan the table using multiple threads


parallelScan(parallelScanTestTableName, scanItemLimit, parallelScanThreads);
}
catch (AmazonServiceException ase) {
System.err.println(ase.getMessage());
}
}

private static void parallelScan(String tableName, int itemLimit, int numberOfThreads)


{
System.out.println(
"Scanning " + tableName + " using " + numberOfThreads + " threads " + itemLimit
+ " items at a time");
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);

// Divide DynamoDB table into logical segments


// Create one task for scanning each segment
// Each thread will be scanning one segment
int totalSegments = numberOfThreads;
for (int segment = 0; segment < totalSegments; segment++) {
// Runnable task that will only scan one segment
ScanSegmentTask task = new ScanSegmentTask(tableName, itemLimit, totalSegments,
segment);

// Execute the task


executor.execute(task);
}

shutDownExecutorService(executor);
}

// Runnable task for scanning a single segment of a DynamoDB table


private static class ScanSegmentTask implements Runnable {

// DynamoDB table to scan


private String tableName;

// number of items each scan request should return


private int itemLimit;

// Total number of segments


// Equals to total number of threads scanning the table in parallel
private int totalSegments;

// Segment that will be scanned with by this task


private int segment;

public ScanSegmentTask(String tableName, int itemLimit, int totalSegments, int


segment) {
this.tableName = tableName;

API Version 2012-08-10


486
Amazon DynamoDB Developer Guide
Scanning: Java

this.itemLimit = itemLimit;
this.totalSegments = totalSegments;
this.segment = segment;
}

@Override
public void run() {
System.out.println("Scanning " + tableName + " segment " + segment + " out of "
+ totalSegments
+ " segments " + itemLimit + " items at a time...");
int totalScannedItemCount = 0;

Table table = dynamoDB.getTable(tableName);

try {
ScanSpec spec = new
ScanSpec().withMaxResultSize(itemLimit).withTotalSegments(totalSegments)
.withSegment(segment);

ItemCollection<ScanOutcome> items = table.scan(spec);


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

Item currentItem = null;


while (iterator.hasNext()) {
totalScannedItemCount++;
currentItem = iterator.next();
System.out.println(currentItem.toString());
}

}
catch (Exception e) {
System.err.println(e.getMessage());
}
finally {
System.out.println("Scanned " + totalScannedItemCount + " items from
segment " + segment + " out of "
+ totalSegments + " of " + tableName);
}
}
}

private static void uploadSampleProducts(String tableName, int itemCount) {


System.out.println("Adding " + itemCount + " sample items to " + tableName);
for (int productIndex = 0; productIndex < itemCount; productIndex++) {
uploadProduct(tableName, productIndex);
}
}

private static void uploadProduct(String tableName, int productIndex) {

Table table = dynamoDB.getTable(tableName);

try {
System.out.println("Processing record #" + productIndex);

Item item = new Item().withPrimaryKey("Id", productIndex)


.withString("Title", "Book " + productIndex + " Title").withString("ISBN",
"111-1111111111")
.withStringSet("Authors", new
HashSet<String>(Arrays.asList("Author1"))).withNumber("Price", 2)
.withString("Dimensions", "8.5 x 11.0 x 0.5").withNumber("PageCount", 500)
.withBoolean("InPublication", true).withString("ProductCategory", "Book");
table.putItem(item);

}
catch (Exception e) {

API Version 2012-08-10


487
Amazon DynamoDB Developer Guide
Scanning: Java

System.err.println("Failed to create item " + productIndex + " in " +


tableName);
System.err.println(e.getMessage());
}
}

private static void deleteTable(String tableName) {


try {

Table table = dynamoDB.getTable(tableName);


table.delete();
System.out.println("Waiting for " + tableName + " to be deleted...this may take
a while...");
table.waitForDelete();

}
catch (Exception e) {
System.err.println("Failed to delete table " + tableName);
e.printStackTrace(System.err);
}
}

private static void createTable(String tableName, long readCapacityUnits, long


writeCapacityUnits,
String partitionKeyName, String partitionKeyType) {

createTable(tableName, readCapacityUnits, writeCapacityUnits, partitionKeyName,


partitionKeyType, null, null);
}

private static void createTable(String tableName, long readCapacityUnits, long


writeCapacityUnits,
String partitionKeyName, String partitionKeyType, String sortKeyName, String
sortKeyType) {

try {
System.out.println("Creating table " + tableName);

List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();


keySchema.add(new
KeySchemaElement().withAttributeName(partitionKeyName).withKeyType(KeyType.HASH)); //
Partition

// key

List<AttributeDefinition> attributeDefinitions = new


ArrayList<AttributeDefinition>();
attributeDefinitions
.add(new
AttributeDefinition().withAttributeName(partitionKeyName).withAttributeType(partitionKeyType));

if (sortKeyName != null) {
keySchema.add(new
KeySchemaElement().withAttributeName(sortKeyName).withKeyType(KeyType.RANGE)); // Sort

// key
attributeDefinitions
.add(new
AttributeDefinition().withAttributeName(sortKeyName).withAttributeType(sortKeyType));
}

Table table = dynamoDB.createTable(tableName, keySchema, attributeDefinitions,


new ProvisionedThroughput()

.withReadCapacityUnits(readCapacityUnits).withWriteCapacityUnits(writeCapacityUnits));

API Version 2012-08-10


488
Amazon DynamoDB Developer Guide
Scanning: .NET

System.out.println("Waiting for " + tableName + " to be created...this may take


a while...");
table.waitForActive();

}
catch (Exception e) {
System.err.println("Failed to create table " + tableName);
e.printStackTrace(System.err);
}
}

private static void shutDownExecutorService(ExecutorService executor) {


executor.shutdown();
try {
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
}
catch (InterruptedException e) {
executor.shutdownNow();

// Preserve interrupt status


Thread.currentThread().interrupt();
}
}
}

Scanning Tables and Indexes: .NET


The Scan operation reads all of the items in a table or index in Amazon DynamoDB.

The following are the steps to scan a table using the AWS SDK for .NET low-level API:

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the ScanRequest class and provide scan operation parameters.

The only required parameter is the table name.


3. Execute the Scan method and provide the QueryRequest object that you created in the preceding
step.

The following Reply table stores replies for forum threads.

Example

>Reply ( <emphasis role="underline">Id</emphasis>, <emphasis


role="underline">ReplyDateTime</emphasis>, Message, PostedBy )

The table maintains all the replies for various forum threads. Therefore, the primary key is composed of
both the Id (partition key) and ReplyDateTime (sort key). The following C# code example scans the
entire table. The ScanRequest instance specifies the name of the table to scan.

Example

AmazonDynamoDBClient client = new AmazonDynamoDBClient();

var request = new ScanRequest


{

API Version 2012-08-10


489
Amazon DynamoDB Developer Guide
Scanning: .NET

TableName = "Reply",
};

var response = client.Scan(request);


var result = response.ScanResult;

foreach (Dictionary<string, AttributeValue> item in response.ScanResult.Items)


{
// Process the result.
PrintItem(item);
}

Specifying Optional Parameters


The Scan method supports several optional parameters. For example, you can optionally use a scan filter
to filter the scan result. In a scan filter, you can specify a condition and an attribute name on which you
want the condition evaluated. For more information, see Scan.

The following C# code scans the ProductCatalog table to find items that are priced less than 0. The
sample specifies the following optional parameters:

• A FilterExpression parameter to retrieve only the items priced less than 0 (error condition).
• A ProjectionExpression parameter to specify the attributes to retrieve for items in the query
results.

The following C# example scans the ProductCatalog table to find all items priced less than 0.

Example

var forumScanRequest = new ScanRequest


{
TableName = "ProductCatalog",
// Optional parameters.
ExpressionAttributeValues = new Dictionary<string,AttributeValue> {
{":val", new AttributeValue { N = "0" }}
},
FilterExpression = "Price < :val",
ProjectionExpression = "Id"
};

You can also optionally limit the page size or the number of items per page, by adding the optional
Limit parameter. Each time you execute the Scan method, you get one page of results that has the
specified number of items. To fetch the next page, you execute the Scan method again by providing
the primary key value of the last item in the previous page so that the Scan method can return the next
set of items. You provide this information in the request by setting the ExclusiveStartKey property.
Initially, this property can be null. To retrieve subsequent pages, you must update this property value to
the primary key of the last item in the preceding page.

The following C# code example scans the ProductCatalog table. In the request, it specifies the Limit
and ExclusiveStartKey optional parameters. The do/while loop continues to scan one page at time
until the LastEvaluatedKey returns a null value.

Example

Dictionary<string, AttributeValue> lastKeyEvaluated = null;


do
{
var request = new ScanRequest

API Version 2012-08-10


490
Amazon DynamoDB Developer Guide
Scanning: .NET

{
TableName = "ProductCatalog",
Limit = 10,
ExclusiveStartKey = lastKeyEvaluated
};

var response = client.Scan(request);

foreach (Dictionary<string, AttributeValue> item


in response.Items)
{
PrintItem(item);
}
lastKeyEvaluated = response.LastEvaluatedKey;

} while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0);

Example - Scan Using .NET


The following C# code provides a working example that scans the ProductCatalog table to find items
priced less than 0.

For step-by-step instructions for testing the following sample, see .NET Code Examples (p. 333).

/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class LowLevelScan
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

static void Main(string[] args)


{
try
{
FindProductsForPriceLessThanZero();

Console.WriteLine("Example complete. To continue, press Enter");


Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("To continue, press Enter");
Console.ReadLine();

API Version 2012-08-10


491
Amazon DynamoDB Developer Guide
Scanning: .NET

}
}

private static void FindProductsForPriceLessThanZero()


{
Dictionary<string, AttributeValue> lastKeyEvaluated = null;
do
{
var request = new ScanRequest
{
TableName = "ProductCatalog",
Limit = 2,
ExclusiveStartKey = lastKeyEvaluated,
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":val", new AttributeValue {
N = "0"
}}
},
FilterExpression = "Price < :val",

ProjectionExpression = "Id, Title, Price"


};

var response = client.Scan(request);

foreach (Dictionary<string, AttributeValue> item


in response.Items)
{
Console.WriteLine("\nScanThreadTableUsePaging - printing.....");
PrintItem(item);
}
lastKeyEvaluated = response.LastEvaluatedKey;
} while (lastKeyEvaluated != null && lastKeyEvaluated.Count != 0);

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void PrintItem(


Dictionary<string, AttributeValue> attributeList)
{
foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
{
string attributeName = kvp.Key;
AttributeValue value = kvp.Value;

Console.WriteLine(
attributeName + " " +
(value.S == null ? "" : "S=[" + value.S + "]") +
(value.N == null ? "" : "N=[" + value.N + "]") +
(value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray())
+ "]") +
(value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray())
+ "]")
);
}
Console.WriteLine("************************************************");
}
}

Example - Parallel Scan Using .NET


The following C# code example demonstrates a parallel scan. The program deletes and then re-creates
the ProductCatalog table and then loads the table with data. When the data load is finished, the

API Version 2012-08-10


492
Amazon DynamoDB Developer Guide
Scanning: .NET

program spawns multiple threads and issues parallel Scan requests. Finally, the program prints a
summary of runtime statistics.

For step-by-step instructions for testing the following sample, see .NET Code Examples (p. 333).

/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
class LowLevelParallelScan
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
private static string tableName = "ProductCatalog";
private static int exampleItemCount = 100;
private static int scanItemLimit = 10;
private static int totalSegments = 5;

static void Main(string[] args)


{
try
{
DeleteExampleTable();
CreateExampleTable();
UploadExampleData();
ParallelScanExampleTable();
}
catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
catch (Exception e) { Console.WriteLine(e.Message); }

Console.WriteLine("To continue, press Enter");


Console.ReadLine();
}

private static void ParallelScanExampleTable()


{
Console.WriteLine("\n*** Creating {0} Parallel Scan Tasks to scan {1}",
totalSegments, tableName);
Task[] tasks = new Task[totalSegments];
for (int segment = 0; segment < totalSegments; segment++)
{
int tmpSegment = segment;
Task task = Task.Factory.StartNew(() =>
{

API Version 2012-08-10


493
Amazon DynamoDB Developer Guide
Scanning: .NET

ScanSegment(totalSegments, tmpSegment);
});

tasks[segment] = task;
}

Console.WriteLine("All scan tasks are created, waiting for them to complete.");


Task.WaitAll(tasks);

Console.WriteLine("All scan tasks are completed.");


}

private static void ScanSegment(int totalSegments, int segment)


{
Console.WriteLine("*** Starting to Scan Segment {0} of {1} out of {2} total
segments ***", segment, tableName, totalSegments);
Dictionary<string, AttributeValue> lastEvaluatedKey = null;
int totalScannedItemCount = 0;
int totalScanRequestCount = 0;
do
{
var request = new ScanRequest
{
TableName = tableName,
Limit = scanItemLimit,
ExclusiveStartKey = lastEvaluatedKey,
Segment = segment,
TotalSegments = totalSegments
};

var response = client.Scan(request);


lastEvaluatedKey = response.LastEvaluatedKey;
totalScanRequestCount++;
totalScannedItemCount += response.ScannedCount;
foreach (var item in response.Items)
{
Console.WriteLine("Segment: {0}, Scanned Item with Title: {1}",
segment, item["Title"].S);
}
} while (lastEvaluatedKey.Count != 0);

Console.WriteLine("*** Completed Scan Segment {0} of {1}.


TotalScanRequestCount: {2}, TotalScannedItemCount: {3} ***", segment, tableName,
totalScanRequestCount, totalScannedItemCount);
}

private static void UploadExampleData()


{
Console.WriteLine("\n*** Uploading {0} Example Items to {1} Table***",
exampleItemCount, tableName);
Console.Write("Uploading Items: ");
for (int itemIndex = 0; itemIndex < exampleItemCount; itemIndex++)
{
Console.Write("{0}, ", itemIndex);
CreateItem(itemIndex.ToString());
}
Console.WriteLine();
}

private static void CreateItem(string itemIndex)


{
var request = new PutItemRequest
{
TableName = tableName,
Item = new Dictionary<string, AttributeValue>()
{

API Version 2012-08-10


494
Amazon DynamoDB Developer Guide
Scanning: .NET

{ "Id", new AttributeValue {


N = itemIndex
}},
{ "Title", new AttributeValue {
S = "Book " + itemIndex + " Title"
}},
{ "ISBN", new AttributeValue {
S = "11-11-11-11"
}},
{ "Authors", new AttributeValue {
SS = new List<string>{"Author1", "Author2" }
}},
{ "Price", new AttributeValue {
N = "20.00"
}},
{ "Dimensions", new AttributeValue {
S = "8.5x11.0x.75"
}},
{ "InPublication", new AttributeValue {
BOOL = false
} }
}
};
client.PutItem(request);
}

private static void CreateExampleTable()


{
Console.WriteLine("\n*** Creating {0} Table ***", tableName);
var request = new CreateTableRequest
{
AttributeDefinitions = new List<AttributeDefinition>()
{
new AttributeDefinition
{
AttributeName = "Id",
AttributeType = "N"
}
},
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = "Id",
KeyType = "HASH" //Partition key
}
},
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = 5,
WriteCapacityUnits = 6
},
TableName = tableName
};

var response = client.CreateTable(request);

var result = response;


var tableDescription = result.TableDescription;
Console.WriteLine("{1}: {0} \t ReadsPerSec: {2} \t WritesPerSec: {3}",
tableDescription.TableStatus,
tableDescription.TableName,
tableDescription.ProvisionedThroughput.ReadCapacityUnits,
tableDescription.ProvisionedThroughput.WriteCapacityUnits);

string status = tableDescription.TableStatus;

API Version 2012-08-10


495
Amazon DynamoDB Developer Guide
Scanning: .NET

Console.WriteLine(tableName + " - " + status);

WaitUntilTableReady(tableName);
}

private static void DeleteExampleTable()


{
try
{
Console.WriteLine("\n*** Deleting {0} Table ***", tableName);
var request = new DeleteTableRequest
{
TableName = tableName
};

var response = client.DeleteTable(request);


var result = response;
Console.WriteLine("{0} is being deleted...", tableName);
WaitUntilTableDeleted(tableName);
}
catch (ResourceNotFoundException)
{
Console.WriteLine("{0} Table delete failed: Table does not exist",
tableName);
}
}

private static void WaitUntilTableReady(string tableName)


{
string status = null;
// Let us wait until table is created. Call DescribeTable.
do
{
System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
try
{
var res = client.DescribeTable(new DescribeTableRequest
{
TableName = tableName
});

Console.WriteLine("Table name: {0}, status: {1}",


res.Table.TableName,
res.Table.TableStatus);
status = res.Table.TableStatus;
}
catch (ResourceNotFoundException)
{
// DescribeTable is eventually consistent. So you might
// get resource not found. So we handle the potential exception.
}
} while (status != "ACTIVE");
}

private static void WaitUntilTableDeleted(string tableName)


{
string status = null;
// Let us wait until table is deleted. Call DescribeTable.
do
{
System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
try
{
var res = client.DescribeTable(new DescribeTableRequest
{
TableName = tableName

API Version 2012-08-10


496
Amazon DynamoDB Developer Guide
Working with Indexes

});

Console.WriteLine("Table name: {0}, status: {1}",


res.Table.TableName,
res.Table.TableStatus);
status = res.Table.TableStatus;
}
catch (ResourceNotFoundException)
{
Console.WriteLine("Table name: {0} is not found. It is deleted",
tableName);
return;
}
} while (status == "DELETING");
}
}
}

Improving Data Access with Secondary Indexes


Topics
• Using Global Secondary Indexes in DynamoDB (p. 500)
• Local Secondary Indexes (p. 537)

Amazon DynamoDB provides fast access to items in a table by specifying primary key values. However,
many applications might benefit from having one or more secondary (or alternate) keys available, to
allow efficient access to data with attributes other than the primary key. To address this, you can create
one or more secondary indexes on a table and issue Query or Scan requests against these indexes.

A secondary index is a data structure that contains a subset of attributes from a table, along with an
alternate key to support Query operations. You can retrieve data from the index using a Query, in much
the same way as you use Query with a table. A table can have multiple secondary indexes, which give
your applications access to many different query patterns.
Note
You can also Scan an index, in much the same way as you would Scan a table.

Every secondary index is associated with exactly one table, from which it obtains its data. This is called
the base table for the index. When you create an index, you define an alternate key for the index
(partition key and sort key). You also define the attributes that you want to be projected, or copied, from
the base table into the index. DynamoDB copies these attributes into the index, along with the primary
key attributes from the base table. You can then query or scan the index just as you would query or scan
a table.

Every secondary index is automatically maintained by DynamoDB. When you add, modify, or delete
items in the base table, any indexes on that table are also updated to reflect these changes.

DynamoDB supports two types of secondary indexes:

• Global secondary index — An index with a partition key and a sort key that can be different from
those on the base table. A global secondary index is considered "global" because queries on the index
can span all of the data in the base table, across all partitions. A global secondary index is stored in its
own partition space away from the base table and scales separately from the base table.
• Local secondary index — An index that has the same partition key as the base table, but a different
sort key. A local secondary index is "local" in the sense that every partition of a local secondary index is
scoped to a base table partition that has the same partition key value.

API Version 2012-08-10


497
Amazon DynamoDB Developer Guide
Working with Indexes

You should consider your application's requirements when you determine which type of index to use.
The following table shows the main differences between a global secondary index and a local secondary
index.

Characteristic Global Secondary Index Local Secondary Index

Key Schema The primary key of a global The primary key of a local
secondary index can be either secondary index must be
simple (partition key) or composite (partition key and
composite (partition key and sort key).
sort key).

Key Attributes The index partition key and sort The partition key of the index
key (if present) can be any base is the same attribute as the
table attributes of type string, partition key of the base table.
number, or binary. The sort key can be any base
table attribute of type string,
number, or binary.

Size Restrictions Per Partition There are no size restrictions for For each partition key value, the
Key Value global secondary indexes. total size of all indexed items
must be 10 GB or less.

Online Index Operations Global secondary indexes can Local secondary indexes are
be created at the same time created at the same time that
that you create a table. You you create a table. You cannot
can also add a new global add a local secondary index
secondary index to an existing to an existing table, nor can
table, or delete an existing you delete any local secondary
global secondary index. indexes that currently exist.
For more information, see
Managing Global Secondary
Indexes (p. 508).

Queries and Partitions A global secondary index lets A local secondary index lets you
you query over the entire table, query over a single partition, as
across all partitions. specified by the partition key
value in the query.

Read Consistency Queries on global secondary When you query a local


indexes support eventual secondary index, you can choose
consistency only. either eventual consistency or
strong consistency.

Provisioned Throughput Every global secondary index Queries or scans on a local


Consumption has its own provisioned secondary index consume read
throughput settings for read and capacity units from the base
write activity. Queries or scans table. When you write to a table,
on a global secondary index its local secondary indexes are
consume capacity units from the also updated; these updates
index, not from the base table. consume write capacity units
The same holds true for global from the base table.
secondary index updates due to
table writes.

Projected Attributes With global secondary index If you query or scan a local
queries or scans, you can only secondary index, you can
request the attributes that request attributes that are

API Version 2012-08-10


498
Amazon DynamoDB Developer Guide
Working with Indexes

Characteristic Global Secondary Index Local Secondary Index


are projected into the index. not projected in to the index.
DynamoDB does not fetch any DynamoDB automatically
attributes from the table. fetches those attributes from
the table.

If you want to create more than one table with secondary indexes, you must do so sequentially. For
example, you would create the first table and wait for it to become ACTIVE, create the next table and
wait for it to become ACTIVE, and so on. If you try to concurrently create more than one table with a
secondary index, DynamoDB returns a LimitExceededException.

For each secondary index, you must specify the following:

• The type of index to be created – either a global secondary index or a local secondary index.
• A name for the index. The naming rules for indexes are the same as those for tables, as listed in
Service, Account, and Table Limits in Amazon DynamoDB (p. 959). The name must be unique for the
base table it is associated with, but you can use the same name for indexes that are associated with
different base tables.
• The key schema for the index. Every attribute in the index key schema must be a top-level attribute of
type String, Number, or Binary. Other data types, including documents and sets, are not allowed.
Other requirements for the key schema depend on the type of index:
• For a global secondary index, the partition key can be any scalar attribute of the base table. A sort
key is optional, and it too can be any scalar attribute of the base table.
• For a local secondary index, the partition key must be the same as the base table's partition key, and
the sort key must be a non-key base table attribute.
• Additional attributes, if any, to project from the base table into the index. These attributes are in
addition to the table's key attributes, which are automatically projected into every index. You can
project attributes of any data type, including scalars, documents, and sets.
• The provisioned throughput settings for the index, if necessary:
• For a global secondary index, you must specify read and write capacity unit settings. These
provisioned throughput settings are independent of the base table's settings.
• For a local secondary index, you do not need to specify read and write capacity unit settings. Any
read and write operations on a local secondary index draw from the provisioned throughput settings
of its base table.

For maximum query flexibility, you can create up to 20 global secondary indexes (default limit) and up to
5 local secondary indexes per table.

The limit of global secondary indexes per table is five for the following AWS Regions:

• AWS GovCloud (US-East)


• AWS GovCloud (US-West)
• Europe (Stockholm)

To get a detailed listing of secondary indexes on a table, use the DescribeTable operation.
DescribeTable returns the name, storage size, and item counts for every secondary index on the table.
These values are not updated in real time, but they are refreshed approximately every six hours.

You can access the data in a secondary index using either the Query or Scan operation. You must specify
the name of the base table and the name of the index that you want to use, the attributes to be returned
in the results, and any condition expressions or filters that you want to apply. DynamoDB can return the
results in ascending or descending order.

API Version 2012-08-10


499
Amazon DynamoDB Developer Guide
Global Secondary Indexes

When you delete a table, all of the indexes associated with that table are also deleted.

For best practices, see Best Practices for Using Secondary Indexes in DynamoDB (p. 905).

Using Global Secondary Indexes in DynamoDB


Some applications might need to perform many kinds of queries, using a variety of different attributes as
query criteria. To support these requirements, you can create one or more global secondary indexes and
issue Query requests against these indexes in Amazon DynamoDB.

Topics
• Scenario: Using a Global Secondary Index (p. 500)
• Attribute Projections (p. 503)
• Querying a Global Secondary Index (p. 504)
• Scanning a Global Secondary Index (p. 505)
• Data Synchronization Between Tables and Global Secondary Indexes (p. 505)
• Provisioned Throughput Considerations for Global Secondary Indexes (p. 506)
• Storage Considerations for Global Secondary Indexes (p. 507)
• Managing Global Secondary Indexes (p. 508)
• Working with Global Secondary Indexes: Java (p. 519)
• Working with Global Secondary Indexes: .NET (p. 526)

Scenario: Using a Global Secondary Index


To illustrate, consider a table named GameScores that tracks users and scores for a mobile gaming
application. Each item in GameScores is identified by a partition key (UserId) and a sort key
(GameTitle). The following diagram shows how the items in the table would be organized. (Not all of
the attributes are shown.)

API Version 2012-08-10


500
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Now suppose that you wanted to write a leaderboard application to display top scores for each game. A
query that specified the key attributes (UserId and GameTitle) would be very efficient. However, if the
application needed to retrieve data from GameScores based on GameTitle only, it would need to use
a Scan operation. As more items are added to the table, scans of all the data would become slow and
inefficient. This makes it difficult to answer questions such as the following:

• What is the top score ever recorded for the game Meteor Blasters?
• Which user had the highest score for Galaxy Invaders?
• What was the highest ratio of wins vs. losses?

To speed up queries on non-key attributes, you can create a global secondary index. A global secondary
index contains a selection of attributes from the base table, but they are organized by a primary key that
is different from that of the table. The index key does not need to have any of the key attributes from
the table. It doesn't even need to have the same key schema as a table.

For example, you could create a global secondary index named GameTitleIndex, with a partition
key of GameTitle and a sort key of TopScore. The base table's primary key attributes are always
projected into an index, so the UserId attribute is also present. The following diagram shows what
GameTitleIndex index would look like.

Now you can query GameTitleIndex and easily obtain the scores for Meteor Blasters. The results are
ordered by the sort key values, TopScore. If you set the ScanIndexForward parameter to false, the
results are returned in descending order, so the highest score is returned first.

API Version 2012-08-10


501
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Every global secondary index must have a partition key, and can have an optional sort key. The index key
schema can be different from the base table schema. You could have a table with a simple primary key
(partition key), and create a global secondary index with a composite primary key (partition key and sort
key)—or vice versa. The index key attributes can consist of any top-level String, Number, or Binary
attributes from the base table. Other scalar types, document types, and set types are not allowed.

You can project other base table attributes into the index if you want. When you query the index,
DynamoDB can retrieve these projected attributes efficiently. However, global secondary index queries
cannot fetch attributes from the base table. For example, if you query GameTitleIndex as shown in the
previous diagram, the query could not access any non-key attributes other than TopScore (although the
key attributes GameTitle and UserId would automatically be projected).

In a DynamoDB table, each key value must be unique. However, the key values in a global secondary
index do not need to be unique. To illustrate, suppose that a game named Comet Quest is especially
difficult, with many new users trying but failing to get a score above zero. The following is some data
that could represent this.

UserId GameTitle TopScore

123 Comet Quest 0

201 Comet Quest 0

301 Comet Quest 0

When this data is added to the GameScores table, DynamoDB propagates it to GameTitleIndex. If
we then query the index using Comet Quest for GameTitle and 0 for TopScore, the following data is
returned.

Only the items with the specified key values appear in the response. Within that set of data, the items
are in no particular order.

A global secondary index only tracks data items where its key attributes actually exist. For example,
suppose that you added another new item to the GameScores table, but only provided the required
primary key attributes.

UserId GameTitle

400 Comet Quest

Because you didn't specify the TopScore attribute, DynamoDB would not propagate this item to
GameTitleIndex. Thus, if you queried GameScores for all the Comet Quest items, you would get the
following four items.

API Version 2012-08-10


502
Amazon DynamoDB Developer Guide
Global Secondary Indexes

A similar query on GameTitleIndex would still return three items, rather than four. This is because the
item with the nonexistent TopScore is not propagated to the index.

Attribute Projections
A projection is the set of attributes that is copied from a table into a secondary index. The partition key
and sort key of the table are always projected into the index; you can project other attributes to support
your application's query requirements. When you query an index, Amazon DynamoDB can access any
attribute in the projection as if those attributes were in a table of their own.

When you create a secondary index, you need to specify the attributes that will be projected into the
index. DynamoDB provides three different options for this:

• KEYS_ONLY – Each item in the index consists only of the table partition key and sort key values, plus
the index key values. The KEYS_ONLY option results in the smallest possible secondary index.
• INCLUDE – In addition to the attributes described in KEYS_ONLY, the secondary index will include
other non-key attributes that you specify.
• ALL – The secondary index includes all of the attributes from the source table. Because all of the table
data is duplicated in the index, an ALL projection results in the largest possible secondary index.

In the previous diagram, GameTitleIndex has only one projected attribute: UserId. So while an
application can efficiently determine the UserId of the top scorers for each game using GameTitle and
TopScore in queries, it can't efficiently determine the highest ratio of wins vs. losses for the top scorers.
To do so, it would have to perform an additional query on the base table to fetch the wins and losses for
each of the top scorers. A more efficient way to support queries on this data would be to project these
attributes from the base table into the global secondary index, as shown in this diagram.

API Version 2012-08-10


503
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Because the non-key attributes Wins and Losses are projected into the index, an application can
determine the wins vs. losses ratio for any game, or for any combination of game and user ID.

When you choose the attributes to project into a global secondary index, you must consider the tradeoff
between provisioned throughput costs and storage costs:

• If you need to access just a few attributes with the lowest possible latency, consider projecting only
those attributes into a global secondary index. The smaller the index, the less that it costs to store it,
and the less your write costs are.
• If your application frequently accesses some non-key attributes, you should consider projecting those
attributes into a global secondary index. The additional storage costs for the global secondary index
offset the cost of performing frequent table scans.
• If you need to access most of the non-key attributes on a frequent basis, you can project these
attributes—or even the entire base table— into a global secondary index. This gives you maximum
flexibility. However, your storage cost would increase, or even double.
• If your application needs to query a table infrequently, but must perform many writes or updates
against the data in the table, consider projecting KEYS_ONLY. The global secondary index would be of
minimal size, but would still be available when needed for query activity.

Querying a Global Secondary Index


You can use the Query operation to access one or more items in a global secondary index. The query
must specify the name of the base table and the name of the index that you want to use, the attributes

API Version 2012-08-10


504
Amazon DynamoDB Developer Guide
Global Secondary Indexes

to be returned in the query results, and any query conditions that you want to apply. DynamoDB can
return the results in ascending or descending order.

Consider the following data returned from a Query that requests gaming data for a leaderboard
application.

{
"TableName": "GameScores",
"IndexName": "GameTitleIndex",
"KeyConditionExpression": "GameTitle = :v_title",
"ExpressionAttributeValues": {
":v_title": {"S": "Meteor Blasters"}
},
"ProjectionExpression": "UserId, TopScore",
"ScanIndexForward": false
}

In this query:

• DynamoDB accesses GameTitleIndex, using the GameTitle partition key to locate the index items
for Meteor Blasters. All of the index items with this key are stored adjacent to each other for rapid
retrieval.
• Within this game, DynamoDB uses the index to access all of the user IDs and top scores for this game.
• The results are returned, sorted in descending order because the ScanIndexForward parameter is set
to false.

Scanning a Global Secondary Index


You can use the Scan operation to retrieve all of the data from a global secondary index. You must
provide the base table name and the index name in the request. With a Scan, DynamoDB reads all of
the data in the index and returns it to the application. You can also request that only some of the data
be returned, and that the remaining data should be discarded. To do this, use the FilterExpression
parameter of the Scan operation. For more information, see Filter Expressions for Scan (p. 476).

Data Synchronization Between Tables and Global Secondary


Indexes
DynamoDB automatically synchronizes each global secondary index with its base table. When an
application writes or deletes items in a table, any global secondary indexes on that table are updated
asynchronously, using an eventually consistent model. Applications never write directly to an index.
However, it is important that you understand the implications of how DynamoDB maintains these
indexes.

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

When you create a global secondary index, you specify one or more index key attributes and their data
types. This means that whenever you write an item to the base table, the data types for those attributes
must match the index key schema's data types. In the case of GameTitleIndex, the GameTitle
partition key in the index is defined as a String data type. The TopScore sort key in the index is of
type Number. If you try to add an item to the GameScores table and specify a different data type for
either GameTitle or TopScore, DynamoDB returns a ValidationException because of the data type
mismatch.

When you put or delete items in a table, the global secondary indexes on that table are updated in an
eventually consistent fashion. Changes to the table data are propagated to the global secondary indexes

API Version 2012-08-10


505
Amazon DynamoDB Developer Guide
Global Secondary Indexes

within a fraction of a second, under normal conditions. However, in some unlikely failure scenarios,
longer propagation delays might occur. Because of this, your applications need to anticipate and handle
situations where a query on a global secondary index returns results that are not up to date.

If you write an item to a table, you don't have to specify the attributes for any global secondary
index sort key. Using GameTitleIndex as an example, you would not need to specify a value for the
TopScore attribute to write a new item to the GameScores table. In this case, DynamoDB does not
write any data to the index for this particular item.

A table with many global secondary indexes incurs higher costs for write activity than tables with
fewer indexes. For more information, see Provisioned Throughput Considerations for Global Secondary
Indexes (p. 506).

Provisioned Throughput Considerations for Global Secondary


Indexes
When you create a global secondary index on a provisioned mode table, you must specify read and write
capacity units for the expected workload on that index. The provisioned throughput settings of a global
secondary index are separate from those of its base table. A Query operation on a global secondary
index consumes read capacity units from the index, not the base table. When you put, update or delete
items in a table, the global secondary indexes on that table are also updated. These index updates
consume write capacity units from the index, not from the base table.

For example, if you Query a global secondary index and exceed its provisioned read capacity, your
request will be throttled. If you perform heavy write activity on the table, but a global secondary index
on that table has insufficient write capacity, the write activity on the table will be throttled.
Note
To avoid potential throttling, the provisioned write capacity for a global secondary index should
be equal or greater than the write capacity of the base table because new updates write to both
the base table and global secondary index.

To view the provisioned throughput settings for a global secondary index, use the DescribeTable
operation. Detailed information about all of the table's global secondary indexes is returned.

Read Capacity Units


Global secondary indexes support eventually consistent reads, each of which consume one half of a read
capacity unit. This means that a single global secondary index query can retrieve up to 2 × 4 KB = 8 KB
per read capacity unit.

For global secondary index queries, DynamoDB calculates the provisioned read activity in the same way
as it does for queries against tables. The only difference is that the calculation is based on the sizes of
the index entries, rather than the size of the item in the base table. The number of read capacity units is
the sum of all projected attribute sizes across all of the items returned. The result is then rounded up to
the next 4 KB boundary. For more information about how DynamoDB calculates provisioned throughput
usage, see Managing Settings on DynamoDB Provisioned Capacity Tables (p. 342).

The maximum size of the results returned by a Query operation is 1 MB. This includes the sizes of all the
attribute names and values across all of the items returned.

For example, consider a global secondary index where each item contains 2,000 bytes of data. Now
suppose that you Query this index and that the query returns eight items. The total size of the matching
items is 2,000 bytes × 8 items = 16,000 bytes. This result is then rounded up to the nearest 4 KB
boundary. Because global secondary index queries are eventually consistent, the total cost is 0.5 × (16
KB / 4 KB), or 2 read capacity units.

API Version 2012-08-10


506
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Write Capacity Units


When an item in a table is added, updated, or deleted, and a global secondary index is affected by
this, the global secondary index consumes provisioned write capacity units for the operation. The total
provisioned throughput cost for a write consists of the sum of write capacity units consumed by writing
to the base table and those consumed by updating the global secondary indexes. If a write to a table
does not require a global secondary index update, no write capacity is consumed from the index.

For a table write to succeed, the provisioned throughput settings for the table and all of its global
secondary indexes must have enough write capacity to accommodate the write. Otherwise, the write to
the table is throttled.

The cost of writing an item to a global secondary index depends on several factors:

• If you write a new item to the table that defines an indexed attribute, or you update an existing item
to define a previously undefined indexed attribute, one write operation is required to put the item into
the index.
• If an update to the table changes the value of an indexed key attribute (from A to B), two writes are
required, one to delete the previous item from the index and another write to put the new item into
the index. 
• If an item was present in the index, but a write to the table caused the indexed attribute to be deleted,
one write is required to delete the old item projection from the index.
• If an item is not present in the index before or after the item is updated, there is no additional write
cost for the index.
• If an update to the table only changes the value of projected attributes in the index key schema, but
does not change the value of any indexed key attribute, one write is required to update the values of
the projected attributes into the index.

All of these factors assume that the size of each item in the index is less than or equal to the 1 KB item
size for calculating write capacity units. Larger index entries require additional write capacity units.
You can minimize your write costs by considering which attributes your queries will need to return and
projecting only those attributes into the index.

Storage Considerations for Global Secondary Indexes


When an application writes an item to a table, DynamoDB automatically copies the correct subset of
attributes to any global secondary indexes in which those attributes should appear. Your AWS account
is charged for storage of the item in the base table and also for storage of attributes in any global
secondary indexes on that table.

The amount of space used by an index item is the sum of the following:

• The size in bytes of the base table primary key (partition key and sort key)
• The size in bytes of the index key attribute
• The size in bytes of the projected attributes (if any)
• 100 bytes of overhead per index item

To estimate the storage requirements for a global secondary index, you can estimate the average size
of an item in the index and then multiply by the number of items in the base table that have the global
secondary index key attributes.

If a table contains an item where a particular attribute is not defined, but that attribute is defined as an
index partition key or sort key, DynamoDB doesn't write any data for that item to the index.

API Version 2012-08-10


507
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Managing Global Secondary Indexes


This section describes how to create, modify, and delete global secondary indexes in Amazon DynamoDB.

Topics
• Creating a Table with Global Secondary Indexes (p. 508)
• Describing the Global Secondary Indexes on a Table (p. 508)
• Adding a Global Secondary Index to an Existing Table (p. 509)
• Deleting a Global Secondary Index (p. 511)
• Modifying a Global Secondary Index during Creation (p. 511)
• Detecting and Correcting Index Key Violations (p. 511)

Creating a Table with Global Secondary Indexes


To create a table with one or more global secondary indexes, use the CreateTable operation with the
GlobalSecondaryIndexes parameter. For maximum query flexibility, you can create up to 20 global
secondary indexes (default limit) per table.

You must specify one attribute to act as the index partition key. You can optionally specify another
attribute for the index sort key. It is not necessary for either of these key attributes to be the same as a
key attribute in the table. For example, in the GameScores table (see Using Global Secondary Indexes in
DynamoDB (p. 500)), neither TopScore nor TopScoreDateTime are key attributes. You could create
a global secondary index with a partition key of TopScore and a sort key of TopScoreDateTime. You
might use such an index to determine whether there is a correlation between high scores and the time of
day a game is played.

Each index key attribute must be a scalar of type String, Number, or Binary. (It cannot be a document
or a set.) You can project attributes of any data type into a global secondary index. This includes scalars,
documents, and sets. For a complete list of data types, see Data Types (p. 13).

If using provisioned mode, you must provide ProvisionedThroughput settings for the index,
consisting of ReadCapacityUnits and WriteCapacityUnits. These provisioned throughput settings
are separate from those of the table, but behave in similar ways. For more information, see Provisioned
Throughput Considerations for Global Secondary Indexes (p. 506).

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

Describing the Global Secondary Indexes on a Table


To view the status of all the global secondary indexes on a table, use the DescribeTable operation.
The GlobalSecondaryIndexes portion of the response shows all of the indexes on the table, along
with the current status of each ( IndexStatus).

The IndexStatus for a global secondary index will be one of the following:

• CREATING — The index is currently being created, and is not yet available for use.
• ACTIVE — The index is ready for use, and applications can perform Query operations on the index.
• UPDATING — The provisioned throughput settings of the index are being changed.
• DELETING — The index is currently being deleted, and can no longer be used.

When DynamoDB has finished building a global secondary index, the index status changes from
CREATING to ACTIVE.

API Version 2012-08-10


508
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Adding a Global Secondary Index to an Existing Table


To add a global secondary index to an existing table, use the UpdateTable operation with the
GlobalSecondaryIndexUpdates parameter. You must provide the following:

• An index name. The name must be unique among all the indexes on the table.
• The key schema of the index. You must specify one attribute for the index partition key; you can
optionally specify another attribute for the index sort key. It is not necessary for either of these key
attributes to be the same as a key attribute in the table. The data types for each schema attribute
must be scalar: String, Number, or Binary.
• The attributes to be projected from the table into the index:
• KEYS_ONLY — Each item in the index consists only of the table partition key and sort key values,
plus the index key values.
• INCLUDE — In addition to the attributes described in KEYS_ONLY, the secondary index includes
other non-key attributes that you specify.
• ALL — The index includes all of the attributes from the source table.
• The provisioned throughput settings for the index, consisting of ReadCapacityUnits
and WriteCapacityUnits. These provisioned throughput settings are separate from those of the
table.

You can only create one global secondary index per UpdateTable operation.

Phases of Index Creation

When you add a new global secondary index to an existing table, the table continues to be available
while the index is being built. However, the new index is not available for Query operations until its
status changes from CREATING to ACTIVE.

Behind the scenes, DynamoDB builds the index in two phases:

Resource Allocation

DynamoDB allocates the compute and storage resources that are needed for building the index.

During the resource allocation phase, the IndexStatus attribute is CREATING and the
Backfilling attribute is false. Use the DescribeTable operation to retrieve the status of a table
and all of its secondary indexes.

While the index is in the resource allocation phase, you can't delete the index or delete its parent
table. You also can't modify the provisioned throughput of the index or the table. You cannot add
or delete other indexes on the table. However, you can modify the provisioned throughput of these
other indexes.
Backfilling

For each item in the table, DynamoDB determines which set of attributes to write to the index
based on its projection (KEYS_ONLY, INCLUDE, or ALL). It then writes these attributes to the index.
During the backfill phase, DynamoDB tracks the items that are being added, deleted, or updated
in the table. The attributes from these items are also added, deleted, or updated in the index as
appropriate.

During the backfilling phase, the IndexStatus attribute is set to CREATING, and the Backfilling
attribute is true. Use the DescribeTable operation to retrieve the status of a table and all of its
secondary indexes.

While the index is backfilling, you cannot delete its parent table. However, you can still delete the
index or modify the provisioned throughput of the table and any of its global secondary indexes.

API Version 2012-08-10


509
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Note
During the backfilling phase, some writes of violating items might succeed while others
are rejected. After backfilling, all writes to items that violate the new index's key schema
are rejected. We recommend that you run the Violation Detector tool after the backfill
phase finishes to detect and resolve any key violations that might have occurred. For more
information, see Detecting and Correcting Index Key Violations (p. 511).

While the resource allocation and backfilling phases are in progress, the index is in the CREATING state.
During this time, DynamoDB performs read operations on the table. You are not charged for this read
activity.

When the index build is complete, its status changes to ACTIVE. You can't Query or Scan the index until
it is ACTIVE.
Note
In some cases, DynamoDB can't write data from the table to the index due to index key
violations. This can occur if the data type of an attribute value does not match the data type of
an index key schema data type, or if the size of an attribute exceeds the maximum length for an
index key attribute. Index key violations do not interfere with global secondary index creation.
However, when the index becomes ACTIVE, the violating keys are not present in the index.
DynamoDB provides a standalone tool for finding and resolving these issues. For more
information, see Detecting and Correcting Index Key Violations (p. 511).

Adding a Global Secondary Index to a Large Table

The time required for building a global secondary index depends on several factors, such as the
following:

• The size of the table


• The number of items in the table that qualify for inclusion in the index
• The number of attributes projected into the index
• The provisioned write capacity of the index
• Write activity on the main table during index builds

If you are adding a global secondary index to a very large table, it might take a long time for the creation
process to complete. To monitor progress and determine whether the index has sufficient write capacity,
consult the following Amazon CloudWatch metrics:

• OnlineIndexPercentageProgress
• OnlineIndexConsumedWriteCapacity
• OnlineIndexThrottleEvents

Note
For more information about CloudWatch metrics related to DynamoDB, see DynamoDB
Metrics (p. 856).

If the provisioned write throughput setting on the index is too low, the index build will take longer
to complete. To shorten the time it takes to build a new global secondary index, you can increase its
provisioned write capacity temporarily.
Note
As a general rule, we recommend setting the provisioned write capacity of the index to 1.5 times
the write capacity of the table. This is a good setting for many use cases. However, your actual
requirements might be higher or lower.

API Version 2012-08-10


510
Amazon DynamoDB Developer Guide
Global Secondary Indexes

While an index is being backfilled, DynamoDB uses internal system capacity to read from the table. This
is to minimize the impact of the index creation and to assure that your table does not run out of read
capacity.

However, it is possible that the volume of incoming write activity might exceed the provisioned write
capacity of the index. This is a bottleneck scenario, in which the index creation takes more time because
the write activity to the index is throttled. During the index build, we recommend that you monitor
the Amazon CloudWatch metrics for the index to determine whether its consumed write capacity is
exceeding its provisioned capacity. In a bottleneck scenario, you should increase the provisioned write
capacity on the index to avoid write throttling during the backfill phase.

After the index has been created, you should set its provisioned write capacity to reflect the normal
usage of your application.

Deleting a Global Secondary Index


If you no longer need a global secondary index, you can delete it using the UpdateTable operation.

You can delete only one global secondary index per UpdateTable operation.

While the global secondary index is being deleted, there is no effect on any read or write activity in the
parent table. While the deletion is in progress, you can still modify the provisioned throughput on other
indexes.
Note
When you delete a table using the DeleteTable action, all of the global secondary indexes on
that table are also deleted.

Modifying a Global Secondary Index during Creation


While an index is being built, you can use the DescribeTable operation to determine what phase it
is in. The description for the index includes a Boolean attribute, Backfilling, to indicate whether
DynamoDB is currently loading the index with items from the table. If Backfilling is true, the resource
allocation phase is complete and the index is now backfilling.

While the backfill is proceeding, you can update the provisioned throughput parameters for the index.
You might decide to do this in order to speed up the index build: You can increase the write capacity of
the index while it is being built, and then decrease it afterward. To modify the provisioned throughput
settings of the index, use the UpdateTable operation. The index status changes to UPDATING, and
Backfilling is true until the index is ready for use.

During the backfilling phase, you can delete the index that is being created. During this phase, you can't
add or delete other indexes on the table.
Note
For indexes that were created as part of a CreateTable operation, the Backfilling attribute
does not appear in the DescribeTable output. For more information, see Phases of Index
Creation (p. 509).

Detecting and Correcting Index Key Violations


During the backfill phase of global secondary index creation, Amazon DynamoDB examines each item in
the table to determine whether it is eligible for inclusion in the index. Some items might not be eligible
because they would cause index key violations. In these cases, the items remain in the table, but the
index doesn't have a corresponding entry for that item.

An index key violation occurs in the following situations:

• There is a data type mismatch between an attribute value and the index key schema data type. For
example, suppose that one of the items in the GameScores table had a TopScore value of type

API Version 2012-08-10


511
Amazon DynamoDB Developer Guide
Global Secondary Indexes

String. If you added a global secondary index with a partition key of TopScore, of type Number, the
item from the table would violate the index key.
• An attribute value from the table exceeds the maximum length for an index key attribute. The
maximum length of a partition key is 2048 bytes, and the maximum length of a sort key is 1024 bytes.
If any of the corresponding attribute values in the table exceed these limits, the item from the table
would violate the index key.

If an index key violation occurs, the backfill phase continues without interruption. However, any violating
items are not included in the index. After the backfill phase completes, all writes to items that violate the
new index's key schema will be rejected.

To identify and fix attribute values in a table that violate an index key, use the Violation Detector tool. To
run Violation Detector, you create a configuration file that specifies the name of a table to be scanned,
the names and data types of the global secondary index partition key and sort key, and what actions to
take if any index key violations are found. Violation Detector can run in one of two different modes:

• Detection mode — Detect index key violations. Use detection mode to report the items in the table
that would cause key violations in a global secondary index. (You can optionally request that these
violating table items be deleted immediately when they are found.) The output from detection mode
is written to a file, which you can use for further analysis.
• Correction mode — Correct index key violations. In correction mode, Violation Detector reads an input
file with the same format as the output file from detection mode. Correction mode reads the records
from the input file and, for each record, it either deletes or updates the corresponding items in the
table. (Note that if you choose to update the items, you must edit the input file and set appropriate
values for these updates.)

Downloading and Running Violation Detector

Violation Detector is available as an executable Java Archive (.jar file), and runs on Windows, macOS, or
Linux computers. Violation Detector requires Java 1.7 (or later) and Apache Maven.

• Download Violation Detector from GitHub

Follow the instructions in the README.md file to download and install Violation Detector using Maven.

To start Violation Detector, go to the directory where you have built ViolationDetector.java and
enter the following command.

java -jar ViolationDetector.jar [options]

The Violation Detector command line accepts the following options:

• -h | --help — Prints a usage summary and options for Violation Detector.


• -p | --configFilePath value — The fully qualified name of a Violation Detector configuration
file. For more information, see The Violation Detector Configuration File (p. 513).
• -t | --detect value — Detect index key violations in the table, and write them to the Violation
Detector output file. If the value of this parameter is set to keep, items with key violations are not
modified. If the value is set to delete, items with key violations are deleted from the table.
• -c | --correct value — Read index key violations from an input file, and take corrective actions
on the items in the table. If the value of this parameter is set to update, items with key violations are
updated with new, non-violating values. If the value is set to delete, items with key violations are
deleted from the table.

API Version 2012-08-10


512
Amazon DynamoDB Developer Guide
Global Secondary Indexes

The Violation Detector Configuration File


At runtime, the Violation Detector tool requires a configuration file. The parameters in this file determine
which DynamoDB resources that Violation Detector can access, and how much provisioned throughput it
can consume. The following table describes these parameters.

Parameter Name Description Required?

awsCredentialsFile The fully qualified name of a file Yes


containing your AWS credentials.
The credentials file must be in
the following format:

accessKey
= access_key_id_goes_here
secretKey
= secret_key_goes_here

dynamoDBRegion The AWS Region in which the Yes


table resides. For example: us-
west-2.

tableName The name of the DynamoDB Yes


table to be scanned.

gsiHashKeyName The name of the index partition Yes


key.

gsiHashKeyType The data type of the index Yes


partition key—String, Number,
or Binary:

S | N | B

gsiRangeKeyName The name of the index sort key. No


Do not specify this parameter
if the index only has a simple
primary key (partition key).

gsiRangeKeyType The data type of the index No


sort key—String, Number, or
Binary:

S | N | B

Do not specify this parameter


if the index only has a simple
primary key (partition key).

recordDetails Whether to write the full details No


of index key violations to the
output file. If set to true (the
default), full information about
the violating items is reported.
If set to false, only the number
of violations is reported.

Whether to write the values


recordGsiValueInViolationRecord No
of the violating index keys to

API Version 2012-08-10


513
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Parameter Name Description Required?


the output file. If set to true
(default), the key values are
reported. If set to false, the
key values are not reported.

detectionOutputPath The full path of the Violation No


Detector output file. This
parameter supports writing to
a local directory or to Amazon
Simple Storage Service (Amazon
S3). The following are examples:

detectionOutputPath
= //local/path/
filename.csv

detectionOutputPath =
s3://bucket/filename.csv

Information in the output file


appears in comma-separated
values (CSV) format. If you don't
set detectionOutputPath,
the output file is named
violation_detection.csv
and is written to your current
working directory.

numOfSegments The number of parallel scan No


segments to be used when
Violation Detector scans the
table. The default value is
1, meaning that the table is
scanned in a sequential manner.
If the value is 2 or higher, then
Violation Detector divides the
table into that many logical
segments and an equal number
of scan threads.

The maximum setting for


numOfSegments is 4096.

For larger tables, a parallel


scan is generally faster than
a sequential scan. In addition,
if the table is large enough
to span multiple partitions, a
parallel scan distributes its read
activity evenly across multiple
partitions.
For more information about
parallel scans in DynamoDB, see
Parallel Scan (p. 480).

API Version 2012-08-10


514
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Parameter Name Description Required?

numOfViolations The upper limit of index key No


violations to write to the output
file. If set to -1 (the default),
the entire table is scanned. If
set to a positive integer, then
Violation Detector stops after
it encounters that number of
violations.

numOfRecords The number of items in the No


table to be scanned. If set to -1
(the default), the entire table
is scanned. If set to a positive
integer, Violation Detector stops
after it scans that many items in
the table.

readWriteIOPSPercent Regulates the percentage of No


provisioned read capacity units
that are consumed during the
table scan. Valid values range
from 1 to 100. The default
value (25) means that Violation
Detector will consume no
more than 25% of the table's
provisioned read throughput.

correctionInputPath The full path of the Violation No


Detector correction input file.
If you run Violation Detector in
correction mode, the contents
of this file are used to modify
or delete data items in the
table that violate the global
secondary index.

The format of the


correctionInputPath file
is the same as that of the
detectionOutputPath file.
This lets you process the output
from detection mode as input in
correction mode.

API Version 2012-08-10


515
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Parameter Name Description Required?

correctionOutputPath The full path of the Violation No


Detector correction output file.
This file is created only if there
are update errors.

This parameter supports writing


to a local directory or to Amazon
S3. The following are examples:

correctionOutputPath
= //local/path/
filename.csv

correctionOutputPath =
s3://bucket/filename.csv

Information in the output


file appears in CSV
format. If you don't set
correctionOutputPath,
the output file is named
violation_update_errors.csv
and is written to your current
working directory.

Detection

To detect index key violations, use Violation Detector with the --detect command line option. To show
how this option works, consider the ProductCatalog table shown in Creating Tables and Loading Data
for Code Examples in DynamoDB (p. 326). The following is a list of items in the table. Only the primary
key (Id) and the Price attribute are shown.

Id (Primary Key) Price

101 5

102 20

103 200

201 100

202 200

203 300

204 400

205 500

All of the values for Price are of type Number. However, because DynamoDB is schemaless, it is possible
to add an item with a non-numeric Price. For example, suppose that you add another item to the
ProductCatalog table.

API Version 2012-08-10


516
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Id (Primary Key) Price

999 "Hello"

The table now has a total of nine items.

Now you add a new global secondary index to the table: PriceIndex. The primary key for this index
is a partition key, Price, which is of type Number. After the index has been built, it will contain eight
items—but the ProductCatalog table has nine items. The reason for this discrepancy is that the value
"Hello" is of type String, but PriceIndex has a primary key of type Number. The String value
violates the global secondary index key, so it is not present in the index.

To use Violation Detector in this scenario, you first create a configuration file such as the following.

# Properties file for violation detection tool configuration.


# Parameters that are not specified will use default values.

awsCredentialsFile = /home/alice/credentials.txt
dynamoDBRegion = us-west-2
tableName = ProductCatalog
gsiHashKeyName = Price
gsiHashKeyType = N
recordDetails = true
recordGsiValueInViolationRecord = true
detectionOutputPath = ./gsi_violation_check.csv
correctionInputPath = ./gsi_violation_check.csv
numOfSegments = 1
readWriteIOPSPercent = 40

Next, you run Violation Detector as in the following example.

$ java -jar ViolationDetector.jar --configFilePath config.txt --detect keep

Violation detection started: sequential scan, Table name: ProductCatalog, GSI name:
PriceIndex
Progress: Items scanned in total: 9, Items scanned by this thread: 9, Violations
found by this thread: 1, Violations deleted by this thread: 0
Violation detection finished: Records scanned: 9, Violations found: 1, Violations deleted:
0, see results at: ./gsi_violation_check.csv

If the recordDetails config parameter is set to true, Violation Detector writes details of each
violation to the output file, as in the following example.

Table Hash Key,GSI Hash Key Value,GSI Hash Key Violation Type,GSI Hash Key Violation
Description,GSI Hash Key Update Value(FOR USER),Delete Blank Attributes When Updating?(Y/
N)

999,"{""S"":""Hello""}",Type Violation,Expected: N Found: S,,

The output file is in CSV format. The first line in the file is a header, followed by one record per item that
violates the index key. The fields of these violation records are as follows:

• Table Hash Key — The partition key value of the item in the table.
• Table Range Key — The sort key value of the item in the table.
• GSI Hash Key Value — The partition key value of the global secondary index.

API Version 2012-08-10


517
Amazon DynamoDB Developer Guide
Global Secondary Indexes

• GSI Hash Key Violation Type — Either Type Violation or Size Violation.
• GSI Hash Key Violation Description — The cause of the violation.
• GSI Hash Key Update Value(FOR USER) — In correction mode, a new user-supplied value for the
attribute.
• GSI Range Key Value — The sort key value of the global secondary index.
• GSI Range Key Violation Type — Either Type Violation or Size Violation.
• GSI Range Key Violation Description — The cause of the violation.
• GSI Range Key Update Value(FOR USER) — In correction mode, a new user-supplied value for the
attribute.
• Delete Blank Attribute When Updating(Y/N) — In correction mode, determines whether to delete (Y)
or keep (N) the violating item in the table—but only if either of the following fields are blank:
• GSI Hash Key Update Value(FOR USER)
• GSI Range Key Update Value(FOR USER)

If either of these fields are non-blank, then Delete Blank Attribute When Updating(Y/N) has
no effect.

Note
The output format might vary, depending on the configuration file and command line options.
For example, if the table has a simple primary key (without a sort key), no sort key fields will be
present in the output.
The violation records in the file might not be in sorted order.

Correction

To correct index key violations, use Violation Detector with the --correct command line option.
In correction mode, Violation Detector reads the input file specified by the correctionInputPath
parameter. This file has the same format as the detectionOutputPath file, so that you can use the
output from detection as input for correction.

Violation Detector provides two different ways to correct index key violations:

• Delete violations — Delete the table items that have violating attribute values.
• Update violations — Update the table items, replacing the violating attributes with non-violating
values.

In either case, you can use the output file from detection mode as input for correction mode.

Continuing with the ProductCatalog example, suppose that you want to delete the violating item
from the table. To do this, you use the following command line.

$ java -jar ViolationDetector.jar --configFilePath config.txt --correct delete

At this point, you are asked to confirm whether you want to delete the violating items.

Are you sure to delete all violations on the table?y/n


y
Confirmed, will delete violations on the table...
Violation correction from file started: Reading records from file: ./
gsi_violation_check.csv, will delete these records from table.
Violation correction from file finished: Violations delete: 1, Violations Update: 0

API Version 2012-08-10


518
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Now both ProductCatalog and PriceIndex have the same number of items.

Working with Global Secondary Indexes: Java


You can use the AWS SDK for Java Document API to create an Amazon DynamoDB table with one or
more global secondary indexes, describe the indexes on the table, and perform queries using the indexes.

The following are the common steps for table operations.

1. Create an instance of the DynamoDB class.


2. Provide the required and optional parameters for the operation by creating the corresponding
request objects.
3. Call the appropriate method provided by the client that you created in the preceding step.

Topics
• Create a Table with a Global Secondary Index (p. 519)
• Describe a Table with a Global Secondary Index (p. 520)
• Query a Global Secondary Index (p. 521)
• Example: Global Secondary Indexes Using the AWS SDK for Java Document API (p. 522)

Create a Table with a Global Secondary Index


You can create global secondary indexes at the same time that you create a table. To do this, use
CreateTable and provide your specifications for one or more global secondary indexes. The following
Java code example creates a table to hold information about weather data. The partition key is
Location and the sort key is Date. A global secondary index named PrecipIndex allows fast access to
precipitation data for various locations.

The following are the steps to create a table with a global secondary index, using the DynamoDB
document API.

1. Create an instance of the DynamoDB class.


2. Create an instance of the CreateTableRequest class to provide the request information.

You must provide the table name, its primary key, and the provisioned throughput values. For the
global secondary index, you must provide the index name, its provisioned throughput settings,
the attribute definitions for the index sort key, the key schema for the index, and the attribute
projection.
3. Call the createTable method by providing the request object as a parameter.

The following Java code example demonstrates the preceding steps. The code creates a table
(WeatherData) with a global secondary index (PrecipIndex). The index partition key is Date and its
sort key is Precipitation. All of the table attributes are projected into the index. Users can query this
index to obtain weather data for a particular date, optionally sorting the data by precipitation amount.

Because Precipitation is not a key attribute for the table, it is not required. However, WeatherData
items without Precipitation do not appear in PrecipIndex.

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

// Attribute definitions
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();

API Version 2012-08-10


519
Amazon DynamoDB Developer Guide
Global Secondary Indexes

attributeDefinitions.add(new AttributeDefinition()
.withAttributeName("Location")
.withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
.withAttributeName("Date")
.withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
.withAttributeName("Precipitation")
.withAttributeType("N"));

// Table key schema


ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new KeySchemaElement()
.withAttributeName("Location")
.withKeyType(KeyType.HASH)); //Partition key
tableKeySchema.add(new KeySchemaElement()
.withAttributeName("Date")
.withKeyType(KeyType.RANGE)); //Sort key

// PrecipIndex
GlobalSecondaryIndex precipIndex = new GlobalSecondaryIndex()
.withIndexName("PrecipIndex")
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits((long) 10)
.withWriteCapacityUnits((long) 1))
.withProjection(new Projection().withProjectionType(ProjectionType.ALL));

ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

indexKeySchema.add(new KeySchemaElement()
.withAttributeName("Date")
.withKeyType(KeyType.HASH)); //Partition key
indexKeySchema.add(new KeySchemaElement()
.withAttributeName("Precipitation")
.withKeyType(KeyType.RANGE)); //Sort key

precipIndex.setKeySchema(indexKeySchema);

CreateTableRequest createTableRequest = new CreateTableRequest()


.withTableName("WeatherData")
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits((long) 5)
.withWriteCapacityUnits((long) 1))
.withAttributeDefinitions(attributeDefinitions)
.withKeySchema(tableKeySchema)
.withGlobalSecondaryIndexes(precipIndex);

Table table = dynamoDB.createTable(createTableRequest);


System.out.println(table.getDescription());

You must wait until DynamoDB creates the table and sets the table status to ACTIVE. After that, you can
begin putting data items into the table.

Describe a Table with a Global Secondary Index


To get information about global secondary indexes on a table, use DescribeTable. For each index, you
can access its name, key schema, and projected attributes.

The following are the steps to access global secondary index information a table.

1. Create an instance of the DynamoDB class.


2. Create an instance of the Table class to represent the index you want to work with.
3. Call the describe method on the Table object.

API Version 2012-08-10


520
Amazon DynamoDB Developer Guide
Global Secondary Indexes

The following Java code example demonstrates the preceding steps.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

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


TableDescription tableDesc = table.describe();

Iterator<GlobalSecondaryIndexDescription> gsiIter =
tableDesc.getGlobalSecondaryIndexes().iterator();
while (gsiIter.hasNext()) {
GlobalSecondaryIndexDescription gsiDesc = gsiIter.next();
System.out.println("Info for index "
+ gsiDesc.getIndexName() + ":");

Iterator<KeySchemaElement> kseIter = gsiDesc.getKeySchema().iterator();


while (kseIter.hasNext()) {
KeySchemaElement kse = kseIter.next();
System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
}
Projection projection = gsiDesc.getProjection();
System.out.println("\tThe projection type is: "
+ projection.getProjectionType());
if (projection.getProjectionType().toString().equals("INCLUDE")) {
System.out.println("\t\tThe non-key projected attributes are: "
+ projection.getNonKeyAttributes());
}
}

Query a Global Secondary Index


You can use Query on a global secondary index, in much the same way you Query a table. You need to
specify the index name, the query criteria for the index partition key and sort key (if present), and the
attributes that you want to return. In this example, the index is PrecipIndex, which has a partition
key of Date and a sort key of Precipitation. The index query returns all of the weather data for a
particular date, where the precipitation is greater than zero.

The following are the steps to query a global secondary index using the AWS SDK for Java Document
API.

1. Create an instance of the DynamoDB class.


2. Create an instance of the Table class to represent the index you want to work with.
3. Create an instance of the Index class for the index you want to query.
4. Call the query method on the Index object.

The attribute name Date is a DynamoDB reserved word. Therefore, you must use an expression attribute
name as a placeholder in the KeyConditionExpression.

The following Java code example demonstrates the preceding steps.

Example

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


DynamoDB dynamoDB = new DynamoDB(client);

API Version 2012-08-10


521
Amazon DynamoDB Developer Guide
Global Secondary Indexes

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


Index index = table.getIndex("PrecipIndex");

QuerySpec spec = new QuerySpec()


.withKeyConditionExpression("#d = :v_date and Precipitation = :v_precip")
.withNameMap(new NameMap()
.with("#d", "Date"))
.withValueMap(new ValueMap()
.withString(":v_date","2013-08-10")
.withNumber(":v_precip",0));

ItemCollection<QueryOutcome> items = index.query(spec);


Iterator<Item> iter = items.iterator();
while (iter.hasNext()) {
System.out.println(iter.next().toJSONPretty());
}

Example: Global Secondary Indexes Using the AWS SDK for Java Document API
The following Java code example shows how to work with global secondary indexes. The example
creates a table named Issues, which might be used in a simple bug tracking system for software
development. The partition key is IssueId and the sort key is Title. There are three global secondary
indexes on this table:

• CreateDateIndex — The partition key is CreateDate and the sort key is IssueId. In addition to
the table keys, the attributes Description and Status are projected into the index.
• TitleIndex — The partition key is Title and the sort key is IssueId. No attributes other than the
table keys are projected into the index.
• DueDateIndex — The partition key is DueDate, and there is no sort key. All of the table attributes are
projected into the index.

After the Issues table is created, the program loads the table with data representing software bug
reports. It then queries the data using the global secondary indexes. Finally, the program deletes the
Issues table.

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.document;

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;

API Version 2012-08-10


522
Amazon DynamoDB Developer Guide
Global Secondary Indexes

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
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;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;

public class DocumentAPIGlobalSecondaryIndexExample {

static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();


static DynamoDB dynamoDB = new DynamoDB(client);

public static String tableName = "Issues";

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

createTable();
loadData();

queryIndex("CreateDateIndex");
queryIndex("TitleIndex");
queryIndex("DueDateIndex");

deleteTable(tableName);

public static void createTable() {

// Attribute definitions
ArrayList<AttributeDefinition> attributeDefinitions = new
ArrayList<AttributeDefinition>();

attributeDefinitions.add(new
AttributeDefinition().withAttributeName("IssueId").withAttributeType("S"));
attributeDefinitions.add(new
AttributeDefinition().withAttributeName("Title").withAttributeType("S"));
attributeDefinitions.add(new
AttributeDefinition().withAttributeName("CreateDate").withAttributeType("S"));
attributeDefinitions.add(new
AttributeDefinition().withAttributeName("DueDate").withAttributeType("S"));

// Key schema for table


ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new
KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.HASH)); // Partition

// key
tableKeySchema.add(new
KeySchemaElement().withAttributeName("Title").withKeyType(KeyType.RANGE)); // Sort

// key

// Initial provisioned throughput settings for the indexes


ProvisionedThroughput ptIndex = new
ProvisionedThroughput().withReadCapacityUnits(1L)

API Version 2012-08-10


523
Amazon DynamoDB Developer Guide
Global Secondary Indexes

.withWriteCapacityUnits(1L);

// CreateDateIndex
GlobalSecondaryIndex createDateIndex = new
GlobalSecondaryIndex().withIndexName("CreateDateIndex")
.withProvisionedThroughput(ptIndex)
.withKeySchema(new
KeySchemaElement().withAttributeName("CreateDate").withKeyType(KeyType.HASH), // Partition

// key
new
KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.RANGE)) // Sort

// key
.withProjection(
new
Projection().withProjectionType("INCLUDE").withNonKeyAttributes("Description", "Status"));

// TitleIndex
GlobalSecondaryIndex titleIndex = new
GlobalSecondaryIndex().withIndexName("TitleIndex")
.withProvisionedThroughput(ptIndex)
.withKeySchema(new
KeySchemaElement().withAttributeName("Title").withKeyType(KeyType.HASH), // Partition

// key
new
KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.RANGE)) // Sort

// key
.withProjection(new Projection().withProjectionType("KEYS_ONLY"));

// DueDateIndex
GlobalSecondaryIndex dueDateIndex = new
GlobalSecondaryIndex().withIndexName("DueDateIndex")
.withProvisionedThroughput(ptIndex)
.withKeySchema(new
KeySchemaElement().withAttributeName("DueDate").withKeyType(KeyType.HASH)) // Partition

// key
.withProjection(new Projection().withProjectionType("ALL"));

CreateTableRequest createTableRequest = new


CreateTableRequest().withTableName(tableName)
.withProvisionedThroughput(
new ProvisionedThroughput().withReadCapacityUnits((long)
1).withWriteCapacityUnits((long) 1))
.withAttributeDefinitions(attributeDefinitions).withKeySchema(tableKeySchema)
.withGlobalSecondaryIndexes(createDateIndex, titleIndex, dueDateIndex);

System.out.println("Creating table " + tableName + "...");


dynamoDB.createTable(createTableRequest);

// Wait for table to become active


System.out.println("Waiting for " + tableName + " to become ACTIVE...");
try {
Table table = dynamoDB.getTable(tableName);
table.waitForActive();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void queryIndex(String indexName) {

API Version 2012-08-10


524
Amazon DynamoDB Developer Guide
Global Secondary Indexes

Table table = dynamoDB.getTable(tableName);

System.out.println("\n***********************************************************
\n");
System.out.print("Querying index " + indexName + "...");

Index index = table.getIndex(indexName);

ItemCollection<QueryOutcome> items = null;

QuerySpec querySpec = new QuerySpec();

if (indexName == "CreateDateIndex") {
System.out.println("Issues filed on 2013-11-01");
querySpec.withKeyConditionExpression("CreateDate = :v_date and
begins_with(IssueId, :v_issue)")
.withValueMap(new ValueMap().withString(":v_date",
"2013-11-01").withString(":v_issue", "A-"));
items = index.query(querySpec);
}
else if (indexName == "TitleIndex") {
System.out.println("Compilation errors");
querySpec.withKeyConditionExpression("Title = :v_title and
begins_with(IssueId, :v_issue)")
.withValueMap(new ValueMap().withString(":v_title", "Compilation
error").withString(":v_issue", "A-"));
items = index.query(querySpec);
}
else if (indexName == "DueDateIndex") {
System.out.println("Items that are due on 2013-11-30");
querySpec.withKeyConditionExpression("DueDate = :v_date")
.withValueMap(new ValueMap().withString(":v_date", "2013-11-30"));
items = index.query(querySpec);
}
else {
System.out.println("\nNo valid index name provided");
return;
}

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

System.out.println("Query: printing results...");

while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}

public static void deleteTable(String tableName) {

System.out.println("Deleting table " + tableName + "...");

Table table = dynamoDB.getTable(tableName);


table.delete();

// Wait for table to be deleted


System.out.println("Waiting for " + tableName + " to be deleted...");
try {
table.waitForDelete();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}

API Version 2012-08-10


525
Amazon DynamoDB Developer Guide
Global Secondary Indexes

public static void loadData() {

System.out.println("Loading data into table " + tableName + "...");

// IssueId, Title,
// Description,
// CreateDate, LastUpdateDate, DueDate,
// Priority, Status

putItem("A-101", "Compilation error", "Can't compile Project X - bad version


number. What does this mean?",
"2013-11-01", "2013-11-02", "2013-11-10", 1, "Assigned");

putItem("A-102", "Can't read data file", "The main data file is missing, or the
permissions are incorrect",
"2013-11-01", "2013-11-04", "2013-11-30", 2, "In progress");

putItem("A-103", "Test failure", "Functional test of Project X produces errors",


"2013-11-01", "2013-11-02",
"2013-11-10", 1, "In progress");

putItem("A-104", "Compilation error", "Variable 'messageCount' was not


initialized.", "2013-11-15",
"2013-11-16", "2013-11-30", 3, "Assigned");

putItem("A-105", "Network issue", "Can't ping IP address 127.0.0.1. Please fix


this.", "2013-11-15",
"2013-11-16", "2013-11-19", 5, "Assigned");

public static void putItem(

String issueId, String title, String description, String createDate, String


lastUpdateDate, String dueDate,
Integer priority, String status) {

Table table = dynamoDB.getTable(tableName);

Item item = new Item().withPrimaryKey("IssueId", issueId).withString("Title",


title)
.withString("Description", description).withString("CreateDate", createDate)
.withString("LastUpdateDate", lastUpdateDate).withString("DueDate", dueDate)
.withNumber("Priority", priority).withString("Status", status);

table.putItem(item);
}

Working with Global Secondary Indexes: .NET


You can use the AWS SDK for .NET low-level API to create an Amazon DynamoDB table with one or more
global secondary indexes, describe the indexes on the table, and perform queries using the indexes.
These operations map to the corresponding DynamoDB operations. For more information, see the
Amazon DynamoDB API Reference.

The following are the common steps for table operations using the .NET low-level API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Provide the required and optional parameters for the operation by creating the corresponding
request objects.

API Version 2012-08-10


526
Amazon DynamoDB Developer Guide
Global Secondary Indexes

For example, create a CreateTableRequest object to create a table and QueryRequest object to
query a table or an index.
3. Execute the appropriate method provided by the client that you created in the preceding step.

Topics
• Create a Table with a Global Secondary Index (p. 527)
• Describe a Table with a Global Secondary Index (p. 528)
• Query a Global Secondary Index (p. 529)
• Example: Global Secondary Indexes Using the AWS SDK for .NET Low-Level API (p. 530)

Create a Table with a Global Secondary Index


You can create global secondary indexes at the same time that you create a table. To do this, use
CreateTable and provide your specifications for one or more global secondary indexes. The following
C# code example creates a table to hold information about weather data. The partition key is Location
and the sort key is Date. A global secondary index named PrecipIndex allows fast access to
precipitation data for various locations.

The following are the steps to create a table with a global secondary index, using the .NET low-level API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the CreateTableRequest class to provide the request information.

You must provide the table name, its primary key, and the provisioned throughput values. For the
global secondary index, you must provide the index name, its provisioned throughput settings,
the attribute definitions for the index sort key, the key schema for the index, and the attribute
projection.
3. Execute the CreateTable method by providing the request object as a parameter.

The following C# code example demonstrates the preceding steps. The code creates a table
(WeatherData) with a global secondary index (PrecipIndex). The index partition key is Date and its
sort key is Precipitation. All of the table attributes are projected into the index. Users can query this
index to obtain weather data for a particular date, optionally sorting the data by precipitation amount.

Because Precipitation is not a key attribute for the table, it is not required. However, WeatherData
items without Precipitation do not appear in PrecipIndex.

client = new AmazonDynamoDBClient();


string tableName = "WeatherData";

// Attribute definitions
var attributeDefinitions = new List<AttributeDefinition>()
{
{new AttributeDefinition{
AttributeName = "Location",
AttributeType = "S"}},
{new AttributeDefinition{
AttributeName = "Date",
AttributeType = "S"}},
{new AttributeDefinition(){
AttributeName = "Precipitation",
AttributeType = "N"}
}
};

// Table key schema

API Version 2012-08-10


527
Amazon DynamoDB Developer Guide
Global Secondary Indexes

var tableKeySchema = new List<KeySchemaElement>()


{
{new KeySchemaElement {
AttributeName = "Location",
KeyType = "HASH"}}, //Partition key
{new KeySchemaElement {
AttributeName = "Date",
KeyType = "RANGE"} //Sort key
}
};

// PrecipIndex
var precipIndex = new GlobalSecondaryIndex
{
IndexName = "PrecipIndex",
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = (long)10,
WriteCapacityUnits = (long)1
},
Projection = new Projection { ProjectionType = "ALL" }
};

var indexKeySchema = new List<KeySchemaElement> {


{new KeySchemaElement { AttributeName = "Date", KeyType = "HASH"}}, //Partition key
{new KeySchemaElement{AttributeName = "Precipitation",KeyType = "RANGE"}} //Sort key
};

precipIndex.KeySchema = indexKeySchema;

CreateTableRequest createTableRequest = new CreateTableRequest


{
TableName = tableName,
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = (long)5,
WriteCapacityUnits = (long)1
},
AttributeDefinitions = attributeDefinitions,
KeySchema = tableKeySchema,
GlobalSecondaryIndexes = { precipIndex }
};

CreateTableResponse response = client.CreateTable(createTableRequest);


Console.WriteLine(response.CreateTableResult.TableDescription.TableName);
Console.WriteLine(response.CreateTableResult.TableDescription.TableStatus);

You must wait until DynamoDB creates the table and sets the table status to ACTIVE. After that, you can
begin putting data items into the table.

Describe a Table with a Global Secondary Index


To get information about global secondary indexes on a table, use DescribeTable. For each index, you
can access its name, key schema, and projected attributes.

The following are the steps to access global secondary index information for a table using the .NET low-
level API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Execute the describeTable method by providing the request object as a parameter.

Create an instance of the DescribeTableRequest class to provide the request information. You
must provide the table name.

API Version 2012-08-10


528
Amazon DynamoDB Developer Guide
Global Secondary Indexes

3.

The following C# code example demonstrates the preceding steps.

Example

client = new AmazonDynamoDBClient();


string tableName = "WeatherData";

DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest { TableName


= tableName});

List<GlobalSecondaryIndexDescription> globalSecondaryIndexes =
response.DescribeTableResult.Table.GlobalSecondaryIndexes;

// This code snippet will work for multiple indexes, even though
// there is only one index in this example.

foreach (GlobalSecondaryIndexDescription gsiDescription in globalSecondaryIndexes) {


Console.WriteLine("Info for index " + gsiDescription.IndexName + ":");

foreach (KeySchemaElement kse in gsiDescription.KeySchema) {


Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType);
}

Projection projection = gsiDescription.Projection;


Console.WriteLine("\tThe projection type is: " + projection.ProjectionType);

if (projection.ProjectionType.ToString().Equals("INCLUDE")) {
Console.WriteLine("\t\tThe non-key projected attributes are: "
+ projection.NonKeyAttributes);
}
}

Query a Global Secondary Index


You can use Query on a global secondary index, in much the same way you Query a table. You need to
specify the index name, the query criteria for the index partition key and sort key (if present), and the
attributes that you want to return. In this example, the index is PrecipIndex, which has a partition
key of Date and a sort key of Precipitation. The index query returns all of the weather data for a
particular date, where the precipitation is greater than zero.

The following are the steps to query a global secondary index using the .NET low-level API.

1. Create an instance of the AmazonDynamoDBClient class.


2. Create an instance of the QueryRequest class to provide the request information.
3. Execute the query method by providing the request object as a parameter.

The attribute name Date is a DynamoDB reserved word. Therefore, you must use an expression attribute
name as a placeholder in the KeyConditionExpression.

The following C# code example demonstrates the preceding steps.

Example

client = new AmazonDynamoDBClient();

QueryRequest queryRequest = new QueryRequest

API Version 2012-08-10


529
Amazon DynamoDB Developer Guide
Global Secondary Indexes

{
TableName = "WeatherData",
IndexName = "PrecipIndex",
KeyConditionExpression = "#dt = :v_date and Precipitation > :v_precip",
ExpressionAttributeNames = new Dictionary<String, String> {
{"#dt", "Date"}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_date", new AttributeValue { S = "2013-08-01" }},
{":v_precip", new AttributeValue { N = "0" }}
},
ScanIndexForward = true
};

var result = client.Query(queryRequest);

var items = result.Items;


foreach (var currentItem in items)
{
foreach (string attr in currentItem.Keys)
{
Console.Write(attr + "---> ");
if (attr == "Precipitation")
{
Console.WriteLine(currentItem[attr].N);
}
else
{
Console.WriteLine(currentItem[attr].S);
}

}
Console.WriteLine();
}

Example: Global Secondary Indexes Using the AWS SDK for .NET Low-Level API
The following C# code example shows how to work with global secondary indexes. The example creates
a table named Issues, which might be used in a simple bug tracking system for software development.
The partition key is IssueId and the sort key is Title. There are three global secondary indexes on this
table:

• CreateDateIndex — The partition key is CreateDate and the sort key is IssueId. In addition to
the table keys, the attributes Description and Status are projected into the index.
• TitleIndex — The partition key is Title and the sort key is IssueId. No attributes other than the
table keys are projected into the index.
• DueDateIndex — The partition key is DueDate, and there is no sort key. All of the table attributes are
projected into the index.

After the Issues table is created, the program loads the table with data representing software bug
reports. It then queries the data using the global secondary indexes. Finally, the program deletes the
Issues table.

For step-by-step instructions for testing the following sample, see .NET Code Examples (p. 333).

Example

/**
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

API Version 2012-08-10


530
Amazon DynamoDB Developer Guide
Global Secondary Indexes

*
* This file is licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License. A copy of
* the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
class LowLevelGlobalSecondaryIndexExample
{
private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
public static String tableName = "Issues";

public static void Main(string[] args)


{
CreateTable();
LoadData();

QueryIndex("CreateDateIndex");
QueryIndex("TitleIndex");
QueryIndex("DueDateIndex");

DeleteTable(tableName);

Console.WriteLine("To continue, press enter");


Console.Read();
}

private static void CreateTable()


{
// Attribute definitions
var attributeDefinitions = new List<AttributeDefinition>()
{
{new AttributeDefinition {
AttributeName = "IssueId", AttributeType = "S"
}},
{new AttributeDefinition {
AttributeName = "Title", AttributeType = "S"
}},
{new AttributeDefinition {
AttributeName = "CreateDate", AttributeType = "S"
}},
{new AttributeDefinition {
AttributeName = "DueDate", AttributeType = "S"
}}
};

// Key schema for table


var tableKeySchema = new List<KeySchemaElement>() {
{
new KeySchemaElement {

API Version 2012-08-10


531
Amazon DynamoDB Developer Guide
Global Secondary Indexes

AttributeName= "IssueId",
KeyType = "HASH" //Partition key
}
},
{
new KeySchemaElement {
AttributeName = "Title",
KeyType = "RANGE" //Sort key
}
}
};

// Initial provisioned throughput settings for the indexes


var ptIndex = new ProvisionedThroughput
{
ReadCapacityUnits = 1L,
WriteCapacityUnits = 1L
};

// CreateDateIndex
var createDateIndex = new GlobalSecondaryIndex()
{
IndexName = "CreateDateIndex",
ProvisionedThroughput = ptIndex,
KeySchema = {
new KeySchemaElement {
AttributeName = "CreateDate", KeyType = "HASH" //Partition key
},
new KeySchemaElement {
AttributeName = "IssueId", KeyType = "RANGE" //Sort key
}
},
Projection = new Projection
{
ProjectionType = "INCLUDE",
NonKeyAttributes = {
"Description", "Status"
}
}
};

// TitleIndex
var titleIndex = new GlobalSecondaryIndex()
{
IndexName = "TitleIndex",
ProvisionedThroughput = ptIndex,
KeySchema = {
new KeySchemaElement {
AttributeName = "Title", KeyType = "HASH" //Partition key
},
new KeySchemaElement {
AttributeName = "IssueId", KeyType = "RANGE" //Sort key
}
},
Projection = new Projection
{
ProjectionType = "KEYS_ONLY"
}
};

// DueDateIndex
va