Azure DocumentDB Stored Procedure in Node.js excute existing - javascript

I have been going around in circles with this. I'm trying to execute an existing stored procedure using the node js documentdb library.
var sproc = self.client.queryStoredProcedures(collection._self, "select * from root r WHERE r.id = 'helloWorld'");
self.client.executeStoredProcedure(sproc._self, function (err, res) {
if(err){
console.log(err);
}else{
console.log(res);`
}
});
Not entirely sure queryStoredProcedures (Seems to be no async version of this) is the correct way of retrieving the uri for the store procedure, I haven't managed to get this to work. I'm also trying to avoid too many round trips to the database, but from what I gather I either hard code the store procedure's uri or have to make at least two requests just to execute the stored procedure.

queryStoredProcedures (along with all query and read functions) return a QueryIterator rather than an actual result. The methods you call on the returned QueryIterator are async. So, following the approach of your example (minus error handling), you would do this:
var queryIterator = self.client.queryStoredProcedures(collection._self, "select * from root r WHERE r.id = 'helloWorld'");
queryIterator.toArray(function(err, result) {
var sproc = result[0];
self.client.executeStoredProcedure(sproc._self, function (err, res) {
console.log(res);`
});
});
However, since the introduction of id-based routing, you can short hand the above like this:
var sprocLink = "dbs/myDatabase/colls/myCollection/sprocs/helloWorld";
self.client.executeStoredProcedure(sprocLink, function (err, res) {
console.log(res);`
});

Related

Using a variable in a WHERE clause MySQL/Node

I'm trying to make a MySQL query to filter data from a table. Effectively what I want to do is:
SELECT data FROM table WHERE column IN ?
The filter is coming from checkboxes in a form on a webpage, so I can pass an array or object fairly easily, but it'll be a varying number of parameters for the IN each time, so I can't us multiple ?. I tried making a for loop to make multiple queries concatenate the arrays that the queries returned, but I ran into scope issues with that. I also tried passing an array directly to the query, but that throws a syntax error. I'm sure there's a straightforward answer to this but I'm not sure how to do it.
Edit: source code added:
Here's where I'm at:
const filterShowQuery = `SELECT sl_Show.showId, sl_Band.BandName,
sl_Show.date, sl_Venue.venueName,
sl_Show.length, sl_Show.attendance, sl_Show.encore FROM sl_Show
JOIN sl_Band on sl_Show.BandID = sl_Band.BandId
JOIN sl_Venue on sl_Show.VenueId = sl_Venue.VenueId
WHERE sl_Band.BandName IN (?)
ORDER BY sl_Band.BandName;`;
Trying to get an array into the ? in WHERE sl_Band.BandName IN
const getShows = (req, res,next) =>{
var {bands, venues} = req.body;
var i = 0; //left over from previous attempt
var data = [];
for (b in bands){
mysql.pool.query(filterShowQuery, bands[b], (err, result) => {
if(err){
console.log('filter band error');
next(err);
return;
}
data = data.concat(result);
console.log(data); //data concatenates property and increases through for loop
})
// same action to be performed with venues once solved
// for (v in venues){
// conditions[i] = venues[v];
// i++;
console.log(data); //data is empty when logging from here or using in res
res.json({rows:data});
}
}
SECURITY WARNING!
I must to say: NEVER, NEVER PASS DATA DIRECTLY TO YOUR SQL!
If you don't know why, just google for SQL Injection. There are lots of examples on how it is done, how easily it can be done, and how to protect your application from this sort of attack.
You should always parametrize your queries. But in the very rare case which you really need to insert data concatenating a string into your sql, validate it before.
(E.g.) If it's a number, than use a Regex or some helper method to check if the value you are inserting into your SQL String is really and only a number and nothing else.
But aside that, you did not provide any source code, so it's really hard to give any help before you do that.

Is this way to access mongodb in node.js acceptable?

I am new to programming and trying to experiment a bit, still struggling with the best way to access mongoDB from within my code. I've seen a few posts here on stack overflow but they more or less all require that the code required to load mongo is included in each and every .js file. I would like to avoid that in order to keep the code for accessing my DB in only one file.
Note that I am using the "mongo-factory" module.
Would the code below be acceptable?
I've created what I would call a "producer" of database objects, database.js
var mongoFactory = require('mongo-factory');
function Database(close,callback) {
mongoFactory.getConnection(<connection string>).then(function (database) {
callback(database.db(<db name>));
if(close) database.close();
}).catch(function (err) {
console.error(err);
});
}
module.exports = Database;
Then when I want to access the database from any of my files I could do the below, avoiding to introduce db-specific parameters and the mongo-factory requirement in here:
var Database = require('./database');
var callback_actOnDatabase = function (db) {
db.collection..... do something here
};
var d = new Database(false, callback_actOnDatabase);
instead of mongo-factoy use mongoose module to connect the database,model declaration also we dont intalise the db parameters again,please go through the link
https://www.npmjs.com/package/mongoose

can't set headers after they are sent node js when using restify module

I have used tedious to connect to sql server and restify for restful api
here is the server.js
server.get('/getInvoiceData', function (req, res, next) {
repository.GetInvoiceData(function(data){
res.send(data);
next();
});
});
and the invoice.js
exports.GetInvoiceData = function(callback){
var query = "SELECT * FROM [Snapdeal].[dbo].[tbl_Configuration]";
var req = new request(query,function(err,rowcount){
if (err)
{
console.log(err.toString());
}else{
console.log(rowcount+ " rows");
}
});
req.on('row',function(){
callback({customernumber:123});
});
connection.execSql(req);
}
I am getting the error as Cant set the headers after they are sent.
I am not 100% sure as I am not familiar with the SQL lib you are using, however, it looks to me like the problem is your row event would be raised per row, rather than per transaction.
You are ending the response after the first row event therefore if there is more than one row being returned the response will already have been closed (hence the error).
One way of dealing with this is to accumulate the row data as it's being retrieved and then raise the callback after your done
Now that you have stated the lib you are using (Tedius), it would appear my hunch was correct. Looking at the library, here is the simplest approach you can take to returning all the rows in a single callback
exports.GetInvoiceData = function(callback){
var query = "SELECT * FROM [Snapdeal].[dbo].[tbl_Configuration]";
var req = new request(query,function(err, rowcount, rows){
if (err) {
console.log(err.toString());
} else{
callback(rows);
}
});
connection.execSql(req);
}
Note - remember to set config.options.rowCollectionOnRequestCompletion to true otherwise the rows parameter will be empty.
My issue, using mssql, was that I had a default value or binding set (in this case, (getdate())) to one of my columns (modified date column). However, the data I was trying to retrieve had preset NULL values for this particular column.
I put data in those rows and I was good to go.

How do I return the results of a query using Sequelize and Javascript?

I'm new at javascript and I've hit a wall hard here. I don't even think this is a Sequelize question and probably more so about javascript behavior.
I have this code:
sequelize.query(query).success( function(row){
console.log(row);
}
)
The var row returns the value(s) that I want, but I have no idea how to access them other than printing to the console. I've tried returning the value, but it isn't returned to where I expect it and I'm not sure where it goes. I want my row, but I don't know how to obtain it :(
Using Javascript on the server side like that requires that you use callbacks. You cannot "return" them like you want, you can however write a function to perform actions on the results.
sequelize.query(query).success(function(row) {
// Here is where you do your stuff on row
// End the process
process.exit();
}
A more practical example, in an express route handler:
// Create a session
app.post("/login", function(req, res) {
var username = req.body.username,
password = req.body.password;
// Obviously, do not inject this directly into the query in the real
// world ---- VERY BAD.
return sequelize
.query("SELECT * FROM users WHERE username = '" + username + "'")
.success(function(row) {
// Also - never store passwords in plain text
if (row.password === password) {
req.session.user = row;
return res.json({success: true});
}
else {
return res.json({success: false, incorrect: true});
}
});
});
Ignore injection and plain text password example - for brevity.
Functions act as "closures" by storing references to any variable in the scope the function is defined in. In my above example, the correct res value is stored for reference per request by the callback I've supplied to sequelize. The direct benefit of this is that more requests can be handled while the query is running and once it's finished more code will be executed. If this wasn't the case, then your process (assuming Node.js) would wait for that one query to finish block all other requests. This is not desired. The callback style is such that your code can do what it needs and move on, waiting for important or processer heavy pieces to finish up and call a function once complete.
EDIT
The API for handling callbacks has changed since answering this question. Sequelize now returns a Promise from .query so changing .success to .then should be all you need to do.
According to the changelog
Backwards compatibility changes:
Events support have been removed so using .on('success') or .success()
is no longer supported. Try using .then() instead.
According this Raw queries documentation you will use something like this now:
sequelize.query("SELECT * FROM `users`", { type: sequelize.QueryTypes.SELECT})
.then(function(users) {
console.log(users);
});

Correct approach to getting all pages from API that utilizes a Link header (using JavaScript/NodeJS)

I'm using a NodeJS module called node-github, which is a wrapper around the Github API, to get some statistics about certain users, such as their followers:
var getFollowers = function(user, callback) {
github.user.getFollowers(user, function(err, res) {
console.log("getFollowers", res.length);
callback(err, res);
});
};
...
getFollwers({user: mike}, function(err, followers) {
if(err) {
console.log(err);
}
else {
console.log(followers);
}
});
Apparently, Github limits call results to a maximum of 100 (via the per_page parameter), and utilizes the Link header to let you know a 'next page' of results exists.
The module I'm using provides several easy methods to handle the Link header, so you won't need to parse it. Basically, you can call github.hasNextPage(res) or github.getNextPage(res) (where res is the response you received from the original github.user.getFollowers() call)
What I'm looking for is the right approach/paradigm to having my function return all results, comprised of all pages. I dabbled a bit with a recursive function, and though it works, I can't help but feeling there may be a better approach.
This answer could serve as a good approach to handling all future Link header calls - not just Github's - if the standard catches on.
Thanks!
Finally, resorted to recursion (remember the 2 great weaknesses of recursion: maintaining it, and explaining it :)). Here's my current code, if anyone is interested:
var getFollowers = function(callback) {
var followers = []
, getFollowers = function(error, result) {
followers = followers.concat(result);
if(github.hasNextPage(result)) {
github.getNextPage(result, getFollowers);
}
else {
callback(error, followers);
}
};
github.user.getFollowers(options, getFollowers);
};
But, I found out that if you just need the total number of followers, you can use the getLastPage function to get the number of followers on the last page and then
total_num_of_followers = num_of_followers_on_last_page + (total_num_of_pages * results_per_page)

Categories

Resources