有没有办法用updateItem实现以下几点: 1.如果DynamoDB中不存在属性,请添加属性 2.如果DynamoDB中存在属性,则更新属性 3.如果属性未包含在参数中,请将这些属性保留为它们。
这是一个例子: 这是DynamoDB中的对象:
{
id: "1234",
variable1: "hello",
variable2: "world"
}
以下是我想要更新的输入:
{
id: "1234",
variable1: "hello2",
variable23: "dog" // the variable name "variable23" could be anything
}
以下是我想要实现的DynamoDB中的更新项目:
{
id: "1234",
variable1: "hello2",
variable2: "world",
variable23: "dog"
}
“variable23”可以是任何变量名称作为输入。
请帮忙!我使用node.js,我真的很感激,如果有人能告诉我一些代码如何实现这一点。
谢谢!
答案 0 :(得分:11)
这正是AWS.DynamoDB.DocumentClient的update
方法所做的。
已经有一个示例代码,介绍如何在Node.js中使用update
方法here用于AWS SDK for JavaScript。
例如:
'use strict';
const aws = require('aws-sdk');
// It is recommended that we instantiate AWS clients outside the scope of the handler
// to take advantage of connection re-use.
const docClient = new aws.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => {
const params = {
TableName: "MYTABLE",
Key: {
"id": "1"
},
UpdateExpression: "set variable1 = :x, #MyVariable = :y",
ExpressionAttributeNames: {
"#MyVariable": "variable23"
},
ExpressionAttributeValues: {
":x": "hello2",
":y": "dog"
}
};
docClient.update(params, function(err, data) {
if (err) console.log(err);
else console.log(data);
});
};
答案 1 :(得分:9)
您可以动态更新属性。参见下面的代码。
export const update = (item) => {
console.log(item)
const Item = {
note: "dynamic",
totalChild: "totalChild",
totalGuests: "totalGuests"
};
let updateExpression='set';
let ExpressionAttributeNames={};
let ExpressionAttributeValues = {};
for (const property in Item) {
updateExpression += ` #${property} = :${property} ,`;
ExpressionAttributeNames['#'+property] = property ;
ExpressionAttributeValues[':'+property]=Item[property];
}
console.log(ExpressionAttributeNames);
updateExpression= updateExpression.slice(0, -1);
const params = {
TableName: TABLE_NAME,
Key: {
booking_attempt_id: item.booking_attempt_id,
},
UpdateExpression: updateExpression,
ExpressionAttributeNames: ExpressionAttributeNames,
ExpressionAttributeValues: ExpressionAttributeValues
};
return dynamo.update(params).promise().then(result => {
return result;
})
}
答案 2 :(得分:4)
这是一种实用的方法:
update: async (tableName, item, idAttributeName) => {
var params = {
TableName: tableName,
Key: {},
ExpressionAttributeValues: {},
ExpressionAttributeNames: {},
UpdateExpression: "",
ReturnValues: "UPDATED_NEW"
};
params["Key"][idAttributeName] = item[idAttributeName];
let prefix = "set ";
let attributes = Object.keys(item);
for (let i=0; i<attributes.length; i++) {
let attribute = attributes[i];
if (attribute != idAttributeName) {
params["UpdateExpression"] += prefix + "#" + attribute + " = :" + attribute;
params["ExpressionAttributeValues"][":" + attribute] = item[attribute];
params["ExpressionAttributeNames"]["#" + attribute] = attribute;
prefix = ", ";
}
}
return await documentClient.update(params).promise();
}
答案 3 :(得分:3)
我认为有些例子有点令人困惑。如果我有以下表格列
ID | Name | Age
我想更新 Name
属性并保持 Age
属性不变。
const updateName = async () => {
const aws = require('aws-sdk');
const docClient = new aws.DynamoDB.DocumentClient();
const newName = 'Bob';
const params = {
TableName: 'myTable',
Key: {
ID: 'myId',
},
UpdateExpression: 'set Name = :r',
ExpressionAttributeValues: {
':r': newName,
},
};
await docClient.update(params).promise();
}
updateName();
这看起来更简单一些。
答案 4 :(得分:3)
这里有一个更安全和最新的函数来实现这一点:
const {
DynamoDBClient, UpdateItemCommand,
} = require('@aws-sdk/client-dynamodb');
const { marshall, unmarshall } = require('@aws-sdk/util-dynamodb');
const client = new DynamoDBClient({});
/**
* Update item in DynamoDB table
* @param {string} tableName // Name of the target table
* @param {object} key // Object containing target item key(s)
* @param {object} item // Object containing updates for target item
*/
const update = async (tableName, key, item) => {
const itemKeys = Object.keys(item);
// When we do updates we need to tell DynamoDB what fields we want updated.
// If that's not annoying enough, we also need to be careful as some field names
// are reserved - so DynamoDB won't like them in the UpdateExpressions list.
// To avoid passing reserved words we prefix each field with "#field" and provide the correct
// field mapping in ExpressionAttributeNames. The same has to be done with the actual
// value as well. They are prefixed with ":value" and mapped in ExpressionAttributeValues
// along witht heir actual value
const { Attributes } = await client.send(new UpdateItemCommand({
TableName: tableName,
Key: marshall(key),
ReturnValues: 'ALL_NEW',
UpdateExpression: `SET ${itemKeys.map((k, index) => `#field${index} = :value${index}`).join(', ')}`,
ExpressionAttributeNames: itemKeys.reduce((accumulator, k, index) => ({ ...accumulator, [`#field${index}`]: k }), {}),
ExpressionAttributeValues: marshall(itemKeys.reduce((accumulator, k, index) => ({ ...accumulator, [`:value${index}`]: item[k] }), {})),
}));
return unmarshall(Attributes);
};
答案 5 :(得分:1)
对于这里解决方案的速度模板版本的任何人,他们在他们的文档中记录了一些东西,我花了一段时间才找到,所以如果对其他人有帮助,这里是一个链接
答案 6 :(得分:0)
很抱歉迟到了,但这是 google 上的 [非 aws-documentation] 最高结果,并且没有回答我的用例 - 使用 DocumentClient 而不使用 [un] marshalling 并具有动态项目。所以我想放弃我的 2 美分,并尝试通过合并来自 @khalid-t 的已批准答案和来自 @Arno 的答案来提供帮助。
'use strict';
const aws = require('aws-sdk');
const docClient = new aws.DynamoDB.DocumentClient();
const updateItem = async (pk, item) => await docClient.update({
TableName,
Key: {pk},
UpdateExpression: 'set ' + Object.keys(item).map(k => `#${k} = :${k}`).join(', '),
ExpressionAttributeNames: Object.entries(item).reduce((acc, cur) => ({...acc, [`#${cur[0]}`]: cur[0]}), {}),
ExpressionAttributeValues: Object.entries(item).reduce((acc, cur) => ({...acc, [`:${cur[0]}`]: cur[1]}), {}),
}).promise();
答案 7 :(得分:0)
我使用 dynamo DB 客户端制作的:
updateItem(item: { [key: string]: any }) {
const marshaledItem = marshall(item, { removeUndefinedValues: true, });
const marshaledItemKeys = Object.entries(marshaledItem);
const params: UpdateItemInput = {
TableName: this.tableName,
UpdateExpression: 'set',
ExpressionAttributeNames: {},
ExpressionAttributeValues: {},
Key: marshall({ pk: item.pk, sk: item.sk })
};
marshaledItemKeys.forEach(([key, value] ) => {
if (key === 'sk' || key === 'pk') return;
params.UpdateExpression += ` #${key} = :${key},`;
params.ExpressionAttributeNames[`#${key}`] = key;
params.ExpressionAttributeValues[`:${key}`] = value;
})
params.UpdateExpression = params.UpdateExpression.slice(0, -1);
console.log('REVEAL YOURSELF, YOU MIGHTY BUG: ', params);
return this.dynamoDbClient.send(new UpdateItemCommand(params));
}
这对我来说非常有效。 Marshall 和 unmarshall 是以下内容的一部分:
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';
如果我传递 undefined
的值,它将从查询中删除这些值。如果我保留它们 null
,它会用 null
这是我如何使用它的示例:
async updatePatient(data: PutPatientData): Promise<DBPatient> {
const {
pk,
sk,
databaseId,
betterPatientId,
clinicientPatientId,
latestClinicientCaseId,
firstName,
lastName,
email,
birthday,
gender,
phone,
} = data;
if (!pk && !databaseId) throw Error('Please provide PK or databaseId');
if (!sk && !betterPatientId) throw Error('Please provide SK or betterPatientId');
const patientRequestData = {
pk: pk || `DATABASE#${databaseId}`,
sk: sk || `PATIENT#${betterPatientId}`,
itemType: 'Patient',
lastUpdatedAt: DateTime.now().toString(),
latestClinicientCaseId: latestClinicientCaseId || undefined,
clinicientPatientId: clinicientPatientId || undefined,
firstName: firstName || undefined,
lastName: lastName || undefined,
email: email || undefined,
birthday: birthday || undefined,
gender: gender || undefined,
phone: phone || undefined,
betterPatientId: betterPatientId || undefined,
} as DBPatient;
// Composite key
if (email && birthday) patientRequestData['itemId'] = `PATIENT#${email}#${birthday}`;
console.log('PATIENT UPDATE', patientRequestData)
return this.updateItem(patientRequestData).then(() => patientRequestData);
}