"use strict";
const DynamoDbDataModels = require("./dynamodb-data-models.js");
var listit = require('list-it');
/**
* The result data model of DynamoDB SCAN or Query.
*
* @param {object} data The rensponse object from DynamoDB API SCAN and QUERY.
*
* @constructor
*/
function DynamoDbResultSet(data) {
this._data = data;
this._columns = getAllScannedAttributeNames(
this._data.Items);
this._rows = convertItemsTo2dArray(
this._data.Items, this._columns);
}
DynamoDbResultSet.prototype.getRawItems = function() {
return this._data.Items;
};
DynamoDbResultSet.prototype.getRawItemAt = function(rowIndex) {
if(rowIndex >= this._data.Items.length) {
throw new RangeError("rowIndex out of range: " + rowIndex);
}
return this._data.Items[rowIndex];
};
/**
* Get an item converted to the native object from DynamoDB Map Data
*
* @returns {object[]} returns array of object converted.
*/
DynamoDbResultSet.prototype.getItems = function() {
return this._data.Items.map( item => {
return DynamoDbDataModels.map2obj(item);
});
};
/**
* Get an item converted to the native object from DynamoDB Map Data
* by index of items.
*
* @param {integer} rowIndex
* The index of item in Items.
*
* @returns {object} returns item converted to object.
*/
DynamoDbResultSet.prototype.getItemAt = function(rowIndex) {
if(rowIndex >= this._data.Items.length) {
throw new RangeError("rowIndex out of range: " + rowIndex);
}
return DynamoDbDataModels.map2obj(this._data.Items[rowIndex]);
};
/**
* Print scan or query result to console.
*
* @param {string} sortItemPath
* An attribute path name of item to sort.
*
* @param {boolean} sortDesc (Optional)
* Specify true to sort items descent.
*
* @returns {undefined}
*/
DynamoDbResultSet.prototype.print = function(sortItemPath, sortDesc) {
DynamoDbResultSet.printScanResult(this._data, sortItemPath, sortDesc);
};
/**
* Print scan or query result to console.
*
* @param {object} data
* The response object from DynamoDB API SCAN and QUERY.
*
* @param {string} sortItemPath
* An attribute path name of item to sort.
*
* @param {boolean} sortDesc (Optional)
* Specify true to sort items descent.
*
* @returns {undefined}
*/
DynamoDbResultSet.printScanResult = function(data, sortItemPath, sortDesc) {
var colNames = getAllScannedAttributeNames(data.Items);
var rows = convertItemsTo2dArray(data.Items, colNames);
if(sortItemPath) {
var colIndex = colNames.indexOf(sortItemPath);
if(colIndex >= 0) {
rows.sort( !sortDesc ? (a, b) => {
if(a[colIndex] > b[colIndex]) { return 1; }
if(a[colIndex] < b[colIndex]) { return -1; }
return 0;
} : (a, b) => {
if(a[colIndex] > b[colIndex]) { return -1; }
if(a[colIndex] < b[colIndex]) { return 1; }
return 0;
});
}
}
if("Count" in data) {
console.log("Count:", data.ScannedCount);
}
// format table
var buf = listit.buffer({ "autoAlign": true });
var rownum = 0;
buf.d("ROWNUM");
buf.d(colNames);
rows.forEach(function(row) {
buf.d(++rownum);
buf.d(row);
});
console.log(buf.toString());
if("NextToken" in data) {
console.log("NextToken:", data.NextToken);
}
if("LastEvaluatedKey" in data) {
console.log("LastEvaluatedKey:", JSON.stringify(data.LastEvaluatedKey));
}
if("ScannedCount" in data) {
console.log("ScannedCount:", data.ScannedCount);
}
};
function getAllScannedAttributeNames(items) {
var colNames = [];
var traverseKeys = function(item, namePath) {
namePath = namePath || [];
Object.keys(item).forEach(function(key) {
namePath.push(key);
var attrName = namePath.join('.');
var type = null;
var types = Object.keys(item[key]);
if(types.length > 0) {
type = types[0];
}
if(type == 'M') {
traverseKeys(item[key]['M'], namePath);
} else {
if(colNames.indexOf(attrName) < 0) {
colNames.push(attrName);
}
}
namePath.pop();
});
};
// Traverse column names
items.forEach(function(item) {
traverseKeys(item);
});
return colNames;
}
//
// Convert scan/query result to 2-D array
//
function convertItemsTo2dArray(items, colNames) {
var rows = [];
items.forEach(function(item) {
var cols = [];
colNames.forEach(function(attrPath) {
var value = refAttrByPath(item, attrPath);
if(value == null) {
value = "";
}
cols.push(value);
});
rows.push(cols);
});
return rows;
}
function refAttrByPath(item, attrPath) {
var pathArray = attrPath.split('.');
for(var i = 0; i < pathArray.length; i++) {
var pathElement = pathArray[i];
if(typeof(item) != "object"
|| !(pathElement in item))
{
return null;
}
item = item[pathElement];
var types = Object.keys(item);
if(types.length > 0) {
var type = types[0];
item = item[type];
switch(type) {
case 'N':
if(item.match(/\./)) {
item = parseFloat(item);
} else {
item = parseInt(item);
}
break;
case "BOOL":
item = (item == true);
break;
}
}
}
return item;
}
module.exports = DynamoDbResultSet;