ããã¯ããªã«ãããããŠæžãããã®ïŒ
åã«Amazon DynamoDBã®ã¯ãšãªãŒãè©ŠããŠã¿ãŸããã
Amazon DynamoDBローカル版(DynamoDB Local )とDocumentClientで、クエリーを試す - CLOVER🍀
ä»åã¯ãã¹ãã£ã³ãè©ŠããŠã¿ããããªãšæããŸãã
Amazon DynamoDBã®ã¹ãã£ã³
Amazon DynamoDBã®ã¹ãã£ã³ã«é¢ããããã¥ã¡ã³ããèŠãŠã¿ãŸãããã
ãŸããæŠèŠã¯ãã¡ãã
Amazon DynamoDB ã® Scan ãªãã¬ãŒã·ã§ã³ã§ã¯ãããŒãã«ãŸãã¯ã»ã«ã³ããªã€ã³ããã¯ã¹ã®ãã¹ãŠã®é ç®ãèªã¿èŸŒã¿ãŸããããã©ã«ãã§ã¯ãScan ãªãã¬ãŒã·ã§ã³ã¯ããŒãã«ãŸãã¯ã€ã³ããã¯ã¹ã®ãã¹ãŠã®é ç®ã®ããŒã¿å±æ§ãè¿ããŸããProjectionExpression ãã©ã¡ãŒã¿ã䜿çšããScan ããã¹ãŠã®å±æ§ã§ã¯ãªãäžéšã®ã¿ãè¿ãããã«ã§ããŸãã
Scan ã¯åžžã«çµæã»ãããè¿ããŸããäžèŽããé ç®ããªãå Žåãçµæã»ããã¯ç©ºã«ãªããŸãã
DynamoDB でのスキャンの使用 - Amazon DynamoDB
å šããŒã¿ãèªã¿èŸŒãããšããã®ãããããã€ã³ããªæ°ãããŸããâŠã
Amazon DynamoDB ã® Scan ãªãã¬ãŒã·ã§ã³ã§ã¯ãããŒãã«ãŸãã¯ã»ã«ã³ããªã€ã³ããã¯ã¹ã®ãã¹ãŠã®é ç®ãèªã¿èŸŒã¿ãŸããããã©ã«ãã§ã¯ãScan ãªãã¬ãŒã·ã§ã³ã¯ããŒãã«ãŸãã¯ã€ã³ããã¯ã¹ã®ãã¹ãŠã®é ç®ã®ããŒã¿å±æ§ãè¿ããŸãã
ãªãã倧ããªããŒã¿ã»ãããæ±ããããã«ãèŠããŸããã1åã®ã¹ãã£ã³ã§æ±ããããŒã¿éã¯æ倧1MBã®ããã§ãã
1 åã® Scan ãªã¯ãšã¹ãã§ãæ倧 1 MB ã®ããŒã¿ãååŸã§ããŸãã
ã¹ãã£ã³ã«ã¯ããã£ã«ã¿ãŒåŒãé©çšããŠçµæã®ãã£ã«ã¿ãªã³ã°ãå¯èœãªããã§ãã
Scan çµæã®çµã蟌ã¿ãå¿ èŠãªå Žåã¯ããªãã·ã§ã³ã§ãã£ã«ã¿åŒãæå®ã§ããŸãããã£ã«ã¿åŒã«ãã£ãŠãScan çµæã®è¿ãããé ç®ã決ãŸããŸããä»ã®ãã¹ãŠã®çµæã¯ç Žæ£ãããŸãã
DynamoDB ã§ã®ã¹ãã£ã³ã®æäœ / Scan ã®ãã£ã«ã¿åŒ
ã¯ãšãªãŒãããã§ãããããã£ã«ã¿ãŒã«ããçµã蟌ã¿ã¯ã¹ãã£ã³å¯Ÿè±¡ã®ããŒã¿éãæžãããïŒæ€çŽ¢å¯Ÿè±¡ãçµã蟌ããïŒããã§ã¯ãªãã
ãããŸã§çµæãååŸããéã«åŒã³åºãå
ã«èŠããããŒã¿ãæžããã ãã§ããã
ãã£ã«ã¿åŒã¯ãScan ã®å®äºåŸãçµæãè¿ãããåã«é©çšãããŸãããã®ãããScan ã¯ããã£ã«ã¿åŒããããã©ããã«ããããããåãéã®èªã¿èŸŒã¿ãã£ãã·ãã£ãŒãæ¶è²»ããŸãã
ãã®ããããã£ã«ã¿ãŒã䜿çšããŠãã¹ãã£ã³æäœã«é¢ããããŒã¿éã®å¶éã«ã¯åœ±é¿ããŸããã
1 åã® Scan ãªãã¬ãŒã·ã§ã³ã§ãæ倧 1 MB ã®ããŒã¿ãååŸã§ããŸãããã®å¶éã¯ããã£ã«ã¿åŒãè©äŸ¡ããåã«é©çšãããŸãã
ãã£ã«ã¿ãŒã®æžãæ¹ã«ã€ããŠã¯ãæ¡ä»¶åŒã®ããŒãžãèŠãªããããšã
ãã£ã«ã¿åŒã®æ§æã¯ãæ¡ä»¶åŒã®æ§æãšåãã§ãããã£ã«ã¿åŒã¯ãæ¡ä»¶åŒãšåãã³ã³ãã¬ãŒã¿ãé¢æ°ããã³è«çæŒç®åã䜿çšã§ããŸãã
å®éã®æ¯èŒæŒç®åããåŒã®æžãæ¹ã®è©³çŽ°ã¯ãã¡ãã§ãã
比較演算子および関数リファレンス - Amazon DynamoDB
式を使用する時の項目属性の指定 - Amazon DynamoDB
ã¹ãã£ã³æäœã§è¿ãã¢ã€ãã ã®æ°ã¯äžéãèšããããšãå¯èœãªããã§ãã
Scan ãªãã¬ãŒã·ã§ã³ã¯ãçµæã§è¿ãããé ç®æ°ãå¶éããããšãã§ããŸããâãããè¡ãã«ã¯ããã£ã«ã¿åŒãè©äŸ¡ããåã«ãLimit ãã©ã¡ãŒã¿ã«ãScan ãªãã¬ãŒã·ã§ã³ãè¿ãé ç®ã®æ倧æ°ãèšå®ããŸãã
DynamoDB ã§ã®ã¹ãã£ã³ã®æäœ / çµæã»ããã®é ç®æ°ã®å¶é
説æãèŠãŠãããšãLimitã®æå®ã¯ã¹ãã£ã³ããå¹ èªäœãçããããã§ããã
ããšãã°ããã£ã«ã¿åŒã䜿çšãããScan å€ã Limit ãšããŠãããŒãã«ã 6 ãããšããŸããScan çµæã«ã¯ãããŒãã«ã®æåã® 6 ã€ã®é ç®ãå«ãŸããŸãã
ããã§ãScan ã«ãã£ã«ã¿åŒãè¿œå ãããšããŸãããã®å ŽåãDynamoDB ã¯è¿ããã 6 ã€ã®é ç®ã«ãã£ã«ã¿ãŒåŒãé©çšããäžèŽããªãé ç®ãå»æ£ããŸããæçµç㪠Scan çµæã¯ãã£ã«ã¿ãªã³ã°ãããé ç®ã®æ°ã«å¿ããŠã6 ã€ä»¥äžã®é ç®ãå«ã¿ãŸãã
ã¹ãã£ã³ã¯ããŒãžã³ã°ã®æ©èœãæã£ãŠãããããŒãžã³ã°ã掻çšããããšã§1MB以äžã®ããŒã¿ãååŸããããšãã§ãããã§ãã
â»1ã€ã®ããŒãžã®å€§ããã¯1MB以äžã§ããå¿
èŠããã
DynamoDB ã§ã¯ãScan ãªãã¬ãŒã·ã§ã³ã®çµæãããŒãžå²ãããŸããããŒãžå²ããè¡ãããšã§ Scan çµæã 1 MB ãµã€ãº (ãŸãã¯ãã以äž) ã®ããŒã¿ã®ãããŒãžãã«åå²ãããŸããã¢ããªã±ãŒã·ã§ã³ã¯çµæã®æåã®ããŒãžã次㫠2 ããŒãžãšåŠçã§ããŸãã
1 ã€ã® Scan ã¯ããµã€ãºã®å¶éã§ãã1 MB 以å ã®çµæã»ããã ããè¿ããŸããããã«çµæããããã©ããã確èªããŠãäžåºŠã« 1 ããŒãžãã€çµæãåãåºãã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã§æ¬¡ã®æäœãè¡ãå¿ èŠããããŸãã
DynamoDB ã§ã®ã¹ãã£ã³ã®æäœ / ããŒãžåäœã®åºå件æ°ãæå®
èªã¿èŸŒãããŒã¿ã®æŽåæ§ã¯ãããã©ã«ãã§ã¯çµææŽåæ§ã§ãã
Scan ãªãã¬ãŒã·ã§ã³ã¯ãçµæçã«æŽåæ§ã®ããèªã¿èŸŒã¿ãããã©ã«ãã§è¡ããŸããã€ãŸããScan çµæããæè¿å®äºãã PutItem ãŸã㯠UpdateItem ãªãã¬ãŒã·ã§ã³ã«ããå€æŽãåæ ããªãå ŽåããããŸãã詳现ã«ã€ããŠã¯ããèªã¿èŸŒã¿æŽåæ§ããåç §ããŠãã ããã
DynamoDB ã§ã®ã¹ãã£ã³ã®æäœ / ã¹ãã£ã³ã®èªã¿èŸŒã¿æŽåæ§
匷ãæŽåæ§ãæ±ããããšãã§ããŸãã
匷åãªæŽåæ§ã®ããèªã¿èŸŒã¿ãå¿ èŠãªå Žåã¯ãScan ãéå§ããæã« ConsistentRead ãã©ã¡ãŒã¿ã true ãªã¯ãšã¹ã㧠Scan ã«èšå®ã§ããŸããããã«ãããScan ãéå§ããåã«å®äºããæžã蟌ã¿ãªãã¬ãŒã·ã§ã³ããã¹ãŠ Scan å¿çã«å«ããããŸãã
ãŸãã䞊åã¹ãã£ã³ãå¯èœãªããã§ãã䞊åã¹ãã£ã³ã䜿çšãããšãã¹ãã£ã³æäœãè¿œå ããããšã§1MB以äžã®ããŒã¿ãååŸã§ãããã§ãã
ããã©ã«ãã§ã¯ãScan ãªãã¬ãŒã·ã§ã³ã¯ãããŒã¿ãé 次åŠçããŸããAmazon DynamoDB ã¯ã¢ããªã±ãŒã·ã§ã³ã« 1 MB åäœã§ããŒã¿ãè¿ããã¢ããªã±ãŒã·ã§ã³ã¯è¿œå ã® Scan ãªãã¬ãŒã·ã§ã³ã䜿çšããŠã次㮠1 MB ã®ããŒã¿ãååŸã§ããŸãã
Amazon DynamoDBã®ã¹ãã£ã³ã¯ããã©ã«ãã§ã·ãŒã±ã³ã·ã£ã«ã¹ãã£ã³ã§ãããã¹ãã£ã³æäœã¯1åã§1ããŒãã£ã·ã§ã³ããèªã¿èŸŒãããšã
ã§ããªãããã§ãã
ã¹ãã£ã³ããããŒãã«ãŸãã¯ã€ã³ããã¯ã¹ã倧ããã»ã©ãScan ãå®äºããã®ã«æéãããããŸããããã«ãã·ãŒã±ã³ã·ã£ã« Scan ã¯ãããããžã§ã³ãããèªã¿èŸŒã¿ã¹ã«ãŒããã容éãåžžã«å®å šã«äœ¿çšã§ãããšã¯éããŸãããDynamoDB ã¯å€§ããªããŒãã«ã®ããŒã¿ãè€æ°ã®ç©çããŒãã£ã·ã§ã³ã«åæ£ããŸãããScan ãªãã¬ãŒã·ã§ã³ã§ã¯ãäžåºŠã« 1 ã€ã®ããŒãã£ã·ã§ã³ããèªã¿èŸŒãããšãã§ããŸããããã®ãããScan ã®ã¹ã«ãŒãããã¯ãåäžã®ããŒãã£ã·ã§ã³ã®æ倧ã¹ã«ãŒãããã«ãã£ãŠå¶çŽãããŸãã
ããã§ãã¹ãã£ã³æã«ãã©ã¡ãŒã¿ãŒãæå®ããããšã§è€æ°ã®ã¯ãŒã«ãŒã«äžŠåã«ã¹ãã£ã³ãããããšãã§ããããã§ãã
Scan ãªãã¬ãŒã·ã§ã³ã§ã¯ãããŒãã«ãŸãã¯ã»ã«ã³ããªã€ã³ããã¯ã¹ãè«ççã«è€æ°ã®ã»ã°ã¡ã³ãã«åå²ããè€æ°ã®ã¢ããªã±ãŒã·ã§ã³ã¯ãŒã«ãŒãã»ã°ã¡ã³ãã䞊è¡ããŠã¹ãã£ã³ããŸããåã¯ãŒã«ãŒã¯ãã¹ã¬ãã (ãã«ãã¹ã¬ããããµããŒãããããã°ã©ãã³ã°èšèª) ãŸãã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã»ã¹ã«ããããšãã§ããŸãã䞊åã¹ãã£ã³ãå®è¡ããã«ã¯ãåã¯ãŒã«ãŒãç¬èªã® Scan ãªã¯ãšã¹ãã以äžã®ãã©ã¡ãŒã¿ã§éä¿¡ããŸãã
ãã ã䞊åã¹ãã£ã³ã䜿çšãããšïŒåœç¶ã§ããïŒã¹ã«ãŒãããã®æ¶è²»ã倧ãããªãå¯èœæ§ãé«ãããã泚æããå¿ èŠããããŸãã
å€æ°ã®ã¯ãŒã«ãŒã䜿çšãã䞊åã¹ãã£ã³ã§ã¯ãã¹ãã£ã³å¯Ÿè±¡ã®ããŒãã«ãŸãã¯ã€ã³ããã¯ã¹ã«å¯ŸããŠããããžã§ã³ãããã¹ã«ãŒãããããã¹ãŠç°¡åã«äœ¿çšã§ããŸããããŒãã«ãŸãã¯ã€ã³ããã¯ã¹ãä»ã®ã¢ããªã±ãŒã·ã§ã³ãã倧éã®èªã¿èŸŒã¿ãŸãã¯æžã蟌ã¿ã¢ã¯ãã£ããã£ãçºçããŠããå Žåã¯ããã®ãããªã¹ãã£ã³ãé¿ããããšããå§ãããŸãã
ããã«ã€ããŠã¯ãäžéãèšããŠã³ã³ãããŒã«ããããšãã§ãããã§ãã
ãªã¯ãšã¹ãããšã«è¿ãããããŒã¿ã®éãå¶åŸ¡ããã«ã¯ãLimit ãã©ã¡ãŒã¿ã䜿çšããŸããããã«ããã1 人ã®ã¯ãŒã«ãŒãããããžã§ã³ãããã¹ã«ãŒãããããã¹ãŠæ¶è²»ããä»ã®ãã¹ãŠã®ã¯ãŒã«ãŒãç ç²ã«ãªãç¶æ³ãé²ãããšãã§ããŸãã
説æãèŠãŠãããšãã¹ãã£ã³ã¯ãããªã«äœ¿ããã®ã§ã¯ãªãããâŠãšããããç¹ã«å€§ããªããŒãã«ã«ã¯äœ¿ã£ãŠã¯ãããªãããã«èŠããã®ã§ããã
ãã£ã±ããã®ããã§ããã
Scan ã¢ã¯ã·ã§ã³ã§ã¯ãFilterExpression ãã©ã¡ãŒã¿ãæå®ã§ããŸããããã䜿çšããŠãçµæã«è¡šç€ºããªãé ç®ãç Žæ£ããããšãã§ããŸããFilterExpression ã¯ãã¹ãã£ã³ãå®è¡ãããåŸã§ãçµæãè¿ãããåã«é©çšãããŸãã(ããã¯ã倧ããªããŒãã«ã§ã¯ãå§ãããŸãããããããããªäžèŽããé ç®ã®ã¿ãè¿ã£ãŠããå Žåã§ããScan å šäœã«å¯ŸããŠæéãè«æ±ãããŸãã)
ã€ã³ããã¯ã¹ã®è©±ã¯ãä»åã¯çœ®ããŠãããŸãã
ãŸãããã£ããé°å²æ°ã¯ç¢ºèªããŠã¿ãŸããããã確èªã¯ãAmazon DynamoDBã®ããŒã«ã«çïŒDynamoDB Local ïŒã䜿ããŸãã
ããŒãžã³ã°ãšäžŠåã¹ãã£ã³ããä»åã¯å¯Ÿè±¡å€ã«ããŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ aws --version aws-cli/2.4.18 Python/3.8.8 Linux/5.4.0-99-generic exe/x86_64.ubuntu.20 prompt/off $ java --version openjdk 17.0.1 2021-10-19 OpenJDK Runtime Environment (build 17.0.1+12-Ubuntu-120.04) OpenJDK 64-Bit Server VM (build 17.0.1+12-Ubuntu-120.04, mixed mode, sharing)
ããŒã«ã«çã®Amazon DynamoDBïŒDynamoDB Local ïŒã®æ å ±ã
$ grep -A 2 'Release Notes' README.txt Release Notes ----------------------------- 2022-1-10 (1.18.0)
ã€ã³ã¡ã¢ãªãŒã§èµ·åãããŠãããŸãã
$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -inMemory
ããŒã«ã«çã®Amazon DynamoDBã«ãAWS CLIã§ã¢ã¯ã»ã¹ããããã®ã¯ã¬ãã³ã·ã£ã«ã
$ export AWS_ACCESS_KEY_ID=fakeMyKeyId $ export AWS_SECRET_ACCESS_KEY=fakeSecretAccessKey $ export AWS_DEFAULT_REGION=ap-northeast-1
確èªã¯ãAWS SDK for JavaScriptã䜿ã£ãŠãNode.jsã§è¡ããŸãã
$ node --version v16.14.0 $ npm --version 8.3.1
æºå
Node.jsãããžã§ã¯ããäœæããŸãããã¹ãã³ãŒãã§ç¢ºèªããããšã«ããŸãããã
$ npm init -y $ npm i -D typescript $ npm i -D -E prettier $ npm i -D jest @types/jest $ npm i -D esbuild esbuild-jest $ mkdir src test
Node.jsã®å宣èšãšAWS SDK for JavaScript v2ãã€ã³ã¹ããŒã«ã
$ npm i -D @types/node@v16 $ npm i aws-sdk
ä»åã®äŸåé¢ä¿ã¯ããã¡ãã
"devDependencies": { "@types/jest": "^27.4.0", "@types/node": "^16.11.24", "esbuild": "^0.14.21", "esbuild-jest": "^0.5.0", "jest": "^27.5.1", "prettier": "2.5.1", "typescript": "^4.5.5" }, "dependencies": { "aws-sdk": "^2.1073.0" }
èšå®ã¯ãã¡ãã
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "lib": ["esnext"], "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
tsconfig.typecheck.conf
{ "extends": "./tsconfig", "compilerOptions": { "baseUrl": "./", "noEmit": true }, "include": [ "src", "test" ] }
.prettierrc.json
{ "singleQuote": true }
jest.config.js
module.exports = { testEnvironment: 'node', transform: { "^.+\\.tsx?$": "esbuild-jest" } };
ä»åããããã¥ã¡ã³ãã€ã³ã¿ãŒãã§ãŒã¹ã䜿ã£ãŠãããŸãã
ドキュメントインターフェイス - Amazon DynamoDB
Class: AWS.DynamoDB.DocumentClient — AWS SDK for JavaScript
ããŒãã«å®çŸ©ãååãšåããã人ããé¡ã«ããŸãã
$ aws dynamodb create-table \ --endpoint-url http://localhost:8000 \ --table-name People \ --attribute-definitions \ AttributeName=familyId,AttributeType=N \ AttributeName=firstName,AttributeType=S \ --key-schema \ AttributeName=familyId,KeyType=HASH \ AttributeName=firstName,KeyType=RANGE \ --provisioned-throughput \ ReadCapacityUnits=10,WriteCapacityUnits=5 \ --table-class STANDARD
ä»åã¯ããœãŒãããŒãfirstName
ã«ããŠããŸããããã¯ãšãªãŒã®æã®ããã«ã¹ãã£ã³ã§ãœãŒãã®æé ã»éé ãå¶åŸ¡ããããšã¯ã§ããªãããã§ãã
ããŒã¿ã®ãé¡ãããµã¶ãšããã§ã
test/people.json
[ { "familyId": 1, "lastName": "ãã°ç°", "firstName": "ãµã¶ãš", "age": 24 }, { "familyId": 1, "lastName": "ãã°ç°", "firstName": "ãã¹ãª", "age": 28 }, { "familyId": 1, "lastName": "磯é", "firstName": "波平", "age": 54 }, { "familyId": 1, "lastName": "磯é", "firstName": "ãã", "age": 50 }, { "familyId": 1, "lastName": "磯é", "firstName": "ã«ããª", "age": 11 }, { "familyId": 1, "lastName": "磯é", "firstName": "ã¯ã«ã¡", "age": 9 }, { "familyId": 1, "lastName": "ãã°ç°", "firstName": "ã¿ã©ãª", "age": 3 }, { "familyId": 2, "lastName": "æ³¢é", "firstName": "ããªã¹ã±", "age": 26 }, { "familyId": 2, "lastName": "æ³¢é", "firstName": "ã¿ã€ã³", "age": 22 }, { "familyId": 2, "lastName": "æ³¢é", "firstName": "ã€ã¯ã©", "age": 1 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "é£ç©", "age": 60 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "ã軜", "age": 50 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "çå ", "age": 20 }, { "familyId": 3, "lastName": "äŒäœå", "firstName": "æµ®æ±", "age": 16 } ]
ããã°ã©ã ãäœæãã
ã§ã¯ãã¹ãã£ã³ã䜿ãããã°ã©ã ãäœæããŸãã
ããŒã¿ã«ãããã³ã°ããã¯ã©ã¹ãäœæã
src/person.ts
export class Person { familyId: number; lastName: string; firstName: string; age: number; constructor( familyId: number, lastName: string, firstName: string, age: number ) { this.familyId = familyId; this.lastName = lastName; this.firstName = firstName; this.age = age; } }
ãã¹ãã³ãŒãã®import
éšåãšãDocumentClient
ã®äœæã
test/scan.test.ts
import { DocumentClient } from 'aws-sdk/clients/dynamodb'; import file from 'fs'; import { Person } from '../src/person'; const dynamodb = new DocumentClient({ credentials: { accessKeyId: 'fakeMyKeyId', secretAccessKey: 'fakeSecretAccessKey', }, region: 'ap-northeast-1', endpoint: 'http://localhost:8000', }); // ããã«ããã¹ããæžãïŒ
ãã¹ãããŒã¿ã®ããŒããšãåé€ãæåŸã«å ¥ããŠãããŸãã
test('load people', async () => { const people = JSON.parse( await file.promises.readFile(`${__dirname}/people.json`, 'utf8') ) as Person[]; const params: DocumentClient.BatchWriteItemInput = { RequestItems: { People: people.map((p) => ({ PutRequest: { Item: p } })), }, }; const writed = await dynamodb.batchWrite(params).promise(); expect(writed.UnprocessedItems).toEqual({}); }); // ããã«ããã¹ããæžãïŒ test('delete people', async () => { const people = JSON.parse( await file.promises.readFile(`${__dirname}/people.json`, 'utf8') ) as Person[]; for (const person of people) { const params: DocumentClient.DeleteItemInput = { TableName: 'People', Key: { familyId: person.familyId, firstName: person.firstName, }, ReturnValues: 'ALL_OLD', }; try { const deleted = await dynamodb.delete(params).promise(); if (deleted.Attributes) { expect(deleted.Attributes['familyId']).toBe(person.familyId); expect(deleted.Attributes['lastName']).toBe(person.lastName); expect(deleted.Attributes['firstName']).toBe(person.firstName); expect(deleted.Attributes['age']).toBe(person.age); } else { throw new Error('fail'); } } catch (e) { throw e; } } return people; });
ã§ã¯ãã¹ãã£ã³ã䜿ã£ãŠãããŸãã
DocumentClient#scan
ã®APIããã¥ã¡ã³ãã¯ãã¡ãã
Class: AWS.DynamoDB.DocumentClient / scan
Amazon DynamoDBèªäœã®Scanã®APIã¯ãã¡ãã
ãŸãã¯æ¡ä»¶ãªãã§ã·ã³ãã«ã«ã
test('scan simply', async () => { const params: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, }; const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(14); expect(result.ScannedCount).toBe(14); if (result.Items) { const names = result.Items.map((v) => { const p = v as Person; return `${p.lastName}${p.firstName}`; }); expect(names).toEqual([ 'æ³¢éã€ã¯ã©', 'æ³¢éã¿ã€ã³', 'æ³¢éããªã¹ã±', '磯éã«ããª', 'ãã°ç°ãµã¶ãš', 'ãã°ç°ã¿ã©ãª', '磯éãã', 'ãã°ç°ãã¹ãª', '磯éã¯ã«ã¡', '磯é波平', 'äŒäœåã軜', 'äŒäœåæµ®æ±', 'äŒäœåçå ', 'äŒäœåé£ç©', ]); } else { throw new Error('fail'); } });
ç¹ã«çµã蟌ã¿ãªããã©ã¡ãŒã¿ãŒèšå®ããŠ
const params: DocumentClient.ScanInput = { TableName: 'People', ConsistentRead: true, };
å®è¡ãããšãå šä»¶ãååŸãã¹ãã£ã³ããŠããããšã確èªã§ããŸãïŒä»åã®ããŒã¿ã¯14件ã§ãïŒã
const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(14); expect(result.ScannedCount).toBe(14);
å®éãè¿ã£ãŠããŠããããŒã¿ãå šä»¶ã§ããã
const names = result.Items.map((v) => { const p = v as Person; return `${p.lastName}${p.firstName}`; }); expect(names).toEqual([ 'æ³¢éã€ã¯ã©', 'æ³¢éã¿ã€ã³', 'æ³¢éããªã¹ã±', '磯éã«ããª', 'ãã°ç°ãµã¶ãš', 'ãã°ç°ã¿ã©ãª', '磯éãã', 'ãã°ç°ãã¹ãª', '磯éã¯ã«ã¡', '磯é波平', 'äŒäœåã軜', 'äŒäœåæµ®æ±', 'äŒäœåçå ', 'äŒäœåé£ç©', ]);
次ã«ããã£ã«ã¿ãŒã䜿ã£ãŠã¿ãŸãã
test('scan with filter', async () => { const params: DocumentClient.ScanInput = { TableName: 'People', FilterExpression: '(lastName = :lastName1 or lastName = :lastName2) and age <= :age', ExpressionAttributeValues: { ':lastName1': '磯é', ':lastName2': 'äŒäœå', ':age': 20, }, ConsistentRead: true, }; const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(4); // ã¹ãã£ã³ã®æ»ãå€ãšãªãããŒã¿æ° expect(result.ScannedCount).toBe(14); // ããŒã¿æ° if (result.Items) { const katsuo = result.Items[0] as Person; expect(katsuo.familyId).toBe(1); expect(katsuo.lastName).toBe('磯é'); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11); const wakame = result.Items[1] as Person; expect(wakame.familyId).toBe(1); expect(wakame.lastName).toBe('磯é'); expect(wakame.firstName).toBe('ã¯ã«ã¡'); expect(wakame.age).toBe(9); const ukie = result.Items[2] as Person; expect(ukie.familyId).toBe(3); expect(ukie.lastName).toBe('äŒäœå'); expect(ukie.firstName).toBe('æµ®æ±'); expect(ukie.age).toBe(16); const jinroku = result.Items[3] as Person; expect(jinroku.familyId).toBe(3); expect(jinroku.lastName).toBe('äŒäœå'); expect(jinroku.firstName).toBe('çå '); expect(jinroku.age).toBe(20); } else { throw new Error('fail'); } });
FilterExpression
ã§æ¡ä»¶ãæå®ããŠãå€ããã€ã³ãã
const params: DocumentClient.ScanInput = { TableName: 'People', FilterExpression: '(lastName = :lastName1 or lastName = :lastName2) and age <= :age', ExpressionAttributeValues: { ':lastName1': '磯é', ':lastName2': 'äŒäœå', ':age': 20, }, ConsistentRead: true, };
æ¡ä»¶åŒã®æžãæ¹ã¯ããã¡ãã
Comparison operator and function reference - Amazon DynamoDB
ããã§ãè¿åŽãããããŒã¿æ°ãšã¹ãã£ã³ããããŒã¿æ°ã«å·®ãçŸããŸãã
const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(4); // ã¹ãã£ã³ã®æ»ãå€ãšãªãããŒã¿æ° expect(result.ScannedCount).toBe(14); // ããŒã¿æ°
ããã¥ã¡ã³ãã«ãããã£ã«ã¿ãŒã¯è¿ã£ãŠãã件æ°ãå€ããã ãã§ãã¹ãã£ã³å¯Ÿè±¡ã®ããŒã¿æ°ãæžãããã§ã¯ãªãããšããããšã
æžãããŠããŸãããããã
ãããžã§ã¯ã·ã§ã³ãååŸããå±æ§ãçµãããšãã§ããŸãã
test('scan with filter, projection', async () => { const params: DocumentClient.ScanInput = { TableName: 'People', FilterExpression: '(lastName = :lastName1 or lastName = :lastName2) and age <= :age', ExpressionAttributeValues: { ':lastName1': '磯é', ':lastName2': 'äŒäœå', ':age': 20, }, ProjectionExpression: 'firstName,age', ConsistentRead: true, }; const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(4); // ã¹ãã£ã³ã®æ»ãå€ãšãªãããŒã¿æ° expect(result.ScannedCount).toBe(14); // ããŒã¿æ° if (result.Items) { const katsuo = result.Items[0] as Person; expect(katsuo.familyId).toBeUndefined(); expect(katsuo.lastName).toBeUndefined(); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11); const wakame = result.Items[1] as Person; expect(wakame.familyId).toBeUndefined(); expect(wakame.lastName).toBeUndefined(); expect(wakame.firstName).toBe('ã¯ã«ã¡'); expect(wakame.age).toBe(9); const ukie = result.Items[2] as Person; expect(ukie.familyId).toBeUndefined(); expect(ukie.lastName).toBeUndefined(); expect(ukie.firstName).toBe('æµ®æ±'); expect(ukie.age).toBe(16); const jinroku = result.Items[3] as Person; expect(jinroku.familyId).toBeUndefined(); expect(jinroku.lastName).toBeUndefined(); expect(jinroku.firstName).toBe('çå '); expect(jinroku.age).toBe(20); } else { throw new Error('fail'); } });
ProjectionExpression
ã§æå®ããŸãããè€æ°ã®å±æ§ã察象ãšããå Žåã¯,
åºåãã§æå®ããŸãã
ProjectionExpression: 'firstName,age',
A string that identifies one or more attributes to retrieve from the specified table or index. These attributes can include scalars, sets, or elements of a JSON document. The attributes in the expression must be separated by commas.
ãããããšãæå®ããå±æ§ã ããè¿ã£ãŠããããã«ãªããŸãã
const katsuo = result.Items[0] as Person; expect(katsuo.familyId).toBeUndefined(); expect(katsuo.lastName).toBeUndefined(); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11); const wakame = result.Items[1] as Person; expect(wakame.familyId).toBeUndefined(); expect(wakame.lastName).toBeUndefined(); expect(wakame.firstName).toBe('ã¯ã«ã¡'); expect(wakame.age).toBe(9); const ukie = result.Items[2] as Person; expect(ukie.familyId).toBeUndefined(); expect(ukie.lastName).toBeUndefined(); expect(ukie.firstName).toBe('æµ®æ±'); expect(ukie.age).toBe(16); const jinroku = result.Items[3] as Person; expect(jinroku.familyId).toBeUndefined(); expect(jinroku.lastName).toBeUndefined(); expect(jinroku.firstName).toBe('çå '); expect(jinroku.age).toBe(20);
次ã¯ã件æ°å¶éãããŠã¿ãŸãããã
test('scan with limit', async () => { const params: DocumentClient.ScanInput = { TableName: 'People', Limit: 5, ConsistentRead: true, }; const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(5); expect(result.ScannedCount).toBe(5); if (result.Items) { const names = result.Items.map((v) => { const p = v as Person; return `${p.lastName}${p.firstName}`; }); expect(names).toEqual([ 'æ³¢éã€ã¯ã©', 'æ³¢éã¿ã€ã³', 'æ³¢éããªã¹ã±', '磯éã«ããª', 'ãã°ç°ãµã¶ãš', ]); } else { throw new Error('fail'); } });
ä»åã¯5件ã«ããŠã¿ãŸããã
const params: DocumentClient.ScanInput = { TableName: 'People', Limit: 5, ConsistentRead: true, };
ååŸä»¶æ°ã5件ã§ããã
const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(5); expect(result.ScannedCount).toBe(5); if (result.Items) { const names = result.Items.map((v) => { const p = v as Person; return `${p.lastName}${p.firstName}`; }); expect(names).toEqual([ 'æ³¢éã€ã¯ã©', 'æ³¢éã¿ã€ã³', 'æ³¢éããªã¹ã±', '磯éã«ããª', 'ãã°ç°ãµã¶ãš', ]);
ãããŠãååŸä»¶æ°å¶éãšãã£ã«ã¿ãŒãçµã¿åãããŠã¿ãŸãã
test('scan with filter, limit', async () => { const params: DocumentClient.ScanInput = { TableName: 'People', FilterExpression: '(lastName = :lastName1 or lastName = :lastName2) and age <= :age', ExpressionAttributeValues: { ':lastName1': '磯é', ':lastName2': 'äŒäœå', ':age': 20, }, Limit: 5, ConsistentRead: true, }; const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(1); // ã¹ãã£ã³ã®æ»ãå€ãšãªãããŒã¿æ° expect(result.ScannedCount).toBe(5); // ããŒã¿æ° if (result.Items) { const katsuo = result.Items[0] as Person; expect(katsuo.familyId).toBe(1); expect(katsuo.lastName).toBe('磯é'); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11); } else { throw new Error('fail'); } });
ãããããšãLimitã§ã¹ãã£ã³å¯Ÿè±¡ã®ããŒã¿ãçµã£ãããšã«ãã£ã«ã¿ãŒãããã£ãŠããããšãããããããŸãã
å šä»¶ã¹ãã£ã³ããåŸã§ããã°4件è¿ã£ãŠããæ¡ä»¶ãæå®ããŠããŸãããLimitã5ã«ãããšä»åã®ããŒãã«å®çŸ©ãããŒã¿ã§ã¯1件ã«ãªããŸããã
const result = await dynamodb.scan(params).promise(); expect(result.Count).toBe(1); // ã¹ãã£ã³ã®æ»ãå€ãšãªãããŒã¿æ° expect(result.ScannedCount).toBe(5); // ããŒã¿æ° if (result.Items) { const katsuo = result.Items[0] as Person; expect(katsuo.familyId).toBe(1); expect(katsuo.lastName).toBe('磯é'); expect(katsuo.firstName).toBe('ã«ããª'); expect(katsuo.age).toBe(11);
ã¹ãã£ã³ã¯ãããªãšããã§ããããã
ããŒãžã³ã°ãªã©ã¯æ±ã£ãŠããŸãããã䜿ãå Žåã¯ããã¡ãã®èšèŒã«åŸã£ãŠLastEvaluatedKey
ã®çµæãèŠãŠã次ã«å®è¡ããã¹ãã£ã³ã®
ExclusiveStartKey
ã«æå®ããããšããæãã«ãªãããã§ãã
DynamoDB ã§ã®ã¹ãã£ã³ã®æäœ / ããŒãžåäœã®åºå件æ°ãæå®
ãŸãšã
ä»åã¯ãAmazon DynamoDBã®ã¹ãã£ã³ãç°¡åã«è©ŠããŠã¿ãŸããã
ãã©ã€ããªãŒããŒã«é¢ãããããŒã¿ãååŸã§ããŸããããã®ç¹æ§ã«ã¯æ³šæããæ¹ãè¯ãããã§ããã