Node.js 无法使用DocumentClient-Nodejs将项写入DynamoDB表

Node.js 无法使用DocumentClient-Nodejs将项写入DynamoDB表,node.js,amazon-dynamodb,aws-sdk,Node.js,Amazon Dynamodb,Aws Sdk,我对DynamoDb绝对是一个新手,我试图简单地从NodeJS Lambda编写一个对象。根据我所阅读和研究的内容,我可能应该使用aws sdk中的DocumentClient。我在这里还发现了以下与DocumentClient有关的问题,但它似乎没有解决我的具体问题……不幸的是,我真的找不到/准确指出这些问题。我已经设置了一个调试器来帮助SAM本地开发,但它似乎只提供了一些错误 代码的实现如下所示 var params = { TableName: "March-Madness-Te

我对DynamoDb绝对是一个新手,我试图简单地从NodeJS Lambda编写一个对象。根据我所阅读和研究的内容,我可能应该使用
aws sdk
中的
DocumentClient
。我在这里还发现了以下与DocumentClient有关的问题,但它似乎没有解决我的具体问题……不幸的是,我真的找不到/准确指出这些问题。我已经设置了一个调试器来帮助SAM本地开发,但它似乎只提供了一些错误

代码的实现如下所示

var params = {
     TableName: "March-Madness-Teams",
     Item: {
        "Id": {"S": randstring.generate(9)},
        "School":{"S": team_name},
        "Seed": {"S": seed},
        "ESPN_Id": {"S": espn_id}
      }
    }
  console.log(JSON.stringify(params))

   dynamodb.put(params, (error,data) => {
      if (error) {
         console.log("Error ", error)
      } else {
         console.log("Success! ", data)
      }
   })
基本上,我正在使用cheerio库和cherry从DOM中提取值并将它们保存到json对象中,如下所示

{
  "TableName": "March-Madness-Teams",
  "Item": {
    "Id": {
      "S": "ED311Oi3N"
    },
    "School": {
      "S": "BAYLOR"
    },
    "Seed": {
      "S": "1"
    },
    "ESPN_Id": {
      "S": "239"
    }
  }
}
当我试图将这个json对象推送到Dynamo时,会出现错误

Error  MultipleValidationErrors: There were 2 validation errors:
* MissingRequiredParameter: Missing required key 'TableName' in params
* MissingRequiredParameter: Missing required key 'Item' in params
上面的错误其实都是好的……我想它不喜欢我将这些内容打包成字符串的事实,所以我删除了引号并发送了以下内容

{
  TableName: "March-Madness-Teams",
  Item: {
    "Id": {
      "S": "ED311Oi3N"
    },
    "School": {
      "S": "BAYLOR"
    },
    "Seed": {
      "S": "1"
    },
    "ESPN_Id": {
      "S": "239"
    }
  }
}
然而,当我这么做的时候……我什么也得不到

下面是一个较大的代码片段

return new Promise((resolve,reject) => {
            axios.get('http://www.espn.com/mens-college-basketball/bracketology')
            .then(html => {

                const dynamodb = new aws.DynamoDB.DocumentClient()

                let $ = cheerio.load(html.data)
                $('.region').each(async function(index, element){
                    var preregion = $(element).children('h3,b').text()
                    var region = preregion.substr(0, preregion.indexOf('(') - 1)

                    $(element).find('a').each(async function(index2, element2){
                        var seed = $(element2).siblings('span.rank').text()
                    if (seed.length > 2){
                        seed = $(element2).siblings('span.rank').text().substring(0, 2)
                    }

                    var espn_id = $(element2).attr('href').split('/').slice(-2)[0]
                    var team_name = $(element2).text()
                    var params = {
                        TableName: "March-Madness-Teams",
                        Item: {
                            "Id": randstring.generate(9),
                            "School":team_name,
                            "Seed": seed,
                            "ESPN_Id": espn_id
                        }
                    }
                    console.log(JSON.stringify(params))

                    // dynamodb.put(params)
                    //     .then(function(data) {
                    //         console.log(`Success`, data)
                    //     })
                })
              })
            })
        })

你能不带这个型号试试吗

而不是

    "School":{"S": team_name},
例如,使用

    "School": team_name,

从您的代码中,我可以看到dynamodb请求中的错误承诺。尝试更改您的行:

dynamodb.put(params).then(function(data) {
    console.log(`Success`, data)
})
将是:

dynamodb.put(params).promise().then(function(data) {
    console.log(`Success`, data)
})
您也可以与Wait结合使用:

await dynamodb.put(params).promise().then(function(data) {
    console.log(`Success`, data)
})

我知道这和我刚开始做的有很大的不同,但我做了一些进一步的挖掘,并对此进行了一些工作……我不确定这是否是最好的方法,但我似乎已经开始工作了……让我知道是否应该改变一些事情

哦,我知道你想要什么

也许您可以看到上面的代码是有效的,但是这里有一个关于async-await和promise的概念需要改进,特别是在lambda函数上

我这里有一些您上面代码中的注释,也许可以作为您改进lambda的考虑因素:

  • 在lambda中使用wait for every promise不是最好的方法,因为我们知道lambda的时间限制。但有时我们可以在其他情况下这样做

  • 也许您可以将dynamodb.put方法更改为dynamodb.batchWriteItem:

  • 或者,如果必须使用dynamodb.put,请尝试对代码进行如下改进:

  • 看起来不错,只需再次检查您的调试点和aws文档示例,您可以显示更多的代码吗?根据您的一条评论,听起来您可能正在将异步与回调相结合。好了,@JasonWadsworth。用更多的源代码编辑了原始帖子。这是在网页上运行,还是在NodeJS服务器上运行?它现在只是一个lambda函数,但将支持一个网页。运气不好…..调试时,它转到我开始调用put API的地方,但当我尝试遍历时,它只是完全跳过回调。即使我在整个dynamodb api代码段中都有断点:(就像Jason说我错过了一些重要的等待…我花了一些时间,重新构造了很多代码,使其更具可读性和潜在意义。我将更新帖子以反映更改并接受它。如果您或任何人看到可能/应该更改的内容,请告诉我!嘿,Mahdi,我尝试了您的代码片段,但它仍然存在。)id不工作。函数成功完成,但是没有任何数据被写入表中…想法?老实说,我没有测试上面的代码。我只是提供了一个想法运行异步/并行多进程(这里您运行多个dynamodb.put)。在您的代码中,您通过wait运行同步进程。这意味着,如果我们有5个put每个需要1,则您的代码执行它们序列化并需要5个。通过并行方式,它们可以在5个put中按avg+-1进行处理。也许您可以尝试更改我的代码:const promises=schools.map(school=>{dynamodb.put(school.promise())to be const promises=schools.map(school=>{return dynamodb.put(school.promise()})
    exports.lambdaHandler = async (event, context) => {
        const html = await axios.get('http://www.espn.com/mens-college-basketball/bracketology')
        let $ = cheerio.load(html.data)
        const schools = buildCompleteSchoolObject(html, $)
        try {
            await writeSchoolsToDynamo(schools)
            return { statusCode: 200 }
        } catch (error) {
            return { statusCode: 400, message: error.message }
        }
    }
    
    const writeSchoolsToDynamo = async (schools) => {
            const promises = schools.map(async school => {
                await dynamodb.put(school).promise()
            })
    
            await Promise.all(promises)
    }
    
    const buildCompleteSchoolObject = (html, $) => {
        const schools = []
    
        $('.region').each(loopThroughSubRegions(schools, $))
        return schools
    }
    const loopThroughSubRegions = (schools, $) => {
        return (index, element) => {
            var preregion = $(element).children('h3,b').text()
            var region = preregion.substr(0, preregion.indexOf('(') - 1)
            $(element).find('a').each(populateSchoolObjects(schools, $))
        }
    }
    const populateSchoolObjects = (schools, $) => {
        return (index, element) => {
            var seed = $(element).siblings('span.rank').text()
            if (seed.length > 2) {
                seed = $(element).siblings('span.rank').text().substring(0, 2)
            }
            var espn_id = $(element).attr('href').split('/').slice(-2)[0]
            var team_name = $(element).text()
            schools.push({
                TableName: "March-Madness-Teams",
                Item: {
                    "Id": randstring.generate(9),
                    "School": team_name,
                    "Seed": seed,
                    "ESPN_Id": espn_id
                }
            })
        }
    }
    
        const writeSchoolsToDynamo = async (schools) => {
            const promises = schools.map(school => {
                dynamodb.put(school).promise()
            })
    
            return Promise.all(promises)
        }