簡體   English   中英

無法使用 DocumentClient - Nodejs 將項目寫入 DynamoDB 表

[英]Unable to write item(s) to DynamoDB table utilizing DocumentClient - Nodejs

我對 DynamoDb 絕對是全新的,我正在嘗試簡單地從 NodeJS Lambda 編寫一個 object。根據我閱讀和研究的內容,我可能應該使用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 庫和 DOM 中的櫻桃采摘值清理網站,並將它們保存到如下所示的 json object 中。

{
  "TableName": "March-Madness-Teams",
  "Item": {
    "Id": {
      "S": "ED311Oi3N"
    },
    "School": {
      "S": "BAYLOR"
    },
    "Seed": {
      "S": "1"
    },
    "ESPN_Id": {
      "S": "239"
    }
  }
}

當我嘗試將此 json object 推送到 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 請求中看到 mis promise。 嘗試改變你的台詞:

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

成為:

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

你也可以結合等待:

await dynamodb.put(params).promise().then(function(data) {
    console.log(`Success`, data)
})
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
            }
        })
    }
}

我知道這與我開始時的做法截然不同,但我做了更多的挖掘工作,並為此做了一些工作……我不確定這是否是最好的方法,但我似乎讓它起作用了…… .讓我知道是否應該改變!

哦,我明白你想要什么。

也許您可以看到上面的代碼有效,但是這里有一個關於異步的概念您必須改進 - await 和 promise,尤其是 lambda function。

我在上面的代碼中有一些注釋,也許可以作為你改進 lambda 的考慮:

  1. 對 lambda 中的每個 promise 使用 await 並不是最好的方法,因為我們知道 lambda 的時間限制。 但有時我們可以為其他情況這樣做。

  2. 也許您可以將 dynamodb.put 方法更改為 dynamodb.batchWriteItem:

BatchWriteItem 操作在一個或多個表中放置或刪除多個項目。

  1. 或者,如果您必須改為使用 dynamodb.put,請嘗試將代碼改進為如下所示:
    const writeSchoolsToDynamo = async (schools) => {
        const promises = schools.map(school => {
            dynamodb.put(school).promise()
        })

        return Promise.all(promises)
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM