обновить атрибуты в записи Dynamodb

Я пытаюсь обновить существующую запись в таблице Dynamodb. Как показано ниже, у меня есть элемент в моей таблице

let params = {
   TableName: proces.env.dynamoDbTable,
   Item: {
      productId: "id",
      att1: val1,
      att2: val2
      }
 }

Я хочу выполнить обновление. Я использую метод обновления aws Dynamodb sdk и передаю ему параметры, как показано ниже

let aws = require('aws-sdk');
 let dbb = new aws.DynamoDb.DocumentClient();
 let params = {
  TableName: process.env.tableName,
  Key: {productID}
  ExpressionAttributeNames: { "#updatedAt" : "updatedAt" }
  ExpressionAttributeValues: {":u":moment().unix(), ":val1" : a, ":val2": b}
  UpdateExpression: "SET att1 = :val1, att2: val2, #updatedAt: :u"
 }
// a, b are passed as argument to function and are optional
dbb.update(params).promise()

Когда аргумент пропадает, динамо-машина вызывает исключение отсутствия ExpressionAttributeValue, и я знаю, что это правильно. Есть ли способ обновить свой элемент с помощью предоставленных атрибутов


comment
Что вы имеете в виду, говоря, когда пропадает аргумент?   -  person Lucas D    schedule 09.07.2020
comment
Кроме того, An expression attribute name must begin with a pound sign (#), docs.aws.amazon.com/amazondynamodb/latest / developerguide /   -  person Lucas D    schedule 09.07.2020
comment
@LucasD Вот как выглядит мое выражение обновления SET #name =: n, #slug =: s, #updatedAt =: u, description =: d, thumbnail =: t Я получаю запрос от внешнего интерфейса для обновления параметра с именем description . Когда я вызываю метод обновления, он выдает мне код ValidationException с отсутствующими значениями атрибутов: n. Я понимаю, что, поскольку я не передал значение, ожидается ошибка. Как мне обновить только несколько атрибутов, которые я получаю, а остальные оставить нетронутыми?   -  person timer_1995    schedule 10.07.2020
comment
Обновите свой вопрос, указав правильное форматирование. Надеясь, что кто-то другой предложит более элегантное решение   -  person Lucas D    schedule 10.07.2020
comment
@LucasD Обязательно переформатирую вопрос. Спасибо за Ваш ответ. Я попробую и обновлю здесь. :)   -  person timer_1995    schedule 11.07.2020


Ответы (2)


К сожалению, с помощью Dynamodb это не так просто. Но вы можете использовать причудливые js-файлы для динамического создания объекта params:

  // for some object `attrs` we find which keys we need to update
  const keys = Object.keys(attrs);
  const values = Object.values(attrs);

  // get a list of key names and value names to match the dynamodb syntax
  const attributeKeyNames = keys.map((k) => '#key_' + k);
  const attributeValueNames = keys.map((k) => ':val_' + k);

  // create individual expressions for each attribute that needs to be updated
  const expressions = attributeValueNames.map((attr, i) => {
    return `${attributeKeyNames[i]} = ${attr}`;
  });

  // add the SET keyword to the beginning of the string
  // and join all the expressions with a comma
  const UpdateExpression = 'SET ' + expressions.join(', ');

  // I use `zipObject()` from lodash https://lodash.com/docs/4.17.15#zipObject
  // it makes an object map from two arrays where the first is the keys and
  // the second is the values
  const ExpressionAttributeValues = _.zipObject(attributeValueNames, values);
  const ExpressionAttributeNames = _.zipObject(attributeKeyNames, keys);

  // now you have all the params
  const params = {
    TableName,
    Key: {
      uuid,
    },
    UpdateExpression,
    ExpressionAttributeValues,
    ExpressionAttributeNames,
  };
person Lucas D    schedule 10.07.2020

Ответ Лукаса Д. отлично работает. Однако следует помнить о нескольких вещах:

Если вы отправляете объект с уникальным ключом в функцию обновления, вы должны удалить этот ключ перед сопоставлением массивов выражений, иначе он будет включен в запрос и получит сообщение об ошибке:

const newObject = {...originalObject}
delete newObject.unique_key

Если вы не можете или не хотите использовать Lodash, вы можете использовать Object.assign для сопоставления массивов ключей / значений:

const ExpressionAttributeValues = Object.assign(...attributeValueNames.map((k, i) => ({[k]: values[i]})));
const ExpressionAttributeNames = Object.assign(...attributeKeyNames.map((k, i) => ({[k]: keys[i]})));
person FX2000    schedule 04.08.2020