首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有动态属性和原子计数器的DynamoDB.DocumentClient

具有动态属性和原子计数器的DynamoDB.DocumentClient
EN

Stack Overflow用户
提问于 2021-10-11 00:58:48
回答 2查看 307关注 0票数 1

我正在使用一个用例,在这个用例中dynamoDB更新应该:

动态重新插入(如果存在更新,插入(如果不存在)项),而不硬编码项目的components.

  • Use -- DynamoDB文档客户端以简化

  • ,并且在相同的原子操作中,更新一个简单的计数器

我从https://stackoverflow.com/a/63511693/15369972的Daniel的一个出色的实用程序方法开始,它为动态值的更新提供了一个通用的实用工具方法,但是没有原子计数器。

在加载动态值之后,我尝试通过将计数器及其增量器添加到参数对象中来添加原子计数器功能,但是在update时将在计数器中获得一个静态值,而不是在每次调用时增加一个值。

这是哪里出了问题?我使用表名、动态javascript对象和包含散列和排序键的数组调用修改后的update函数:

await update(tableName, jsonObjectToStore, ['myHashKey', 'mySortKey'])

修改后的update方法没有像我所希望的那样递增,它是:

代码语言:javascript
运行
复制
async function update (tableName, item, idAttributeNames) {

    var params = {
        TableName: tableName,
        Key: {},
        ExpressionAttributeValues: {},
        ExpressionAttributeNames: {},
        UpdateExpression: "",
        ReturnValues: "UPDATED_NEW"
    };

    for (const attname of idAttributeNames) {
        params["Key"][attname] = item[attname];
    }

    let prefix = "set ";
    let attributes = Object.keys(item);
    for (let i=0; i<attributes.length; i++) {
        let attribute = attributes[i];
        if (!idAttributeNames.includes(attribute)) {
            params["UpdateExpression"] += prefix + "#" + attribute + " = :" + attribute;
            params["ExpressionAttributeValues"][":" + attribute] = item[attribute];
            params["ExpressionAttributeNames"]["#" + attribute] = attribute;
            prefix = ", ";
        }
    }
    
    // Add the counter
    params["UpdateExpression"] +=  ", #nImports = :nImports + :incr";
    console.log(params["UpdateExpression"])
    
    console.log(params["ExpressionAttributeValues"])
    params["ExpressionAttributeValues"][":incr"] = 1;
    params["ExpressionAttributeValues"][":nImports"] = 0;
    console.log(params["ExpressionAttributeValues"])
        
    console.log(params["ExpressionAttributeNames"])
    params["ExpressionAttributeNames"]["#nImports"] = 'nImports'
    console.log(params["ExpressionAttributeNames"])
    
    await docClient.update

    return await docClient.update(params).promise();
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-10-15 19:45:27

与AWS支持一起找到一个合理的解决方案。他们也不确定如何使用ddb文档客户端来执行原子计数器(相对于有许多文档示例的低级客户机),但建议使用ADD命令,这会产生数字字段原子更新的副作用。

因此,通过下面的示例,我们从要存储的对象构造动态更新,然后在update表达式中追加ADD语句(没有逗号!),并将实际上是数字增量的内容添加到ExpressionAttributeValues for nImports中。就像这样,这应该是一个完整的工作λ示例。有几个console.log语句可以显示正在发生的事情:

代码语言:javascript
运行
复制
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
async function update (tableName, item, idAttributeNames) {
    var params = {
        TableName: tableName,
        Key: {},
        ExpressionAttributeValues: {},
        ExpressionAttributeNames: {},
        UpdateExpression: "",
        ReturnValues: "UPDATED_NEW"
    };

    for (const attname of idAttributeNames) {
        params["Key"][attname] = item[attname];
    }

    let prefix = "set ";
    let attributes = Object.keys(item);
    for (let i=0; i<attributes.length; i++) {
        let attribute = attributes[i];
        if (!idAttributeNames.includes(attribute)) {
            params["UpdateExpression"] += prefix + "#" + attribute + " = :" + attribute;
            params["ExpressionAttributeValues"][":" + attribute] = item[attribute];
            params["ExpressionAttributeNames"]["#" + attribute] = attribute;
            prefix = ", ";
        }
    }
    console.log('params before adding atomic counter is:', params)
    // Add the counter using the ADD syntax
    params["UpdateExpression"] +=  " ADD #nImports :nImports"
    params["ExpressionAttributeValues"][":nImports"] = 1;
    params["ExpressionAttributeNames"]["#nImports"] = 'nImports'

    console.log('params after adding atomic counter is:', params)
    
    try {
        const result = await docClient.update(params).promise();
        console.log('after await, result is ', result);
        return result;
    } catch (err) {
        console.log('err is ', err)
    }
};



exports.handler = async (event) => {
    
    const item = {title: 'sometitle', site_url: "www.amazon.com", key: "G"};
    const body = await update('test_table', item, ['title', 'site_url']);
    const response = {
        statusCode: 200,
        body: JSON.stringify(body),
    };
    return response;
}
票数 0
EN

Stack Overflow用户

发布于 2021-10-16 16:42:40

AWS的好心人做了更多的挖掘工作,并指出了初始代码中的一个错误,在纠正后,应该按照需要使用SET操作符进行增量。

基本上,原始代码没有正确地将变量作为增量的目标。因此,我们添加递增变量的校正版本应该是:

代码语言:javascript
运行
复制
    console.log('params before adding atomic counter is:', params)
    // Add the counter
    params["UpdateExpression"] += ", #nImports = #nImports + :incr";
    params["ExpressionAttributeValues"][":incr"] = 1;
    //params["ExpressionAttributeValues"][":nImports"] = 0;
    params["ExpressionAttributeNames"]["#nImports"] = 'nImports'

    console.log('params after adding atomic counter is:', params)```

I'm sticking with the original ADD answer because I like the differentiation it gives over the properties inserted by the SET, but both seem valid and I wanted to include the correction as well
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69520042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档