1

给定以下 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"
  };

这显然不起作用,因为[inlist_append会触发语法错误。
是否有任何解决方案可以实现这一目标,而不必在先前的请求中获取数据并将其手动添加到列表中?

4

1 回答 1

1

list_append(...)不幸的是,除非该属性本身是一个列表,否则您不能将属性名称用作操作数。我相信你能做的最好的事情就是预先存储myobject正确的类型,然后按预期更新它。

由于这里的存储很便宜并且网络/计算很昂贵,因此您甚至可以复制数据以使其中一个具有正确的形式。

这是一个完整的示例,在哪里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' } ]
}

于 2020-12-04T14:36:42.830 回答