Pass URL parameter into Database query in nodejs - node.js

I am trying to pass URL parameter into the SQL query. I have a column called "puppy_id" and one of the values is puppy1.
I want to call this URL :- localhost:3000/api/puppies/puppy1
and it should execute the query in the database SELECT * FROM puppytable WHERE puppy_id='puppy1' and return the output.
I have no problem to connect to the database. But, it is showing that no data returned. I think, I am doing something wrong in executing the query.
My Code :-
index.js
var express = require('express');
var router = express.Router();
var db = require('../queries');
router.get('/api/puppies/:puppy_id', db.getPuppyStatus);
module.exports = router;
queries.js
module.exports = {
getPuppyStatus: getPuppyStatus
};
function getPuppyStatus(req, res, next) {
var puppyID = parseInt(req.params.puppy_id);
db.any('select * from puppytable where puppy_id =$1', puppyID)
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
message: 'Retrieved puppies'
});
})
.catch(function (err) {
return next(err);
});
}
queries.js is in root of project directory.
It is calling from here in index.js
var db = require('../queries');
This is my output :-
{"status":"success","data":[],"message":"Retrieved puppies"}
To debug when I am doing console.log(puppyID); , it is giving me NaN
What should be the recommended way to do this ?

I don't see where req.params.family_id is coming from, but it looks like it should be req.params.puppy_id - as below - otherwise it would be undefined, which would not match anything in your database.
function getPuppyStatus(req, res, next) {
var puppyID = req.params.puppy_id;
//call puppy_id, not family_id
//puppy_id is also a string being passed in, it can't be turned into an integer
db.any('select * from puppytable where puppy_id =$1', puppyID)
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
message: 'Retrieved puppies'
});
})
.catch(function (err) {
return next(err);
});
}

You're converting to a number a string "puppy1". This is the reason you're getting NaN.
I don't know what's the type of the id in your column.
You've two options:
id as number, try to send a number instead of a string and you're code should be fine.
id as string, remove the parseInt.
var puppyID = req.params.puppy_id;

Related

node js SQL Insert Query with Constructor / JSON text as values parameter

First real app and I'm stuck trying to insert a new row into SQL.
//This is the API endpoint
Sponsor.create = (newSponsor, result)=> {
var sqlStmt = 'insert into sponsors (SponsorName, SponsorState, SponsorDesc, pnfpExperience, Status) values ?'
sql.query(sqlStmt, [newSponsor], (err, res)=> {
if(err) {
console.log(" error: ", err);
result(null, err);
}
else{
console.log(res);
result(null, res);
}
});
};
request.body returns the JSON text but not an array of values that can be used in the query. I keep getting a COUNT error or syntax error. I've tried JSON.parse but I get an undefined error. I know there has to be a simple way to convert the JSON text to the right format but I don't know what I'm missing. The "findAll" and "findById" routes work and I can insert static values. I've also tried "newSponsor" with and without brackets. I'll refine the connection method in time but I'm just trying to understand why this doesn't work. Any help is greatly appreciated.
// Controller.js for Reference
exports.create = function(req, res) {
const new_sponsor = new Sponsor(req.body);
//handles null error
if(req.body.constructor === Object && Object.keys(req.body).length === 0){
res.status(400).send({ error:true, message: 'Please provide all required field' });
}else{
Sponsor.create(new_sponsor, function(err, sponsor) {
if (err)
res.send(err);
res.json({error:false,message:"Sponsor added successfully!",data:sponsor});
});
}
};

Convert Oracle query output to json (Oracle / NodeJS)

I'm doing an app with React / Express (NodeJS) / Oracle,
I have an Express route that gets datas from an Oracle table,
Here's a part of the code in the route :
let conn;
try {
conn = await oracledb.getConnection(config);
const result = await conn.execute("select JSON_OBJECT ('departement' VALUE departement, 'ufh' VALUE ufh, 'libelle' VALUE libelle, 'nomhopital' VALUE nomhopital, 'typeservice' VALUE typeservice, 'actif' VALUE actif) from Z_SOUPAP2CARTESITE where actif=1");
res.send(result.rows);
}
But when I go on the route in the browser, the datas have this shape :
[["92","028X362","ABC ACCUEIL URG MEDECINE","ANTOINE BECLERE","ADULTE",1],["92","028X472","ABC URGENCES PEDIATRIQUE","ANTOINE BECLERE","PEDIATRIE",1],["92","014X545","APR ACCEUIL URGENCES ADU","AMBROISE PARE","ADULTE",1]]
and I want this :
[
{"departement":"92","ufh":"028X362","libelle":"ABC ACCUEIL URG MEDECINE","nomhopital":"ANTOINE BECLERE","typeservice":"ADULTE","actif":1},
{"departement":"92","ufh":"028X472","libelle":"ABC URGENCES PEDIATRIQUE","nomhopital":"ANTOINE BECLERE","typeservice":"PEDIATRIE","actif":1}
]
Why are you using JSON_VALUE? The driver returns native JavaScript objects. You could write the query as:
select department "department",
ufh "ufh",
libelle "libelle",
nomhopital "nomhopital",
typeservice "typeservice"
from Z_SOUPAP2CARTESITE
where actif=1
In the query above, the double-quoted column aliases are used to control the case of the keys.
By default, the driver returns an array of arrays (no keys). If you want an array of objects, you need to pass an options object to execute that changes the outFormat. See this part of the doc: https://oracle.github.io/node-oracledb/doc/api.html#queryoutputformats
Here's an example from the doc:
const result = await connection.execute(
`SELECT department_id, department_name
FROM departments
WHERE manager_id < :id`,
[110], // bind value for :id
{ outFormat: oracledb.OUT_FORMAT_OBJECT }
);
console.log(result.rows);
If you want to use the JSON generation functions in Oracle, such as JSON_VALUE, you have to avoid a double parse - just access the string as JSON.
See this series for more info on building a REST API with Node.js and Oracle Database: https://jsao.io/2018/03/creating-a-rest-api-with-node-js-and-oracle-database/
The below solution works for me:
app.post('/getData', async function (req, res) {
try {
const result = await connection.execute("SELECT * FORM USER", [], { outFormat: oracledb.OUT_FORMAT_OBJECT });
// print response in json file: import => const fs = require("fs");
fs.writeFile("response.json", JSON.stringify(result.rows), err => {
if (err) throw err;
console.log('File successfully written to disk');
});
res.send({
data: result.rows,
});
} catch (err) {
console.log(err);
}});

Express.JS and Node-MSSQL select error: Invalid Column name on any value that isn't an int

I think the table I'm trying to query isn't normalized (not my dataset). Whenever my where clause includes a value that is not a number I get the error below. It's as if the value of the where clause is confused with the column name itself. Now if I change the column to a field that only contains numbers, it executes without error. Any idea as to why this is happening?
name: 'ERROR',
event: 'errorMessage',
number: 207,
state: 1,
class: 16,
message: "Invalid column name 'somestring'.",
serverName: 'server1234\\SQLEXPRESS',
procName: '',
lineNumber: 1
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'username',
password: 'password',
server: 'server1234',
database: 'dbname1234'
};
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from dbo.recordset3 where column4=somestring', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});```
Solved! when using where you need to use escaped single quotes.
where column4 = \'somestring\'
request.query(('select * from users WHERE username=' + '\'' + req.body.username + '\''), function (err, recordset) {
U should use request.input function to pass values to query to avoid sql injection attempts.
https://www.npmjs.com/package/mssql#input-name-type-value
https://www.npmjs.com/package/mssql#sql-injection
// create Request object
var request = new sql.Request();
//use request.input
request.input('column4',sql.VarChar,"somestring");
// query to the database and get the records
request.query('select * from dbo.recordset3 where column4=#column4', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});

How To Bind Node-js DB Query to Web Form

I'm using node and postgres, I'm new to writing async function, what I'm trying to do is a very simple query that will do a total count of records in the database, add one to it and return the result. The result will be visible before the DOM is generated. I don't know how to do this, since async function doesn't return value to callers (also probably I still have the synchronous mindset). Here's the function:
function generateRTA(callback){
var current_year = new Date().getFullYear();
const qry = `SELECT COUNT(date_part('year', updated_on))
FROM recruitment_process
WHERE date_part('year', updated_on) = $1;`
const value = [current_year]
pool.query(qry, value, (err, res) => {
if (err) {
console.log(err.stack)
} else {
var count = parseInt(res.rows[0].count) + 1
var rta_no = String(current_year) + '-' + count
callback(null, rta_no)
}
})
}
For the front-end I'm using pug with simple HTML form.
const rta_no = generateRTA(function (err, res){
if(err){
console.log(err)
}
else{
console.log(res)
}
})
app.get('/new_application', function(req, res){
res.render('new_application', {rta_number: rta_no})
});
I can see the rta_no in console.log but how do I pass it back to the DOM when the value is ready?
Based on the ajax call async response, it will update the div id "div1" when it gets the response from the Node js .
app.js
app.get("/webform", (req, res) => {
res.render("webform", {
title: "Render Web Form"
});
});
app.get("/new_application", (req, res) => {
// Connect to database.
var connection = getMySQLConnection();
connection.connect();
// Do the query to get data.
connection.query('SELECT count(1) as cnt FROM test ', function(err, rows, fields) {
var person;
if (err) {
res.status(500).json({"status_code": 500,"status_message": "internal server error"});
} else {
// Check if the result is found or not
if(rows.length==1) {
res.status(200).json({"count": rows[0].cnt});
} else {
// render not found page
res.status(404).json({"status_code":404, "status_message": "Not found"});
}
}
});
// Close connection
connection.end();
});
webform.pug - Via asynchronous call
html
head
script(src='https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js')
script.
$(document).ready(function(){
$.ajax({url: "/new_application", success: function(result){
$("#div1").html(result.count);
}});
});
body
div
Total count goes here :
#div1
value loading ...
That seems okay, I'm just not sure of this:
The result will be visible before the DOM is generated
This constraint defeats the purpose of async, as your DOM should wait for the returned value to be there. Instead of waiting for it you could just render the page and once the function returns and runs your callback update the value.
Also, perhaps it's worth having a look into promises

How to implement query string parameters for RESTful APIs

I am new to RESTful APIs and I've successfully implemented the GET and DELETE command for my API (GET localhost:4000/api, DELETE localhost:4000/api on Postman works fine).
Code for my get looks like:
router.get('/', function(req, res) {
user.find({}, function(err, users) {
if(err){
res.status(404).send({
message: err,
data: []
});
} else {
res.status(200).send({
message: 'OK',
data: users
});
}
});
});
Now I want to implement using parameters. For example, I want to implement something like sorting where
http://localhost/4000/api/users?sort={"name": 1}
(1- ascending; -1 - descending)
would mean sorting the name in ascending order.
What I am not sure how to do is:
How do I make the ?sort thing work?
How do I select which field to sort?
Please help!
You can only pass order(asc, desc), if you want to sort by name you can do like that
http://localhost/4000/api/users?order=-1
or
http://localhost/4000/api/users?&order=1
then in your controller
router.get('/', function(req, res) {
let order = req.query.order;
user
.find({})
.sort({"name": order})
.exec(function(err, users) {
if(err){
res.status(404).send({
message: err,
data: []
});
} else {
res.status(200).send({
message: 'OK',
data: users
});
}
});
});
These works if you use mongoose.js for mongodb
One cool solution that I frequently use is the following form
/api/users?sort=-name|+firstname
I use | for multiple fields sorting, and - for desc, + for asc
In express:
const { sort } = req.query; // sort = '-name|+firstname';
const order = sort.split('|') // will return an array ['-name', '+firstname']
.reduce((order, item) => {
const direction = item.charAt(0) === '-' ? -1 : 1;
const field = item.substr(1);
order[field] = direction;
return order;
}, {})
// order {'name': -1, 'firstname': 1}
users.find({}).sort(order); // do your logic

Resources