The method you have described is not possible using DynamoDB even with the newly announced transactions. The reason is because your GSI is eventually consistent and may not reflect the most up-to-date state of the items in your table, so no ConditionExpression can be used on a GSI.
However, you can achieve similar functionality by having a separate EmployeeId-InUse table. It could be as simple as a single attribute: employeeId
. Since this is a table rather than a GSI, you can use a TransactWriteItems request to write to your EmployeeData and your EmployeeId-InUse tables at the same time. A transaction will fail if any part of the transaction fails, so you can use a ConditionExpression to Prevent Overwrites of an Existing Item to ensure the transaction will fail if the SSN or the EmployeeId already exists.
Here’s a sample of what the “TransactItems” part of your dynamodb request would look like for this.
“TransactItems”: [
{
“Put” : {
“ConditionExpression” : “attribute_not_exists(ssn)”,
“Item” : {
... employee data goes here ...
},
“TableName”: “EmployeeData”
}
},
{
“Put” : {
“ConditionExpression” : “attribute_not_exists(employeeId)”,
“Item” : {
“employeeId”: {
“S” : “Employee1457”
}
},
“TableName”: “EmployeeIDs-InUse”
}
}
]
There are a couple of things you need to watch out for here. Make sure you update the EmployeeId-InUse
table every time you add or remove an employee and also if you update the employeeId that is associated with a given SSN. Also, be aware that a transaction will consume twice as much capacity as a regular write.