首页 > 解决方案 > Node.js AWS DynamoDB 仅扫描特定字段

问题描述

在许多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.jsamazon-web-servicesamazon-dynamodb

解决方案


有没有可能只扫描单个项目而不更改我的 json 格式的方法?

不幸是,您必须Scan用于搜索非关键属性

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

  • 将 的副本另存motor_namesetting_motor_name顶级属性
  • 创建GSI一个setting_motor_name
  • 使用Queryonsetting_motor_name实现毫秒级效率

乍看上去:

{
  "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

--

最好的方案是保持这些数据平坦,但这需要侵入性地更改模式。这样就没有重复了,你可以申请GSImotor_name因为它是顶级属性

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

推荐阅读