Skip to content

Instantly share code, notes, and snippets.

@gelin
Created February 20, 2020 15:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gelin/132092fdc821bc87e525842feb179b5c to your computer and use it in GitHub Desktop.
Save gelin/132092fdc821bc87e525842feb179b5c to your computer and use it in GitHub Desktop.
Increment nested number in DynamoDB
import com.amazonaws.services.dynamodbv2.document.PrimaryKey
import com.amazonaws.services.dynamodbv2.document.api.UpdateItemApi
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException
fun UpdateItemApi.nestedIncrement(key: PrimaryKey, attribute: String, path: List<String>, increment: Int) {
tryToIncrement(key, listOf(attribute) + path, increment)
}
private fun List<String>.toPathExpression(): String =
mapIndexed { index, _ -> "#p$index" }.joinToString(".")
private fun List<String>.toNameMap(): Map<String, String> =
mapIndexed { index, name -> "#p$index" to name }.toMap()
private fun UpdateItemApi.tryToIncrement(key: PrimaryKey, path: List<String>, increment: Int) {
val pathExpression = path.toPathExpression()
val attributesMap = path.toNameMap()
try {
updateItem(
key,
"SET $pathExpression = $pathExpression + :inc",
"attribute_exists($pathExpression)",
attributesMap,
mapOf(":inc" to increment)
)
} catch (e: ConditionalCheckFailedException) {
tryToCreateMap(key, path, increment)
}
}
private fun UpdateItemApi.tryToCreateMap(key: PrimaryKey, path: List<String>, value: Any) {
val pathExpression = path.toPathExpression()
val attributesMap = path.toNameMap()
val upperPath = path.dropLast(1)
val upperPathExpression = upperPath.toPathExpression()
if (upperPath.isNotEmpty()) {
try {
updateItem(
key,
"SET $pathExpression = :new",
"attribute_exists($upperPathExpression)",
attributesMap,
mapOf(":new" to value)
)
} catch (e: ConditionalCheckFailedException) {
val lastName = path.last()
tryToCreateMap(key, upperPath, mapOf(lastName to value))
}
} else {
updateItem(
key,
"SET $pathExpression = :new",
attributesMap,
mapOf(":new" to value)
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment