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)
I just noticed the same thing: there doesn’t seem to be a way to do an
UpdateItem
using aUpdateExpression
with the Enhanced Client.The Enhanced Client’s
DynamoDbTable<T>#updateItem
takes anUpdateItemEnhancedRequest
which 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
TransactWriteItems
with anUpdateItem
using anUpdateExpression
. To be fair, I don’t think this was supported in the v1 SDK either.For now, I’m having to do a
GetItem
so that I can get the full blown entity and update a single attribute before adding it as anUpdateItem
to theTransactWriteItems
.@billydh I see you are using v1
DynamoDBLocal
to run the code, my guess is this is not supported by DynamoDBLocal. I’ll run some tests with the DynamoDB API to be sure.