Невозможно записать элемент (ы) в таблицу DynamoDB, используя DocumentClient - Nodejs - PullRequest
0 голосов
/ 23 февраля 2020

Я абсолютно новичок в DynamoDb и пытаюсь просто написать объект из NodeJS Lambda. Исходя из того, что я прочитал и исследовал, я, вероятно, должен использовать DocumentClient из aws-sdk. Я также нашел следующий вопрос , касающийся проблем с DocumentClient, но он, похоже, не решает мою конкретную проблему c .... которую я, к сожалению, не могу найти / определить. Я настроил отладчик, чтобы помочь с локальной разработкой 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, показанном ниже.

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

Когда я пытаюсь сделать sh этот json объект для "Динамо", я получаю сообщения об ошибках:

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)
                    //     })
                })
              })
            })
        })

Ответы [ 4 ]

0 голосов
/ 01 марта 2020

О, я понимаю, что вы хотите.

Может быть, вы видите, что приведенный выше код работает, но есть одна концепция, которую вы должны улучшить в отношении asyn c - ждать и обещать, особенно в отношении лямбда-функции.

У меня есть несколько замечаний из приведенного выше кода, возможно, вы можете подумать над улучшением лямбды:

  1. Использование await для каждого обещания в lambda - не лучший подход, потому что мы знаем ограничение по времени лямбды. Но иногда мы можем сделать это для другого случая.

  2. Может быть, вы можете изменить метод dynamicodb.put, чтобы он был dynamicodb.batchWriteItem:

Операция BatchWriteItem помещает или удаляет несколько элементов в одной или нескольких таблицах.

Или Если вам вместо этого нужно использовать Dynamodb.put, попробуйте улучшить код так:
    const writeSchoolsToDynamo = async (schools) => {
        const promises = schools.map(school => {
            dynamodb.put(school).promise()
        })

        return Promise.all(promises)
    }
0 голосов
/ 28 февраля 2020

Из вашего кода я вижу неправильное обещание по запросу DynamodB. Попробуйте изменить свои строки:

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

на:

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

, которые вы также можете комбинировать с await:

await dynamodb.put(params).promise().then(function(data) {
    console.log(`Success`, data)
})
0 голосов
/ 29 февраля 2020
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
            }
        })
    }
}

Я знаю, что это кардинально отличается от того, с чего я начал, но я немного покопался и вроде как работал над этим ... Я не уверен, что это лучший способ, но мне показалось, что заставить его работать ... Дайте мне знать, если что-то должно измениться!

0 голосов
/ 23 февраля 2020

Можете ли вы попробовать без типа?

Вместо

    "School":{"S": team_name},

, например, используйте

    "School": team_name,
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...