UpdateExpression:将其他属性的值添加到列表
UpdateExpression: Add other attribute's value to list
给定以下 DynamoDB 文档:
{
"myobject" : {"foo" : "bar"},
"mylist" : [{"some" : "stuff}]
}
我的目标是更新此文档以获得以下结果:
{
"myobject" : {"foo" : "bar"},
"mylist" : [{"some" : "stuff}, {"foo" : "bar"}]
}
我请求的参数如下所示:
let params = {
TableName: doctorSlotsTable,
Key: {
hashKey: hash,
rangeKey: range
},
UpdateExpression: 'SET mylist = list_append(if_not_exists(mylist, :empty_list), [myobject])',
ExpressionAttributeValues : {
':empty_list' : []
},
ReturnValues : "UPDATED_NEW"
};
这显然是行不通的,因为 list_append
中的 [
触发了语法错误。
是否有任何解决方案可以实现这一点,而无需获取先前请求中的数据并将其手动添加到列表中?
不幸的是,您不能将属性名称用作 list_append(...)
的操作数,除非该属性本身是一个列表。我相信你能做的最好的事情就是预先将 myobject
存储在正确的类型中,然后按预期更新它。
由于这里的存储很便宜,network/compute 很贵,您甚至可以复制数据以使用正确的格式之一。
这是一个完整的示例,其中 createTable()
和 deleteTable()
完全符合您的想法:
const PK = 'the item';
async function createObjAndList() {
const docClient = new DocumentClient();
const myObject = { foo: "bar" };
const theItem = {
PK,
myObject,
myObjectAsList: [ myObject ],
myList: [ { some : "stuff" } ],
};
const putParams = {
TableName,
Item: theItem
}
await docClient.put(putParams).promise();
console.log(`Put item ${util.inspect(theItem)}`);
}
async function updateListWithObject() {
const docClient = new DocumentClient();
const updateParams = {
TableName,
Key: { PK },
UpdateExpression: `SET #myList = list_append(if_not_exists(#myList, :emptyList), #myObjectAsList)`,
ExpressionAttributeNames: {
'#myList': 'myList',
'#myObjectAsList': 'myObjectAsList',
},
ExpressionAttributeValues: {
':emptyList': [],
}
}
await docClient.update(updateParams).promise();
console.log(`Updated list to include object`);
}
async function getObjAndList() {
const docClient = new DocumentClient();
const results = await docClient.get({ TableName, Key: { PK }}).promise();
console.log(`Item is now: ${util.inspect(results.Item)}`);
}
if (module === require.main) {
(async () => {
try {
await createTable();
await createObjAndList()
await updateListWithObject();
await getObjAndList();
} catch (err) {
console.log(`Error: ${err.message}`);
} finally {
await deleteTable();
}
})();
}
这个输出是:
Put item {
PK: 'the item',
myObject: { foo: 'bar' },
myObjectAsList: [ { foo: 'bar' } ],
myList: [ { some: 'stuff' } ]
}
Updated list to include object
Item is now: {
myList: [ { some: 'stuff' }, { foo: 'bar' } ],
myObject: { foo: 'bar' },
PK: 'the item',
myObjectAsList: [ { foo: 'bar' } ]
}
给定以下 DynamoDB 文档:
{
"myobject" : {"foo" : "bar"},
"mylist" : [{"some" : "stuff}]
}
我的目标是更新此文档以获得以下结果:
{
"myobject" : {"foo" : "bar"},
"mylist" : [{"some" : "stuff}, {"foo" : "bar"}]
}
我请求的参数如下所示:
let params = {
TableName: doctorSlotsTable,
Key: {
hashKey: hash,
rangeKey: range
},
UpdateExpression: 'SET mylist = list_append(if_not_exists(mylist, :empty_list), [myobject])',
ExpressionAttributeValues : {
':empty_list' : []
},
ReturnValues : "UPDATED_NEW"
};
这显然是行不通的,因为 list_append
中的 [
触发了语法错误。
是否有任何解决方案可以实现这一点,而无需获取先前请求中的数据并将其手动添加到列表中?
不幸的是,您不能将属性名称用作 list_append(...)
的操作数,除非该属性本身是一个列表。我相信你能做的最好的事情就是预先将 myobject
存储在正确的类型中,然后按预期更新它。
由于这里的存储很便宜,network/compute 很贵,您甚至可以复制数据以使用正确的格式之一。
这是一个完整的示例,其中 createTable()
和 deleteTable()
完全符合您的想法:
const PK = 'the item';
async function createObjAndList() {
const docClient = new DocumentClient();
const myObject = { foo: "bar" };
const theItem = {
PK,
myObject,
myObjectAsList: [ myObject ],
myList: [ { some : "stuff" } ],
};
const putParams = {
TableName,
Item: theItem
}
await docClient.put(putParams).promise();
console.log(`Put item ${util.inspect(theItem)}`);
}
async function updateListWithObject() {
const docClient = new DocumentClient();
const updateParams = {
TableName,
Key: { PK },
UpdateExpression: `SET #myList = list_append(if_not_exists(#myList, :emptyList), #myObjectAsList)`,
ExpressionAttributeNames: {
'#myList': 'myList',
'#myObjectAsList': 'myObjectAsList',
},
ExpressionAttributeValues: {
':emptyList': [],
}
}
await docClient.update(updateParams).promise();
console.log(`Updated list to include object`);
}
async function getObjAndList() {
const docClient = new DocumentClient();
const results = await docClient.get({ TableName, Key: { PK }}).promise();
console.log(`Item is now: ${util.inspect(results.Item)}`);
}
if (module === require.main) {
(async () => {
try {
await createTable();
await createObjAndList()
await updateListWithObject();
await getObjAndList();
} catch (err) {
console.log(`Error: ${err.message}`);
} finally {
await deleteTable();
}
})();
}
这个输出是:
Put item {
PK: 'the item',
myObject: { foo: 'bar' },
myObjectAsList: [ { foo: 'bar' } ],
myList: [ { some: 'stuff' } ]
}
Updated list to include object
Item is now: {
myList: [ { some: 'stuff' }, { foo: 'bar' } ],
myObject: { foo: 'bar' },
PK: 'the item',
myObjectAsList: [ { foo: 'bar' } ]
}