Created
May 2, 2019 18:23
-
-
Save robzhu/aee623cf161f67223c4a91e4deee30ec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// credentials are stored in a .env file with the following contents: | |
// | |
// accessKeyId= | |
// secretAccessKey= | |
// region= | |
// tableName= | |
// See: https://github.com/motdotla/dotenv | |
require("dotenv").config(); | |
import * as AWS from "aws-sdk"; | |
import { ConfigurationOptions } from "aws-sdk/lib/config"; | |
const AwsConfig = { | |
accessKeyId: process.env.accessKeyId, | |
secretAccessKey: process.env.secretAccessKey, | |
region: process.env.region | |
}; | |
AWS.config.update(AwsConfig as ConfigurationOptions); | |
const DynamoDB = new AWS.DynamoDB.DocumentClient(); | |
const TableName = process.env.tableName; | |
interface Person { | |
id: string; | |
name: string; | |
friends: string[]; | |
} | |
async function writeInitialDoc() { | |
await DynamoDB.put({ | |
TableName, | |
Item: { | |
id: "1234", | |
name: "carl", | |
friends: ["meatwad", "frylock", "shake"] | |
} | |
}).promise(); | |
} | |
async function writeDocWithSet() { | |
await DynamoDB.put({ | |
TableName, | |
Item: { | |
id: "1234", | |
name: "carl", | |
friends: DynamoDB.createSet(["meatwad", "frylock", "shake"]) | |
} | |
}).promise(); | |
const result = await DynamoDB.get({ | |
TableName, | |
Key: { id: "1234" } | |
}).promise(); | |
console.log(result.Item.friends); | |
console.log(typeof result.Item.friends); | |
console.log(Array.isArray(result.Item.friends.values)); | |
} | |
async function removeFriendByValue(friendName: string) { | |
const Key = { id: "1234" }; | |
// fetch the document | |
let result = await DynamoDB.get({ | |
TableName, | |
Key | |
}).promise(); | |
// find the index | |
const indexToRemove = result.Item.friends.indexOf(friendName); | |
if (indexToRemove === -1) { | |
// element not found | |
return; | |
} | |
// remove-by-index | |
await DynamoDB.update({ | |
TableName, | |
Key, | |
UpdateExpression: `REMOVE friends[${indexToRemove}]` | |
}).promise(); | |
} | |
// helper function to return the error in a promise | |
async function updateWithErrorWrapper(params: any): Promise<any> { | |
return new Promise(resolve => { | |
DynamoDB.update(params, (err, data) => { | |
resolve({ err, data }); | |
}); | |
}); | |
} | |
async function conditionalRemoveFriendByValue(friendName: string) { | |
const Key = { id: "1234" }; | |
// fetch the document | |
let result = await DynamoDB.get({ | |
TableName, | |
Key | |
}).promise(); | |
// find the index | |
let indexToRemove = result.Item.friends.indexOf(friendName); | |
if (indexToRemove === -1) { | |
// element not found | |
return false; | |
} | |
// remove-by-index IFF the attribute contains the element we want to remove. | |
const { err, data } = await updateWithErrorWrapper({ | |
TableName, | |
Key, | |
UpdateExpression: `REMOVE friends[${indexToRemove}]`, | |
ConditionExpression: `friends[${indexToRemove}] = :valueToRemove`, | |
ExpressionAttributeValues: { | |
":valueToRemove": friendName | |
} | |
}); | |
if (err) { | |
if (err.code === "ConditionalCheckFailedException") { | |
console.error("condition expression failed"); | |
} else { | |
console.error("unhandled error: " + err); | |
} | |
return false; | |
} | |
return true; | |
} | |
async function conditionalVersionRemoveFriendByValue(friendName: string) { | |
const Key = { id: "1234" }; | |
// fetch the document | |
let document = (await DynamoDB.get({ | |
TableName, | |
Key | |
}).promise()).Item; | |
// find the index | |
let indexToRemove = document.friends.indexOf(friendName); | |
let version = document.version; | |
if (indexToRemove === -1) { | |
// element not found | |
return false; | |
} | |
// remove-by-index IFF the version field matches | |
const { err, data } = await updateWithErrorWrapper({ | |
TableName, | |
Key, | |
UpdateExpression: ` | |
REMOVE friends[${indexToRemove}] | |
ADD version :incrementVersionBy | |
`, | |
ConditionExpression: `version = :version`, | |
ExpressionAttributeValues: { | |
":version": version, | |
":incrementVersionBy": 1 | |
} | |
}); | |
if (err) { | |
if (err.code === "ConditionalCheckFailedException") { | |
console.error("condition expression failed"); | |
} else { | |
console.error("unhandled error: " + err); | |
} | |
return false; | |
} | |
return true; | |
} | |
async function deleteFriendByValue(friendName: string) { | |
const Key = { id: "1234" }; | |
// fetch the document | |
let result = await DynamoDB.get({ | |
TableName, | |
Key | |
}).promise(); | |
// Delete the value from the set. This operation is idempotent and will not | |
// produce an error if the value(s) are missing. | |
const { err, data } = await updateWithErrorWrapper({ | |
TableName, | |
Key, | |
UpdateExpression: `DELETE friends :valuesToRemove`, | |
ExpressionAttributeValues: { | |
":valuesToRemove": DynamoDB.createSet([friendName]) | |
} | |
}); | |
if (err) { | |
console.error("unhandled error: " + err); | |
return false; | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment