The updateItem method does not work with String Set type
See original GitHub issueI am unable to add item to a String Set type attribute.
Programming Language: Kotlin 1.3.72
Describe the issue
I used to use the standard DynamoDbAsyncClient in the Java SDK v2 to do an update item operation which has a String Set attribute. The update item expression was specified in this way.
val updateItemRequest: UpdateItemRequest = UpdateItemRequest
.builder()
.tableName(tableName)
.key(
mapOf(
"customerId" to AttributeValue.builder().s(eligibilityPersist.customerId).build()
)
)
.updateExpression(
"ADD #eligibility :eligibility " + "SET #eventDateTime = :eventDateTime, #eventId = :eventId"
)
.expressionAttributeNames(
mapOf(
"#eligibility" to "eligibility",
"#eventDateTime" to "eventDateTime",
"#eventId" to "eventId"
)
)
.expressionAttributeValues(
mapOf(
":eligibility" to AttributeValue.builder().ss(eligibilityPersist.eligibility.first()).build(),
":eventDateTime" to AttributeValue.builder().s(eligibilityPersist.eventDateTime).build(),
":eventId" to AttributeValue.builder().s(eligibilityPersist.eventId).build()
)
)
.build()
It works as expected, i.e. if there’s already an existing eligibility attribute, the above update item request appends the new item (if not already in the String Set) to it. I am trying to replicate that using the async client in dynamodb-enhanced package. However, instead of adding it to the existing String Set, it overwrites it entirely.
Please see my code snippet below.
Steps to Reproduce
See this code snippet.
import reactor.core.publisher.Mono
import reactor.kotlin.core.publisher.toMono
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient
import software.amazon.awssdk.enhanced.dynamodb.Expression
import software.amazon.awssdk.enhanced.dynamodb.Key
import software.amazon.awssdk.enhanced.dynamodb.TableSchema
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
@DynamoDbBean
data class EligibilityPersist(
@get:DynamoDbPartitionKey var customerId: String? = null,
var eligibility: MutableSet<String>? = null,
var eventDateTime: String? = null,
var eventId: String? = null
)
class CustomerEligibilityRepo(
client: DynamoDbEnhancedAsyncClient,
tableName: String
) {
private val table = client.table(tableName, ELIGIBILITY_TABLE_SCHEMA)
fun getEligibility(customerId: String): Mono<EligibilityPersist> {
val key = Key.builder()
.partitionValue(customerId)
.build()
return table.getItem(key).toMono()
}
fun updateWithExpression(eligibilityPersist: EligibilityPersist): Mono<EligibilityPersist> {
return table
.updateItem { r ->
r.item(eligibilityPersist)
.ignoreNulls(true)
.conditionExpression(
Expression.builder()
.expression("ADD campaignEligibility = :campaignEligibility")
.putExpressionValue(":campaignEligibility", AttributeValue.builder().ss(eligibilityPersist.eligibility).build())
.build()
)
}
.toMono()
}
fun update(eligibilityPersist: EligibilityPersist): Mono<EligibilityPersist> {
return table
.updateItem { r ->
r.item(eligibilityPersist).ignoreNulls(true)
}
.toMono()
}
companion object {
private val ELIGIBILITY_TABLE_SCHEMA = TableSchema.fromBean(EligibilityPersist::class.java)
}
}
Then, just execute any of the update functions.
Current Behavior
So, the updateWithExpression() does not work with the following error.
"stack_trace":"com.amazonaws.services.dynamodbv2.exceptions.DynamoDBLocalServiceException: Invalid ConditionExpression: Syntax error; token: \"ADD\", near: \"ADD campaignEligibility\"
I guess it does not accept the standard dynamodb update expression syntax, e.g. SET or ADD?
On the other hand, the update() function overwrites the entire String Set.
Your Environment
- AWS Java SDK version used:
2.15.7 - JDK version used:
AdoptOpenJDK 11 - Operating System and version:
MacOS 10.15.7
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (3 by maintainers)

Top Related StackOverflow Question
I just noticed the same thing: there doesn’t seem to be a way to do an
UpdateItemusing aUpdateExpressionwith the Enhanced Client.The Enhanced Client’s
DynamoDbTable<T>#updateItemtakes anUpdateItemEnhancedRequestwhich takes an itemT, i.e. the full-blown entity.It is supported on the AWS SDK v2 client however:
I think the main use case this does not cover is a
TransactWriteItemswith anUpdateItemusing anUpdateExpression. To be fair, I don’t think this was supported in the v1 SDK either.For now, I’m having to do a
GetItemso that I can get the full blown entity and update a single attribute before adding it as anUpdateItemto theTransactWriteItems.@billydh I see you are using v1
DynamoDBLocalto run the code, my guess is this is not supported by DynamoDBLocal. I’ll run some tests with the DynamoDB API to be sure.