如何使用node.js从`AWS dynamodb`获取/扫描所有项目

Vis*_*hnu 24 node.js amazon-dynamodb aws-lambda

如何从AWS dynamodb使用中获取/扫描所有项目node.js.我在这里发布我的代码.

var docClient = new aws.DynamoDB.DocumentClient();
    var params = {
    TableName:"users",
    KeyConditionExpression:"user_status=:status",
    ExpressionAttributeValues: {
        ":status": "Y"
    }
    };

    var queryExecute = function(callback) {
        docClient.query(params,function(err,result) {
            if(err) {
                console.log(err)
                callback(err);
                } else {
                console.log(result);

                if(result.LastEvaluatedKey) {
                    params.ExclusiveStartKey = result.LastEvaluatedKey;
                    queryExecute(callback);
                    } else {
                        callback(err,items);
                    }
                }
            });
        }
        queryExecute(callback); 
Run Code Online (Sandbox Code Playgroud)

这给了我以下错误.

ValidationException: Query condition missed key schema element: `user_id`.
Run Code Online (Sandbox Code Playgroud)

这里的主键是user_id.我不想在查询条件中使用它,因为如果我提到主键,我需要设置一个值KeyConditionExpression.可能是我错了.但是请建议我一个很好的方法来获取所有项目dynamodb,这是有的user_status = "Y"

not*_*est 31

如果您想在不使用Hash密钥值的情况下从DynamoDB获取数据,则需要使用Scan API.

注意: Scan API会读取表中的所有项目以获取结果.因此,这在DynamoDB中是一项代价高昂的操作.

替代方法:使用GSI

上述情景的扫描码: -

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

var params = {
    TableName: "users",
    FilterExpression: "#user_status = :user_status_val",
    ExpressionAttributeNames: {
        "#user_status": "user_status",
    },
    ExpressionAttributeValues: { ":user_status_val": 'somestatus' }

};

docClient.scan(params, onScan);
var count = 0;

function onScan(err, data) {
    if (err) {
        console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
    } else {        
        console.log("Scan succeeded.");
        data.Items.forEach(function(itemdata) {
           console.log("Item :", ++count,JSON.stringify(itemdata));
        });

        // continue scanning if we have more items
        if (typeof data.LastEvaluatedKey != "undefined") {
            console.log("Scanning for more...");
            params.ExclusiveStartKey = data.LastEvaluatedKey;
            docClient.scan(params, onScan);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 该代码具有递归调用,直到 LastEvaluatedKey 未定义。所以,它应该工作。 (7认同)
  • Scan 最多只能扫描 1MB 的数据,因此此代码不适用于大于 1MB 的数据库。 (4认同)
  • 尽管这似乎可行,但我认为如果此答案实际上返回数据,而不是仅仅将其打印到控制台,那就更好了。对于刚接触JS或函数式编程的人来说,从此处提出一个解决方案(实际上将数据(通过callbak)返回给调用函数)的解决方案并不一定很容易。 (2认同)
  • 同意@JuhaKervinen,最好返回数据。汉克的回答做到了这一点,而且更加简洁。 (2认同)

Han*_*ank 20

这为我工作:

export const scanTable = async (tableName) => {
    const params = {
        TableName: tableName,
    };

    let scanResults = [];
    let items;
    do{
        items =  await documentClient.scan(params).promise();
        items.Items.forEach((item) => scanResults.push(item));
        params.ExclusiveStartKey  = items.LastEvaluatedKey;
    }while(typeof items.LastEvaluatedKey != "undefined");

    return scanResults;

};
Run Code Online (Sandbox Code Playgroud)

  • 这有效,但有一些最佳实践改进:将“scanResults”设置为“const”,将“!=”更改为“!==”,将“items”设置为“const”,并在循环内部使用单独的变量在循环外部声明它。 do 循环用于存储 LastEvaluatedKey。 (3认同)
  • 您不能在循环内分配给常量“items”,而是将其设置为“let”。您还可以使用更好的语法在数组中添加多个项目:scanResults.push(...items.Items),这里您还必须在推送之前检查 items.Items 是否未定义。 (2认同)
  • 我收到错误:-“类型 '{ TableName: any; 上不存在属性 'ExclusiveStartKey'” }'。params.ExclusiveStartKey = items.LastEvaluatedKey;` 您如何引用“params”对象中未声明的键? (2认同)

Nic*_*via 12

AWS 文档示例对我不起作用。@Hank 方法成功了。

在 lambda 中使用处理程序:

const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({
    // optional tuning - 50% faster(cold) / 20% faster(hot)
    apiVersion: '2012-08-10',
    sslEnabled: false,
    paramValidation: false,
    convertResponseTypes: false
});

const tableName = 'series';

exports.handler = async (event, context, callback) => {
    let params = { TableName: tableName };

    let scanResults = [];
    let items;

    do {
        items = await docClient.scan(params).promise();
        items.Items.forEach((item) => scanResults.push(item));
        params.ExclusiveStartKey = items.LastEvaluatedKey;
    } while (typeof items.LastEvaluatedKey != "undefined");

    callback(null, scanResults);
};
Run Code Online (Sandbox Code Playgroud)


Ioa*_*kos 8

使用承诺和异步

const aws = require('aws-sdk');
aws.config.update({ region: 'us-east-1' });
const documentClient = new aws.DynamoDB.DocumentClient();

const scanAll = async (params) => {
  let lastEvaluatedKey = 'dummy'; // string must not be empty
  const itemsAll = [];
  while (lastEvaluatedKey) {
    const data = await documentClient.scan(params).promise();
    itemsAll.push(...data.Items);
    lastEvaluatedKey = data.LastEvaluatedKey;
    if (lastEvaluatedKey) {
      params.ExclusiveStartKey = lastEvaluatedKey;
    }
  }
  return itemsAll;
}
Run Code Online (Sandbox Code Playgroud)

像这样使用

const itemsAll = scanAll(params);
Run Code Online (Sandbox Code Playgroud)

查询代码相同(只需将扫描替换为查询)


Maz*_*oth 6

我使用这样的承诺:

let AWS = require('aws-sdk');
let docClient = new AWS.DynamoDB.DocumentClient();

async function dbRead(params) {
    let promise = docClient.scan(params).promise();
    let result = await promise;
    let data = result.Items;
    if (result.LastEvaluatedKey) {
        params.ExclusiveStartKey = result.LastEvaluatedKey;
        data = data.concat(await dbRead(params));
    }
    return data;
}
Run Code Online (Sandbox Code Playgroud)

并使用它:

let params = {
  TableName: 'Table'
};
let data = await dbRead(params);
Run Code Online (Sandbox Code Playgroud)

  • 为了理解递归,首先要理解递归。 (2认同)

kal*_*lpa 5

const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({
    // optional tuning - 50% faster(cold) / 20% faster(hot)
    apiVersion: '2012-08-10',
    sslEnabled: false,
    paramValidation: false,
    convertResponseTypes: false,
    region: 'us-east-2' // put your region
});
const tableName = 'tableName'; // put your tablename

exports.handler = async (event, context, callback) => {
    let params = { TableName: tableName };

    let scanResults = [];
    let items;

    do {
        items = await docClient.scan(params).promise();
        items.Items.forEach((item) => scanResults.push(item));
        params.ExclusiveStartKey = items.LastEvaluatedKey;
    } while (typeof items.LastEvaluatedKey != "undefined");

    callback(null, scanResults);
};
Run Code Online (Sandbox Code Playgroud)