在DynamoDB中,您可以UpdateItem忽略未定义的值吗?

时间:2018-11-28 15:45:02

标签: node.js amazon-dynamodb

DynamoDB用于管理可能提供1个或更多属性的PATCH请求。我希望这些属性在请求中存在时进行更新,否则在更新中将其忽略。 DocumentClient.update(params),其中params是:

    TableName: '...',
    Key: {...},
    UpdateExpression: `set 
      Cost = :Cost,
      Sales = :Sales,
      ...
    ExpressionAttributeValues: {
      ':Cost': get(requestBody, 'form.cost', undefined),
      ':Sales': get(requestBody, 'form.sales', undefined),
      ...
    }

这是否只能通过manipulating the expression strings实现?

1 个答案:

答案 0 :(得分:0)

我觉得我在此多字段PATCH中使用的DynamoDB错误,特别是因为解决方案过于复杂。

如果有其他人发现它有帮助或更好的解决方案,请留在这里,以解决问题:

  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'
  }