Friends, I've been banging my head against my desk. I'm writing an Alexa+Lambda+Dynamodb string of actions/events. The issue comes in my Lambda Node.JS. I have the function getChores in which I'm trying to run a simple getItem() to pull just a sample entry in a dynamodb, however I can ONLY access the data returned in the Else statement but I need to pass it via the callback in speechOutput. Any assistance you can provide would be greatly appreciated!
function getChores(callback) {
sessionAttributes = {};
var params = {
TableName: 'Chores',
Key: {
'chore': {
S: 'Clean up toys'
},
}
};
// Call DynamoDB to read the item from the table
var results = ddb.getItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
//CAN ONLY ACCESS HERE!
console.log("Success", data.Item);
speechOutput = data.Item.chore.S;
console.log(data.Item.chore.S);
console.log(speechOutput);
}
});
console.log(results);
//Get card title from data
const cardTitle = "Chore"
//Get output from data
//const speechOutput = element.chore;
// If the user either does not reply to the welcome message or says something that is not
// understood, they will be prompted again with this text.
const repromptText = '';
const shouldEndSession = false;
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
It looks like ddb.getItem is an async method. You need to call the callback method 'callback' inside the else block.
What should I do to stop the post request from posting new object if the object already exists?
I have pasted my code and json object. I have tried next(); but it doesnt work and a duplicate object with some other id is created no matter what. I am using before beforePostTransaction function to check if the product already exists. The request contains the id and the store id of the
index.js
const Transaction = require('./transactions/TransactionModel');
const TransactionCTL = require('./transactions/TransactionController');
Transaction.before('post', TransactionCTL.beforePostTransaction);
Transaction.register(router, '/transactions');
TransactionController.js
const beforePostTransaction = (req, res, next) => {
var id = req.body.id;
Transaction.findById(
id,
(err, data)=>{
if (!data){
next();
}
else{
var store = data.store;
store = JSON.stringify(store);
store = store.replace(/\"/g, "");
if(store !== req.body.store){ //update the whole object
next();
}
else{
//do what?
}
}
});
res.sendStatus(409);
}
json object
[{
"_id": "596db06849822a13c97ba3f9",
"store": "596b088131ea400490897c50"
}]
Not sure what is your model. But if it is mongoose you can use method
.findOneAndUpdate(query,
update,
{upsert: true},
function (error, result) {
if (!error) { //if you need to do something else
}
});
Where update is your object. It will create new item if it not exist and update it if it exist.
Currently I'm getting my data out of a SQL Server 2012 using a powershell and the mssql plugin. I'm trying to extract out data using queries, so I had a query to get the particular information and then use express.js to send the data over to a textbox. This is the code currently.
Server.JS
app.get('/Warning', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'Atiqah',
password: 'password',
server: 'DESKTOP-5045H9Q',
database: 'TestDB'
};
// connect to your database
sql.connect(config, function (err) {
var record;
if (err) console.log(err);
// create Request object
var request = new sql.Request();
var stringrequest =
// query to the database and get the records
request.query("SELECT COUNT([EntryType]),EntryType FROM TestTable GROUP BY EntryType", function (err, recordset) {
if (err) console.log(err)
// send records as a response
record = recordset;
console.log("You are currently connected to " + JSON.stringify(config));
res.send(JSON.stringify(recordset));
//console.log("Query submitted is " + JSON.stringify(stringrequest));
});
});
Index2.html
function myFunction() {
$.get("/Warning", function (string) {
$('#txtWarning').val(string);
});
}
<body onload="myFunction()">
<textarea rows="8" cols="70" id="txtWarning"></textarea></body>
The data that i get out of the textbox would be something like this:
{"recordsets":[[{"":734,"EntryType":"\"Warning\""},{"":1049,"EntryType":"\"Error\""}]],"recordset":[{"":734,"EntryType":"\"Warning\""},{"":1049,"EntryType":"\"Error\""}],"output":{},"rowsAffected":[2]}
How do I go around only getting the numbers out of this var? Any help would be much appreciated. The output that I wanted would look something like this.
734, 1049, 734, 1049.
Simple solution:
var data = {}; //your object here
var nums = [];
Object.keys(data)
.filter(x => Array.isArray(data[x]))
.forEach(x => {
data[x].forEach(y => {
nums.push(y[""]);
})
});
I need to convert some JSON to XML with this library, I need to do that in order to send some data to the Database in a post request I am working on.
This is what req.body returns
{ DealerName: 'amrcl',
CardId: '123',
Nickname: 'mkm123',
Picture: 'http://lorempixel.com/150/150/',
Active: '1',
LegalId: '1',
TypeId: '1'
}
is dynamic data. Let me show you the code
export default function (req, res) {
try {
const connection = new sql.Connection(spConfig, function spConnection (errSpConnection) {
const request = connection.request();
if (errSpConnection) {
res.status(401);
}
request.input('Dealer_Param', sql.VarChar(1000), req.body);
request.input('param_IS_DEBUG', sql.Bit, null);
request.output('output_IS_SUCCESSFUL', sql.Bit);
request.output('output_STATUS', sql.VarChar(500));
request.execute('[mydbo].[StoredProcedure]', function spExecution (errSpExecution, dataset) {
connection.close();
if (errSpExecution) {
res.status(401);
} else {
if (request.parameters.output_IS_SUCCESSFUL.value) {
res.status(200).json({
success : 'New dealer successfully inserted.',
});
}
}
});
});
}
}
that is for Stored Procedure method which is with the mssql module.
As you see the code above, there is a failure error, because in request.input('Dealer_Param', sql.VarChar(1000), req.body); I am sending the JSON I paste at the beginning of the question. But if instead of req.body I put this XML with Dummy data '<Dealers><Detail DealerName = "TESTING123" CardId = "1222" NickName = "tester123" Active = "1" LegalId = "16545" TypeId = "1"></Detail></Dealers>' then everything works fine because the DB need to receive an XML.
So, what are your recommendations, what should I do to put the JSON data as a XML ?
I would just load the json2xml library...
install $ npm install json2xml
import the module in your code: var json2xml = require("json2xml");
and then convert the json to xml like so:
var key,
attrs=[];
for (key in req.body) {
if (req.body.hasOwnProperty(key)) {
var obj = {};
obj.key = req.body.key;
attrs.push(obj);
}
}
var dealerXml = json2xml({dealer:req.body, attr:attrs}, { attributes_key:'attr'});
request.input('Dealer_Param', sql.VarChar(1000), dealerXml);
I'm using nodejs and tedious connector to get data from mssql server. In documentation, I only see this one way to retrieve data
var request = new Request("select Name, Value, Article_Id from [tableone] where Id = '1'", function (err, rowCount, rows) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
});
request.on('row', function (rows) {
...
bigArrat.push(JSON.stringify(rows));
});
But in my example I want all rows, not only one property but more. Currently, it return in separate row one cell eg. rows[0].value will return Name, rows[1].value Value ... for me it is rubbish.
I want to get all information in json array of object not all metadata or one property. There is a way to do this or there is a better connector for nodejs and sqlserver ?
The rows value sent to your initial callback is the array of rows being sent back:
var request = new Request("select Name, Value, Article_Id from [tableone] where Id = '1'", function (err, rowCount, rows) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
console.log(rows) // this is the full array of row objects
// it just needs some manipulating
jsonArray = []
rows.forEach(function (columns) {
var rowObject ={};
columns.forEach(function(column) {
rowObject[column.metadata.colName] = column.value;
});
jsonArray.push(rowObject)
});
return callback(null, rowCount, jsonArray);
});
In Sql Server 2016 you can format query results as JSON text using FOR JSON option, see https://msdn.microsoft.com/en-us/library/dn921882.aspx
You just need to read JSON fragments returned by query.
Add this to your config.
rowCollectionOnRequestCompletion: true
var config = {
userName: '', // update me
password: '', // update me
server: '', // update me
options: {
database: '', // update me
encrypt: true,
rowCollectionOnRequestCompletion: true
}
}
Then on your query you can now get the data of rows.
var executeQuery = (res,query) => {
request = new Request(query, (err, rowCount, rows) => {
console.log("Rows: ", rows);
res.send(rows);
});
connection.execSql(request);
}
I learned it from:
http://tediousjs.github.io/tedious/api-request.html
EDIT
Update not to have metadata:
var data = []
request = new Request(query, (err, rowCount, rows) => {
if(err) {
console.log(err)
res.send({ status: 500, data: null, message: "internal server error."})
} else {
console.log(rowCount+' row(s) returned')
res.send({ status: 200, data: data, message: "OK"})
}
})
request.on('row', function(row){
data.push({
last_name: row[0].value,
first_name: row[1].value
})
})
connection.execSql(request)
If you are using express on server side I can recommend using express4-tedious (see https://www.npmjs.com/package/express4-tedious). It allows to easily write apis for SQL connections with small code and streams json result to response.
Connection:
var express = require('express');
var tediousExpress = require('express4-tedious');
var app = express();
app.use(function (req, res, next) {
req.sql = tediousExpress(req, {connection object});
next();
});
Example Api:
/* GET from tableone, streams json result into response */
router.get('/', function (req, res) {
req.sql("select Name, Value, Article_Id from [tableone] where Id = '1' for json path")
.into(res);
});
You can then call these apis e.g. from frontend.
I tried that way but it did not work for me perhaps my knowledge of js and callbacks is not good enough. So, here is my solution. I had to add things to my config of connection to make rows of request work. You would also have to do this. Go to: at the end of new Request section, and to the rows.
here
Second thing, I did is pretty simple.
var jsonArray = [];
var rowObject= {};
var request = new Request("SELECT TOP 5 * FROM tableName",function(err,rowCounts,rows)
{
if (err)
{
console.log(err);
}
else
{
console.log(rowCounts + " rows returned");
}
//Now parse the data from each of the row and populate the array.
for(var i=0; i < rowCounts; i++)
{
var singleRowData = rows[i];
//console.log(singleRowData.length);
for(var j =0; j < singleRowData.length; j++)
{
var tempColName = singleRowData[j].metadata.colName;
var tempColData = singleRowData[j].value;
rowObject[tempColName] = tempColData;
}
jsonArray.push(rowObject);
}
//This line will print the array of JSON object.
console.log(jsonArray);
and to show you how my connection.config looks like:
static config: any =
{
userName: 'username',
password: 'password',
server: 'something.some.some.com',
options: { encrypt: false, database: 'databaseName' ,
rowCollectionOnRequestCompletion: true }
};//End: config
and this is how I am passing it to connection.
static connection = new Connection(Server.config);
Complementing the answer from #Jovan MSFT:
var request = new Request('select person_id, name from person for json path', function(err) {
if (err) {
console.log(err);
}
connection.close();
});
And, finally, in the row event:
request.on('row', function(columns) {
var obj = JSON.parse(columns[0].value);
console.log(obj[0].name);
});
P.S.: the code above does not iterate over columns parameter because for json path returns a single array of objects in a single row and column.
Applying map-reduce function in returned rows:
rows.map(r=>{
return r.reduce((a,k)=>{
a[k.metadata.colName]=k.value
return a
}
,{})
})
This is a combination of a few responses above. This uses FOR JSON AUTO in the SELECT statement and parses the "column" as JSON. The row/column nomenclature may be a bit misleading for folks unfamiliar with this API. In this case, the first "columns" value will be an array of the rows in your table:
var request = new Request("SELECT Name, Value, Article_Id FROM [tableone] WHERE Id = '1' FOR JSON AUTO", function (err, rowCount, rows) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
});
request.on('row', (columns) => {
const json = JSON.parse(columns[0].value);
});