Node.js 仅 AWS DynamoDB 扫描特定字段

Node.js AWS DynamoDB Scan specific field(s) only

在许多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 格式的情况下只扫描单个项目吗?

感谢您阅读我的问题。

有什么方法可以在不改变我的 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"
}