如何动态更新动态模型项中的属性?

如何动态更新动态模型项中的属性?

问题描述:

我使用Node js在dynamodb中创建了一个项目,该项目具有多个属性,例如品牌,类别,折扣,有效性等。我正在使用uuid为每个项目生成ID。现在,假设我要更新商品的validity属性,在这种情况下,我当前正在发送将validity值修改为新值的整个json对象。

I created an item in dynamodb using Node js, the item has multiple attributes such as brand, category, discount, validity, etc. I am using uuid to generate ids for each item. Now let's say I want to update the validity attribute of the item, in which case I am currently sending the entire json object with the value of validity modified to the new value.

这绝对不是最佳选择,请帮助我找到最佳解决方案。

This is definitely not optimal, please help me find an optimal solution.

const params = {
    TableName: process.env.PRODUCT_TABLE,
    Key: {
      id: event.pathParameters.id,
    },
    ExpressionAttributeNames: {
      '#discount': 'discount',
    },
    ExpressionAttributeValues: {
      ':brand': data.brand,
      ':category': data.category,
      ':discount': data.discount,
      ':denominations': data.denominations,
      ":validity": data.validity,
      ":redemption": data.redemption    
    },
    UpdateExpression: 'SET #discount = :discount, denominations = :denominations, brand = :brand, category = :category, validity = :validity, redemption = :redemption',
    ReturnValues: 'ALL_NEW',
  };

如果要更改,我只想发送要使用新值更新的属性从6个月到8个月的有效期,我应该发送以下信息:
{
validity: 8 months
}
并且它应该更新该项目。
该项目的任何其他属性应相同。

I want to send just the attribute I want to update with the new value, if I want to change the validity from 6 months to 8 months, I should just send something like: { "validity": "8 months" } And it should update the validity attribute of the item. Same should apply to any other attribute of the item.

'use strict';

const AWS = require('aws-sdk');

const dynamoDb = new AWS.DynamoDB.DocumentClient();

module.exports.update = (event, context, callback) => {
  const data = JSON.parse(event.body);

  let attr = {};
  let nameobj = {};
  let exp = 'SET #';
  let arr = Object.keys(data);
  let attrname = {};

  arr.map((key) => {attr[`:${key}`]=data[key]});

  arr.map((key) => {
    exp += `${key} = :${key}, `
  });

  arr.map((key) => {nameobj[`#${key}`]=data[key]});

  attrname = {
    [Object.keys(nameobj)[0]] : nameobj[Object.keys(nameobj)[0]]
  }

  const params = {
    TableName: process.env.PRODUCT_TABLE,
    Key: {
      id: event.pathParameters.id,
    },
    ExpressionAttributeNames: attrname,
    ExpressionAttributeValues: attr,
    UpdateExpression: exp,
    ReturnValues: 'ALL_NEW',
  };

  // update the todo in the database
  dynamoDb.update(params, (error, result) => {
    // handle potential errors
    if (error) {
      console.error(error);
      callback(null, {
        statusCode: error.statusCode || 501,
        headers: { 'Content-Type': 'text/plain' },
        body: 'Couldn\'t update the card',
      });
      return;
    }

    // create a response
    const response = {
      statusCode: 200,
      body: JSON.stringify(result.Attributes),
    };
    callback(null, response);
  });
};


与其他评论相反,这很有可能,使用 UpdateItem 操作。

Contrary to others comments, this is very possible, use the UpdateItem action.

语言不可知的API文档

JavaScript特定的API文档

如果要动态创建查询,请尝试以下操作:

If you want to dynamically create the query, try something like this:

const generateUpdateQuery = (fields) => {
    let exp = {
        UpdateExpression: 'set',
        ExpressionAttributeNames: {},
        ExpressionAttributeValues: {}
    }
    Object.entries(fields).forEach(([key, item]) => {
        exp.UpdateExpression += ` #${key} = :${key},`;
        exp.ExpressionAttributeNames[`#${key}`] = key;
        exp.ExpressionAttributeValues[`:${key}`] = item
    })
    exp.UpdateExpression = exp.UpdateExpression.slice(0, -1);
    return exp
}

let data = {
    'field' : { 'subfield': 123 },
    'other': '456'
}

let expression = generateUpdateQuery(data)

let params = {
    // Key, Table, etc..
    ...expression
}

console.log(params)

输出:

{ 
    UpdateExpression: 'set #field = :field, #other = :other',
    ExpressionAttributeNames: {
        '#field': 'field',
        '#other': 'other'
    },
    ExpressionAttributeValues: {
        ':field': { 
            'subfield': 123
        },
        ':other': '456'
    } 
}