Метод, который вы описали, невозможен при использовании DynamoDB даже с недавно объявленными транзакциями. Причина в том, что ваш GSI в конечном итоге непротиворечив и может не отражать самое современное состояние элементов в вашей таблице, поэтому в GSI нельзя использовать выражение ConditionExpression.
Однако , вы можете достичь аналогичной функциональности, имея отдельную таблицу EmployeeId-InUse. Это может быть просто как один атрибут: employeeId
. Поскольку это таблица, а не GSI, вы можете использовать запрос TransactWriteItems для одновременной записи в таблицы EmployeeData и EmployeeId-InUse. Транзакция завершится неудачей, если произойдет сбой какой-либо части транзакции, поэтому вы можете использовать выражение ConditionExpression для Предотвратить перезапись существующего элемента , чтобы гарантировать, что транзакция завершится неудачей, если SSN или EmployeeId уже существует.
Вот пример того, как будет выглядеть часть TransactItems в вашем запросе DynamodB для этого.
“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”
}
}
]
Есть пара вещей, на которые нужно обратить внимание. Обязательно обновляйте таблицу EmployeeId-InUse
при каждом добавлении или удалении сотрудника, а также при обновлении employeeId, связанного с данным SSN. Также имейте в виду, что транзакция потребляет вдвое больше емкости, чем обычная запись.