【问题标题】:Node.js AWS DynamoDB Scan specific field(s) onlyNode.js AWS DynamoDB 仅扫描特定字段
【发布时间】:2021-03-26 10:43:17
【问题描述】:

在许多AWS DynamoDB 数据中,我想使用node.js 搜索特定的键值数据。

我的数据库单键示例如下。

{
  "device_id" : "abcde12345", // Primary Key, String
  "setting": {
    "left_motor": 30,
    "right_motor": 30,
    "motor_name": "STRING_WHAT_I_WANT_TO_CHECK"
  },
  "another_fields1" : "1234",
  "another_fields2": {
    "key1" : 1,
    "key2" : "2",
    "key3" : { ... }
  }
}

我收集所有项目的motor_name的代码如下。

// require modules
var fs       = require('fs'); // used for save json-result.
var AWS      = require('aws-sdk');
var config   = require('./config_file'); // secret data
var schedule = require('node-schedule');

AWS.config.update({
  region: config.dynamodb.region,
  endpoint: config.dynamodb.endpoint,
  accessKeyId: config.dynamodb.access_key,
  secretAccessKey: config.dynamodb.secret_key
});

var documentClient = new AWS.DynamoDB.DocumentClient();

var params = {
  TableName: config.dynamodb.device_table
};

// I set run once at 9 o'clock, but after do single-time, I kill pm2 process.
// (just for run once only)

var motor_name_list = {}; // result will be saved.
var j = schedule.scheduleJob("0 0 9 * * *", function() {
  documentClient.scan(params, onScan);
});

function onScan(err, data) {
  if(err) {
    console.log(err);
  }
  else { // READ SUCCESS
    /*
      'single_item' sample is like upper json-code
       But, I reference only one value, setting.motor_name
    */
    data.Items.forEach(function(single_item) {
      // process scan success datas
      var motor_name = single_item.setting.motor_name;
      if(motor_name_list.hasOwnProperty(motor_name))
        motor_name_list[motor_name] += 1;
      else
        motor_name_list[motor_name] = 1;
    });

 
    if(typeof data.LastEvaluatedKey != 'undefined') {
      params.ExclusiveStartKey = data.LastEvaluatedKey;

      // Because of Read Limit per minute, I delay next-step for one minute.
      // (maybe, ReadCapacityUnits)
      setTimeout(function() {
        documentClient.scan(params, onScan);
      }, 60 * 1000);
    }
    else {
      // save motor_name_list as a file (fs.writeFileSync...)
    }
  } // END OF READ SUCCESS
}

由于延迟,需要很多时间。 (实际上是 10~15 分钟)。
(单个onScan 读取 300~500 项,我有将近 5000 项。

有没有什么方法可以只扫描单个项目而不改变我的 json 格式?

感谢您阅读我的问题。

【问题讨论】:

    标签: node.js amazon-web-services amazon-dynamodb


    【解决方案1】:

    有没有什么方法可以只扫描单个项目而不改变我的 json 格式?

    很遗憾不行,你必须使用Scan来搜索非关键属性

    假设 schema 无法更改,但您可以添加额外的 attribute 并且您愿意接受一些重复:

    • 将motor_name 的副本另存为setting_motor_name 作为顶级属性
    • 在setting_motor_name 上创建一个GSI
    • 在setting_motor_name 上使用Query 以实现毫秒级效率

    一目了然:

    {
      "setting": {
        "left_motor": 30,
        "right_motor": 30,
        "motor_name": "STRING_WHAT_I_WANT_TO_CHECK"
      },
      "setting_motor_name": "STRING_WHAT_I_WANT_TO_CHECK"
    }
    

    权衡是:

    • 您必须注意为您保留的任何现有数据插入 setting_motor_name
    • 对setting.motor_name 的任何更新都应更新为setting_motor_name

    --

    最好的方案是保持这些数据平坦,但这需要侵入性地更改架构。这样就没有重复了,你可以在motor_name上应用GSI,因为它是一个顶级属性

    {
      "setting": {
        "left_motor": 30,
        "right_motor": 30
      },
      "motor_name": "STRING_WHAT_I_WANT_TO_CHECK"
    }
    

    【讨论】:

    • 谢谢。我明白这是不可能的。我将更改motor_name 的位置或等待扫描所有项目。无论如何,在您的回答中,GSI 是指全球二级索引?
    • 是,GSI = 全球二级索引
    猜你喜欢
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多