Мне кажется, что я неправильно использую DynamoDB для этого многополевого PATCH, тем более что решение слишком сложное.
Оставьте это здесь на тот случай, если кто-то найдет это полезным или, что лучше, найдет более подходящее решение:
let fieldsToUpdate = [
// these are just string constants from another file
[dynamoDbFields.cost, apiFields.cost],
[dynamoDbFields.annualSales, apiFields.annualSales],
... ]
// get the new DynamoDB value from the request body (it may not exist)
.map(([dynamoDbField, apiField]) => [dynamoDbField, _.get(requestBody, apiField)])
// filter any keys that are undefined on the request body
.filter(([dynamoDbField, value]) => value !== undefined)
// create a mapping of the field identifier (positional index in this case) to the DynamoDB value, e.g. {':0': '123'}
let expressionAttributeValues = fieldsToUpdate.reduce((acc, [dynamoDbField, value], index) =>
_.assignIn(acc, {[`:${index}`]: value}), {})
// and create the reciprocal mapping of the identifier to the DynamoDB field name, e.g {ID: ':0'}
let updateExpression = fieldsToUpdate.reduce((acc, [dynamoDbField], index) =>
_.assignIn(acc, {[dynamoDbField]: `:${index}`}), {})
const params = {
TableName: TABLE_NAME,
Key: {[dynamoDbFields.id]: _.get(requestBody, apiFields.id)},
UpdateExpression: `set ${Object.entries(updateExpression).map((v) => v.join('=')).join(',')}`,
ExpressionAttributeValues: expressionAttributeValues,
ConditionExpression: `attribute_exists(${dynamoDbFields.id})`,
ReturnValues: 'ALL_NEW'
}