我正在使用DynamoDB UpdateItem更新数据库中的记录。像这样的基本功能对我有用。
var user = {
userID: '123213',
name: 'John Doe',
age: 12,
type: 'creator'
};
var params = {
TableName:table,
Key:{
"UserID": user.userID
},
UpdateExpression: "set Name = :r, Age=:p, Type=:a",
ExpressionAttributeValues:{
":r":user.name,
":p":user.age,
":a":user.type
},
ReturnValues:"UPDATED_NEW"
};
docClient.update(params, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
});
可是...
如果我只想更新一个属性,名称就像这样:
var user = {
userID: '123213',
name: 'John Smith'
};
var params = {
TableName:table,
Key:{
"UserID": user.userID
},
UpdateExpression: "set Name = :r, Age=:p, Type=:a",
ExpressionAttributeValues:{
":r":user.name,
":p":user.age,
":a":user.type
},
ReturnValues:"UPDATED_NEW"
};
它给了我错误
ExpressionAttributeValues不能为NULL 。
我知道我可以通过检查用户的值来动态生成UpdateExpression
字符串,如下所示:
for (var key in user) {
if (user.hasOwnProperty(key)) {
...add to DynamicUpdateExpression..
}
}
但有没有办法告诉updateItem忽略空值并只更新name
?
答案 0 :(得分:2)
我问了同样的问题......在Java中有SaveBehavior.UPDATE_SKIP_NULL_ATTRIBUTES,但我在aws-sdk中找不到类似于nodejs的内容。
您可以使用 AttributeUpdates 代替 UpdateExpression 来制作更清晰的解决方法:
const AWS = require(aws-sdk);
const bluebird = require('bluebird');
const _ = require('lodash');
AWS.config.setPromisesDependency(bluebird);
const dynamodb = new AWS.DynamoDB.DocumentClient();
var skipNullAttributes = (attributes) => {
return _.omitBy(attributes, (attr) => {
return _.isNil(attr.Value);
});
}
var update = (id, attributes) => {
var params = {
TableName : 'MyTableName',
Key : { id: id },
AttributeUpdates: skipNullAttributes(attributes)
};
return dynamodb.update(params).promise();
}
exports.handler = (event, context, callback) => {
var body = JSON.parse(event.body);
var userId = event.pathParameters.id;
var attributes = {
firstName: { Action: 'PUT', Value: body.firstName },
lastName : { Action: 'PUT', Value: body.lastName }
};
update(userId, attributes)
.then((result) => console.log(result) )
.catch((error) => console.error(error) );
callback(null, {statusCode: 200, body: JSON.stringify({message: 'done!'})});
}
答案 1 :(得分:1)
这是一个简单得多的答案。
当您将ExpressionAttributeValues视为一个对象时,它将起作用。
代码如下:
params.TableName = ddbTable;
params.UpdateExpression = "set LastPostedDateTime = :l" ;
if (req.body.AttachmentDescription) { params.UpdateExpression += ", AttachmentDescription = :d"; }
if (req.body.AttachmentURL) { params.UpdateExpression += ", AttachmentURL = :a"; }
因此,首先,我们使用一种简单的串联技术来构建是否可以传递值的表达式。
然后我们提供值:
params.ExpressionAttributeValues = {};
params.ExpressionAttributeValues[':l'] = formattedDate ;
if (req.body.AttachmentDescription) { params.ExpressionAttributeValues[':d']= req.body.AttachmentDescription ; }
if (req.body.AttachmentURL) { params.ExpressionAttributeValues[':a']= req.body.AttachmentURL ; }
难点在于ExpressionAttributeValues,在这里,我们将其视为对象,并且如果我们首先将其定义为对象,则可以将其添加到对象,因此将{}。
然后,如果对象尚不具有属性名称,则将其添加,然后添加值。
最终结果是,您的记录可以很宽,因为可以使用可变字段名称扩展记录。即该应用程序列出了URL和描述符。使用可变字段名称,我可以在同一记录中添加更多URL和描述符。最终会有一个内存限制,但是对于一些可变字段而言,这种类型的应用程序对于我的应用程序而言已足够。
答案 2 :(得分:0)
通过向我的documentClient
构造函数传递附加选项,我设法获得了预期的结果。
const documentClient = new AWS.DynamoDB.DocumentClient({convertEmptyValues: true});
这会将空字符串转换为true
(在dynamodb世界中也称为NULL
),并且我的http请求json对象中不存在的字段不会影响数据库或导致请求失败。
答案 3 :(得分:0)
我发现了另一种受@David White的回答启发的方法。此外,OP非常接近动态编写UpdateExpression和ExpressionAttributeValues的方法。这是关于如何制作动态更新表达式的代码,无论您具有什么属性。
const create = (req, context, callback) => {
const data = JSON.parse(req.body)
const params = {
TableName: process.env.DYNAMODB_TABLE,
Key: { title: data.title },
};
params.UpdateExpression = "SET latestUpdate = :updateTime"
params.ExpressionAttributeValues = {}
for (let k in data) {
if (k !== 'title') {
// you don't want to update whatever you've set as your primary key for the table, so you have to ignore this
params.UpdateExpression += `, ${k} = :${k}`
params.ExpressionAttributeValues[`:${k}`] = data[k]
}
}
params.ExpressionAttributeValues[':updateTime'] = Date.now()
dynamodb.update(params)