Recursive Recostackr todos los elementos en DynamoDB Query usando Node JS

Esta es probablemente más una pregunta JS / Async que una pregunta específica de DynamoDB –

Quiero search todos los elementos en una tabla con una key hash en DynamoDB de Amazon. La tabla también tiene la tecla Range en él.

Estoy usando una biblioteca NodeJS que es una envoltura alnetworkingedor de la API REST DynamoDB de AWS. – Nodo-DynamoDB

DynamoDB solo devuelve 1 MB de resultados con cada consulta. Para recuperar el recordatorio de los resultados, incluye lastEvaluatedKey . Podemos include esto en otra consulta para get otros resultados de 1 MB de valor y así sucesivamente …

Estoy enfrentando dificultades para escribir una function recíproca asíncrona que debe llegar al service secuencialmente hasta que pueda recuperar todos los resultados. (la tabla nunca tendrá más de 10 MB para mi caso de uso, no hay posibilidad de una consulta desbocada)

Algunos pseudo código para ilustración:

ddb.query('products', primarykey, {}, function(err,result){ //check err if(result && result.lastEvaluatedKey){ //run the query again var tempSet = result.items; //temporarily store result.items so we can continue and fetch remaining items. } else{ var finalSet = result.items; //figure out how to merge with items that were fetched before. } }); 

 var getAll = function(primarykey, cb) { var finalSet = [], nextBatch = function(lek) { ddb.query('products', primarykey, { exclusiveStartKey: lek }, function(err, result) { if (err) return cb(err); if (result.items.length) finalSet.push.apply(finalSet, result.items); if (result.lastEvaluatedKey) nextBatch(result.lastEvaluatedKey); else cb(null, finalSet); }); }; nextBatch(); }; getAll(primarykey, function(err, all) { console.log(err, all); }); 

Después de unas cuantas tazas de café, escribí esta function recursiva. Espero que esto ayude a otros. Si ve un error, por favor edítelo o deje un comentario.

  var DynamoDbItemFetcher = function(table,hash,maxItems,callback){ var self = this; self.table = table; self.startKey = null; self.hash = hash; self.maxItems = maxItems; self.items = []; self.callback = callback; self.getItems = function(){ var params = {}; if(self.startKey){ params.exclusiveStartKey = self.startKey; } ddb.query(self.table,self.hash,params,function(err1,result){ if(err1) return self.callback(err1, null); if(result){ self.items = self.items.concat(result.items); if(result.lastEvaluatedKey && result.lastEvaluatedKey.hash){ if(self.maxItems && self.items.length > self.maxItems){ self.callback(null,self.items); }else { self.startKey = result.lastEvaluatedKey;//reset start key self.getItems(callback);//recursive call... } }else{ //no more items..return whatever is in store. self.callback(null,self.items); } } else{ self.callback(null, null); } }); }; }; 

Aquí hay una variación usando promises. Necesitaba get una list de nombres de tablas, no escanear elementos de una tabla, pero se aplican conceptos similares.

 function getTableNames(key, prevTableNames) { return new Promise(function(resolve, reject) { let request = dynamodb.listTables({ ExclusiveStartTableName: key }, function(err, response) { if (err) { reject(err); } else { let tableNames = (prevTableNames || []).concat(response.TableNames); if (response.LastEvaluatedTableName) { getTableNames(response.LastEvaluatedTableName, tableNames) .then(resolve) .catch(reject); } else { resolve(tableNames) } } }); }); }