{"id":228,"date":"2016-05-19T23:09:45","date_gmt":"2016-05-19T15:09:45","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=228"},"modified":"2026-03-17T00:13:15","modified_gmt":"2026-03-16T16:13:15","slug":"aws-dynamodb-notes","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/aws-dynamodb-notes.html","title":{"rendered":"AWS DynamoDB Notes"},"content":{"rendered":"<p>AWS DynamoDB is a fully managed key-value store (also document store) NoSQL database as a service provided by Amazon Web Services. Its pricing model is that you only pay for the throughput (read and write) you use instead of the storage usage and the running hours of database instances.<\/p>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/Introduction.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/Introduction.html<\/a><br \/>\n<a href=\"http:\/\/www.slideshare.net\/AmazonWebServices\/design-patterns-using-amazon-dynamodb\">http:\/\/www.slideshare.net\/AmazonWebServices\/design-patterns-using-amazon-dynamodb<\/a><\/p>\n<h2>Glossary<\/h2>\n<p>DynamoDB is schema-less.<\/p>\n<ul>\n<li>table: a table is a collection of items.<\/li>\n<li>item: an item is a collection of attributes (key-value pairs).<\/li>\n<li>attribute: an attribute is similar to a field or column in other databases.<\/li>\n<li>primary key: one or two attributes that can uniquely identify every item in a table.\n<ul>\n<li>partition key (aka hash key): a simple primary key, composed of one attribute.<\/li>\n<li>partition key and sort key (aka range key): a composite primary key, composed of two attributes.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/HowItWorks.CoreComponents.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/HowItWorks.CoreComponents.html<\/a><\/p>\n<h3>Global Secondary Index (GSI)<\/h3>\n<p>secondary index \u6307\u7684\u662f\u9664\u4e86 primary key \u4e4b\u5916\u7684\u7b2c\u4e8c\u7d44 key<br \/>\n\u53ef\u4ee5\u6709\u5f88\u591a\u7d44 secondary index<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/SecondaryIndexes.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/SecondaryIndexes.html<\/a><\/p>\n<p>GSI \u53ef\u4ee5\u7528\u5728\u662f  partition key \u6216 partition + sort key \u7684 table<br \/>\nGSI \u8ddf primary key \u4e00\u6a23\u53ef\u4ee5 simple \u6216\u662f composite \u7684<br \/>\nGSI \u53ef\u4ee5\u96a8\u6642\u589e\u6e1b<\/p>\n<p>\u5982\u679c\u4f60\u4e0d\u9700\u8981 strong consistency \u6216\u500b\u5225 partition \u7684\u8cc7\u6599\u91cf\u5927\u65bc 10GB<br \/>\n\u90a3\u5c31\u7528 GSI<\/p>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/GSI.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/GSI.html<\/a><br \/>\n<a href=\"http:\/\/iamgarlic.blogspot.tw\/2015\/01\/amazon-dynamodb-global-secondary-index.html\">http:\/\/iamgarlic.blogspot.tw\/2015\/01\/amazon-dynamodb-global-secondary-index.html<\/a><\/p>\n<h3>Local Secondary Index (LSI)<\/h3>\n<p>LSI \u53ea\u80fd\u7528\u5728\u662f partition + sort key \u7684 table<br \/>\nLSI \u5fc5\u9808\u7528\u539f\u672c\u7684  partition key \u642d\u914d\u5176\u4ed6 attribute \u505a\u70ba\u65b0\u7684  partition + sort key\uff08LSI \u53ea\u6703\u662f composite \u7684\uff09<br \/>\nLSI \u53ea\u80fd\u5728\u5efa\u7acb table \u7684\u6642\u5019\u5b9a\u7fa9<\/p>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/LSI.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/LSI.html<\/a><br \/>\n<a href=\"http:\/\/iamgarlic.blogspot.tw\/2015\/01\/amazon-dynamodb-local-secondary-index.html\">http:\/\/iamgarlic.blogspot.tw\/2015\/01\/amazon-dynamodb-local-secondary-index.html<\/a><\/p>\n<h2>Query and Scan<\/h2>\n<p>\u80fd\u4e0d\u7528 <code>scan<\/code> \u5c31\u4e0d\u7528<br \/>\n\u7562\u7adf\u9019\u500b\u64cd\u4f5c\u5c31\u662f\u53bb\u6383 table \u88e1\u7684\u6240\u6709 item<\/p>\n<p>primary key \u548c local secondary index \u53ea\u80fd\u5728\u5efa\u7acb table \u6642\u6307\u5b9a<br \/>\n\u4e00\u65e6\u5efa\u7acb\u5c31\u4e0d\u80fd\u6539\u4e86<br \/>\n\u4f46\u662f global secondary index \u5c31\u6c92\u6709\u9019\u500b\u9650\u5236<\/p>\n<p>\u5982\u679c\u662f\u7528 partition + sork key \u7576 primary key<br \/>\n<code>get<\/code> \u7684\u6642\u5019\u8981\u540c\u6642\u7d66 partition key \u548c sort key<br \/>\n<code>query<\/code> \u7684\u6642\u5019\u53ef\u4ee5\u53ea\u7d66 partition key \u800c sort key \u53ef\u7d66\u53ef\u4e0d\u7d66\uff08\u4f46\u662f partition key \u4e00\u5b9a\u8981\u7d66\uff09<\/p>\n<p>\u7121\u8ad6\u662f\u7576 primary key\u3001GSI \u6216 LSI<br \/>\n\u53ea\u8981\u662f partition key \u7684 attribute \u4e00\u5f8b\u53ea\u80fd\u4f7f\u7528 = \u4f86 query<br \/>\n\u8a72 attribute \u6c92\u6709 rich query \u7684\u80fd\u529b\uff08\u5c31\u662f &gt;, &lt;, between, contains \u90a3\u4e9b\u689d\u4ef6\uff09<br \/>\nsort key \u624d\u6703\u6709 rich query<\/p>\n<p>Best Practices<\/p>\n<p><a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/BestPractices.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/BestPractices.html<\/a><\/p>\n<p>Choosing a Partition Key<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/GuidelinesForTables.html\">http:\/\/docs.aws.amazon.com\/amazondynamodb\/latest\/developerguide\/GuidelinesForTables.html<\/a><\/p>\n<p>Querying DynamoDB by date<br \/>\n<a href=\"http:\/\/stackoverflow.com\/questions\/14836600\/querying-dynamodb-by-date\">http:\/\/stackoverflow.com\/questions\/14836600\/querying-dynamodb-by-date<\/a><\/p>\n<p>Pick an item randomly<br \/>\n<a href=\"http:\/\/stackoverflow.com\/questions\/10666364\/aws-dynamodb-pick-a-record-item-randomly\">http:\/\/stackoverflow.com\/questions\/10666364\/aws-dynamodb-pick-a-record-item-randomly<\/a><\/p>\n<p>ref:<br \/>\n<a href=\"https:\/\/www.uplift.agency\/blog\/posts\/2016\/03\/clearcare-dynamodb\">https:\/\/www.uplift.agency\/blog\/posts\/2016\/03\/clearcare-dynamodb<\/a><br \/>\n<a href=\"https:\/\/medium.com\/building-timehop\/one-year-of-dynamodb-at-timehop-f761d9fe5fa1#.3g97b3lqy\">https:\/\/medium.com\/building-timehop\/one-year-of-dynamodb-at-timehop-f761d9fe5fa1#.3g97b3lqy<\/a><\/p>\n<h2>Commands<\/h2>\n<p>DynamoDB is schema-less, so that you can only define keys you need for specifying primary key or local secondary index when creating table.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\"># \u53ef\u4ee5\u7528 project name \u4f5c\u70ba table name \u7684 prefix\n# \u4e4b\u5f8c\u53ef\u4ee5\u96a8\u6642\u4fee\u6539 read \/ write capacity units\n$ aws dynamodb create-table \\\n--table-name CodeTengu_Preference \\\n--attribute-definitions AttributeName=name,AttributeType=S \\\n--key-schema AttributeName=name,KeyType=HASH \\\n--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5\n\n$ aws dynamodb create-table \\\n--table-name CodeTengu_WeeklyIssue \\\n--attribute-definitions AttributeName=number,AttributeType=N AttributeName=publication,AttributeType=S AttributeName=publishedAt,AttributeType=N \\\n--key-schema AttributeName=number,KeyType=HASH \\\n--global-secondary-indexes IndexName=publication_publishedAt,KeySchema='[{AttributeName=publication,KeyType=HASH},{AttributeName=publishedAt,KeyType=RANGE}]',Projection='{ProjectionType=ALL}',ProvisionedThroughput='{ReadCapacityUnits=5,WriteCapacityUnits=5}' \\\n--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5\n\n$ aws dynamodb create-table \\\n--table-name CodeTengu_WeeklyPost \\\n--attribute-definitions AttributeName=issueNumber,AttributeType=N AttributeName=id,AttributeType=N  AttributeName=categoryCode,AttributeType=S \\\n--key-schema AttributeName=issueNumber,KeyType=HASH AttributeName=id,KeyType=RANGE \\\n--global-secondary-indexes IndexName=categoryCode_id,KeySchema='[{AttributeName=categoryCode,KeyType=HASH},{AttributeName=id,KeyType=RANGE}]',Projection='{ProjectionType=ALL}',ProvisionedThroughput='{ReadCapacityUnits=5,WriteCapacityUnits=5}' \\\n--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/create-table.html\">http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/create-table.html<\/a><br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/update-table.html\">http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/update-table.html<\/a><\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">$ aws dynamodb put-item \\\n--table-name CodeTengu_Preference \\\n--item file:\/\/fixtures\/curated_api_config.json \\\n--return-consumed-capacity TOTAL\n\n# fixtures\/curated_api_config.json\n{\n  \"name\": { \"S\": \"curated_api_config\" },\n  \"apiKey\": { \"S\": \"xxx\" }\n}<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/put-item.html\">http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/put-item.html<\/a><\/p>\n<pre class=\"line-numbers\"><code class=\"language-bash\">$ aws dynamodb get-item \\\n--table-name CodeTengu_WeeklyIssue \\\n--key '{\"number\": {\"N\": \"42\"}}'<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/get-item.html\">http:\/\/docs.aws.amazon.com\/cli\/latest\/reference\/dynamodb\/get-item.html<\/a><\/p>\n<h2>Usage<\/h2>\n<p>\u4f60\u61c9\u8a72\u7528 <code>AWS.DynamoDB.DocumentClient<\/code><br \/>\n\u800c\u4e0d\u662f\u76f4\u63a5\u7528 <code>AWS.DynamoDB<\/code><\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">const AWS = require(\"aws-sdk\");\n\nconst dynamodb = new AWS.DynamoDB({\n  apiVersion: \"2012-08-10\",\n  region: \"ap-northeast-1\",\n});\nconst dynamodbClient = new AWS.DynamoDB.DocumentClient({ service: dynamodb });\n\nconst params = {\n  RequestItems: {\n    CodeTengu_Preference: {\n      Keys: [{ name: \"xxx\" }],\n    },\n  },\n};\n\ndynamodbClient.batchGet(params, (err, data) =&gt; {\n  if (err) {\n    console.log(\"fail\");\n    console.log(err);\n  } else {\n    console.log(\"success\");\n    console.log(data);\n  }\n});<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"http:\/\/aws.amazon.com\/sdk-for-node-js\/\">http:\/\/aws.amazon.com\/sdk-for-node-js\/<\/a><br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/AWSJavaScriptSDK\/latest\/AWS\/DynamoDB.html\">http:\/\/docs.aws.amazon.com\/AWSJavaScriptSDK\/latest\/AWS\/DynamoDB.html<\/a><br \/>\n<a href=\"http:\/\/docs.aws.amazon.com\/AWSJavaScriptSDK\/latest\/AWS\/DynamoDB\/DocumentClient.html\">http:\/\/docs.aws.amazon.com\/AWSJavaScriptSDK\/latest\/AWS\/DynamoDB\/DocumentClient.html<\/a><\/p>\n<p>\u5b8c\u6574\u7684\u7a0b\u5f0f\u78bc\u653e\u5728 GitHub \u4e0a<\/p>\n<p><a href=\"https:\/\/github.com\/CodeTengu\/lambdabaku\">https:\/\/github.com\/CodeTengu\/lambdabaku<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>AWS DynamoDB is a fully managed key-value store (also document store) NoSQL database as a service provided by Amazon Web Services. Its pricing model is that you only pay for the throughput (read and write) you use instead of the storage usage and the running hours of database instances.<\/p>\n","protected":false},"author":1,"featured_media":779,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,38,116],"tags":[16,107,11,12],"class_list":["post-228","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-about-database","category-about-devops","category-about-web-development","tag-amazon-web-services","tag-aws-dynamodb","tag-javascript","tag-node-js"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/228","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=228"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/228\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/779"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=228"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}