【问题标题】:DynamoDB scan returns multiple scan resultsDynamoDB 扫描返回多个扫描结果
【发布时间】:2020-07-01 00:45:22
【问题描述】:

所以我写了下面的函数。这个版本有点删节,我已经对数据进行了匿名化,但关键组件在那里。

该函数基本上从 API-Gateway 调用中获取参数列表,为每个参数查询一个 db,然后返回结果。

我发现扫描使用一个参数运行完美,但在调用超过 1 个时返回重复数据。从日志中我可以看到,当传递多个参数时,扫描会运行多次

例如,使用一个参数,函数日志返回

2020-03-19 20:27:42.974 Starting the 0 scan with 3 as the id 
2020-03-19 20:27:43.047 The 0 scan has completed successfully

有两个参数的日志是

2020-03-19 20:28:42.189 Starting the 0 scan with 2 as the id
2020-03-19 20:28:42.261 The 0 scan has completed successfully
2020-03-19 20:28:42.262 Starting the 1 scan with 3 as the id
2020-03-19 20:28:42.267 The 0 scan has completed successfully
2020-03-19 20:28:42.293 The 1 scan has completed successfully

并且有 3 个参数的日志是

2020-03-19 20:29:49.209 Starting the 0 scan with 1 as the id
2020-03-19 20:29:49.323 The 0 scan has completed successfully
2020-03-19 20:29:49.325 Starting the 1 scan with 2 as the id
2020-03-19 20:29:49.329 The 0 scan has completed successfully
2020-03-19 20:29:49.380 The 1 scan has completed successfully
2020-03-19 20:29:49.381 Starting the 2 scan with 3 as the id
2020-03-19 20:29:49.385 The 1 scan has completed successfully
2020-03-19 20:29:49.437 The 2 scan has completed successfully

这是运行 for 循环和扫描的代码。我已经硬编码了参数并排除了一些不相关的东西

     const params = ['1','2','3'];
     for (let i = 0; i < params.length; i++) {
      console.log("Starting the " + i + " scan with " + params[i] + " as the scan parameter")
      const scanParams = {
      TableName: "Dynamo_Table",
      FilterExpression: "Org = :Org",
      ExpressionAttributeValues: { ":Org": params[i] },
      ProjectionExpression: "User_ID, Org, first_name, last_name"
     };
     await dynamoClient.scan(scanParams, function(err, data) {
      if (err) {
        console.log("data retrival failed, error logged is :" + err);
        return err;
      }
      else {
        console.log("The " + i +" scan has completed successfully")
        //console.log("data retrival successful: " + JSON.stringify(data));
        userData = userData.concat(data.Items)
        //console.log("partial data structure is " + data)
      }
    }).promise();
  }
      responseData = JSON.stringify(userData)
      console.log("Complete response is " + responseData)
      console.log("data after execution scan is " + data)

我试图通过定义等待和使用 AWS 的 .promise() 函数来强制程序等待扫描的竞争。但是,这些似乎并没有阻止线程执行。我不确定它为什么会启动多次扫描。 for 循环的运行次数没有超出应有的次数,那么为什么会调用搜索函数呢?

【问题讨论】:

  • 因此您只想查询具有特定组织值的项目。 Org 是分区键吗?此外,您正在滥用 SDK 功能。你在等待一些不是承诺的东西。你混淆了承诺和回调。你会使用const data = await dynamoClient.scan(params).promise();,但scan 是错误的解决方案。
  • 感谢 jarmod,几天前我意识到了这一点,但我完全忘记了。您共享的代码是否也适用于查询?我现在要测试它,但我离我的工作比较远
  • 是的,但是您需要多个查询,每个组织一个,假设 Org 确实是分区键(是吗?)
  • 是的,在这种情况下,我已经在 for 循环中运行了扫描,所以除了那个命令之外不需要修改任何内容
  • 嘿另一个问题。您共享的代码,为什么它有效?扫描是否返回回调而不是承诺?我对节点的异步功能很模糊

标签: javascript node.js amazon-web-services asynchronous aws-lambda


【解决方案1】:

这是一个如何使用 DynamoDB DocumentClient 按分区键查询多个项目并收集结果的示例。这使用了query() 调用的承诺变体,并等待使用Promise.all() 完成所有查询承诺。

var AWS = require('aws-sdk');
AWS.config.update({ region: 'us-east-1' });

const dc = new AWS.DynamoDB.DocumentClient();

// Array of organization IDs we want to query
const orgs = ['1', '2', '3'];

// Async function to query for one specific organization ID
const queryOrg = async org => {
  const params = {
    TableName: 'orgs',
    KeyConditionExpression: 'org = :o1',
    ExpressionAttributeValues: { ':o1': org, },
  };

  return dc.query(params).promise();
}

// Async IIFE because you cannot use await outside of an async function
(async () => {
  // Array of promises representing async organization queries made
  const promises = orgs.map(org => queryOrg(org));

  // Wait for all queries to complete and collect the results in an array
  const items = await Promise.all(promises);

  // Results are present in the same order that the queries were mapped
  for (const item of items) {
    console.log('Item:', item.Items[0]);
  }
})();

【讨论】:

    【解决方案2】:

    当您想在 DynamoDB 数据库中搜索某些内容时,建议您使用 Query 选项而不是 Scan

    这是因为 Scan 读取数据库的每一项,而 Query 只查找提到的 Hask 键(主键)。

    如果您想在脑海中寻找具有特定“属性”的数据,您可以使用全局二级索引,其中您可以将“属性”设置为哈希键,同时选择您选择的排序键。这可能会解决您的问题,其中表格多次返回答案。

    【讨论】:

      猜你喜欢
      • 2019-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-08
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      相关资源
      最近更新 更多