query multiple items to send to view in node using mssql module - javascript

I am trying to query multiple tables and pass those values to my view, this is my code which is producing the error.
router.get('/', function(req, res, next) {
sql.connect(config).then(() => {
return sql.query`select Project_Type_Desc from Project_Type`
}).then(result => {
return sql.query`select Curency_Code from Currency_List`
}).then(cur => {
res.render('newProject', {projects: result} , {currency : curr})
}).catch(err => {
console.log(err)
});
});
Please let me know what i am doing wrong. Thanks is advance.

It looks to me like you're turning a value from your first query to the variable result. However you then make another query and don't retain the value as you lose scope of result, you'll want to do something like this.
router.get('/', function(req, res, next) {
// I've added a variable here which we will use to save the query
// result to.
let projectResult;
sql.connect(config).then(() => {
return sql.query`select Project_Type_Desc from Project_Type`
}).then(result => {
// Now we save the query result
projectResult = result;
return sql.query`select Curency_Code from Currency_List`
}).then(cur => {
// We are now outside of the scope from the last block (above), so we use
// the value we saved in the parent scope (router.get).
res.render('newProject', {projects: projectResult} , {currency : curr})
}).catch(err => {
console.log(err)
});
});

Related

Return value inside a collection is returned as undefined but works as a response send

I have the following GET call which works as intended, connecting to a couchbase db and performing some updates.
databaseRouter.put('/update/:id', (req, res) => {
updateDocument(req, res);
});
export const updateDocument = (req, res) => {
collection.get(req.params.id, (err, result) => {
if (err) {
res.status(404).send(err);
} else {
const document = result.value;
document.product_id = req.body.id || document.product_id;
collection.replace(req.params.id, document, (err) => {
if (err) {
res.status(500).send(err);
}
}).then(() => res.json(document));
}
}).catch(e => console.log(e));
}
This is for external clients to use.
But I want this to logic to be reusable within the project in another instance for batch processing. Not a rest call.
Thus I am looking to refactor the updateDocument function to return the document value or errors instead of performing res.send();
But I can't just modify as follows. result is undefined.
And I am also not gonna be able to maintain the status codes for errors.
Unless I explicitly return like a object with a key called status.
export const updateDocument = (req, res) => {
.....
}).then(() => document); // instead of }).then(() => res.json(document));
.....
}
databaseRouter.put('/update/:id', (req, res) => {
const result = updateDocument(req, res); // result is undefined
res.send(result);
});
Is there a way I could elegantly extract the logic so that I can continue to achieve what I have for the GET call for clients
but also be able to reuse the same logic internally within the project?

Node.js MSSQL package query function not returning data

I'm writing my first Node.js REST API. I'm using MS SQL Server as my database. I am using the npm package mssql to work with my SQL server DB.
I took the code below directly from the mssql docs example page. I simply wrapped it into a function.
function getServices() {
sql
.connect(config)
.then((pool) => {
// Query
return pool
.request()
.input("SID", sql.Int, 1)
.query(
"select * from [dbo].[Services] where ServiceId = #SID"
);
})
.then((result) => {
//console.dir(result); //this has data.
return result;
})
.catch((err) => {
console.log(err);
return err;
});
}
The above code works just fine and gets the data from my DB. The issue happens when I try to make this code into a function that I can use on my express route, as shown below.
router.get("/", (req, res, next) => {
const data = getServices();
console.log("data: ", data); //this comes back as undefined
res.status(200).json({
message: "Handling GET request from /services router.",
});
});
From reading the docs and all the others posts on stackoverflow. I am using the .then() promise mechanism, so why is my "result" not getting back to the function on my express route? The "data" const on the express route is always undefined. What am I missing here?
Rule of thump: calling a function const data = getServices(); means that this function doesn't contain any asynchronous work like async/await/.then/.catch/Promise.
Once a function containes one of those, it should always be called with one of the above.
SO #1 you must change
router.get("/", async (req, res, next) => {
const data = await getServices();
console.log("data: ", data); //this comes back as undefined
res.status(200).json({
message: "Handling GET request from /services router.",
});
});
Then the function itself
function getServices() {
try {
return sql
.connect(config)
.then((pool) => {
// Query
return pool
.request()
.input("SID", sql.Int, 1)
.query(
"select * from [dbo].[Services] where ServiceId = #SID"
);
})
.then((result) => {
//console.dir(result); //this has data.
return result;
})
} catch(ex){
return ex;
}
}
I kept digging through some more SO posts and found my working solution. Updated, working code is posted below.
router.get("/", (req, res, next) => {
getServices().then((result) => {
res.status(200).json(result.recordset);
});
});
function getServices() {
return new Promise((resolve) => {
sql
.connect(config)
.then((pool) => {
// Query
return pool
.request()
.input("SID", sql.Int, 1)
.query(
"select * from [dbo].[Services] where ServiceId = #SID"
);
})
.then((result) => {
//console.dir(result);
resolve(result);
})
.catch((err) => {
console.log(err);
resolve(err);
});
});
}

How do i return data from a database?

I cant subscribe to an observable returned by a stored procedure on server-side.
Im trying to call a stored procedure on a controller, like this
alerts: async ( req, res, next ) => {
try{
let id_user = req.params.id
let res_array = []
return await Database.knex.raw( 'CALL getAlerts( ? )', [id_user] ).then( response => {
response[0][0].map( res => {
res_array.push(res)
})
return res_array
} )
} catch ( error ) {
return next( error );
}
}
This is called on a component by using
this.api.get('alerts/'+ this.auth.user.id).subscribe( (alerts: any) => {
console.log("subscribing", alerts)
})
Through the route
router.get('/alerts/:id', controller.alerts);
The SP returns the correct values, but when I try to subscribe to access them on the component, I cant see the console log, or do anything with that observable.
Why is this? I read as much as I could on the subject but I still can't seem to pinpoint the issue. Thank you all.
That's not how you return something from Express.js. You should refactor to something like:
alerts: (req, res, next) => {
const { id } = req.params
Database.knex.raw('CALL getAlerts( ? )', [id])
.then(response => response[0][0])
.then(res.send)
.then(() => next())
.catch(next)
}

estimatedDocumentCount() returns an object instead of a number

I am trying to display the number of documents in my MongoDB database whenever the user retrieves the homepage of my web application. The following diagram shows how I wanted to implement this: https://liveuml.com/view/5db6af5e663178088afee61e
Here is the relevant code snippet for the Router
app.route('/')
.get(
(req, res, next) => {
res.locals.countOfWords = countAllWords();
next();
},
(req, res, next) => {
renderIndex(req, res);
}
);
And the relevant code snippet for the Controller
function countAllWords() {
myModel.estimatedDocumentCount({}, (err, result) => {
return result; // returns an object instead of an integer
});
}
function renderIndex(req, res) {
res.render('index', {
'countOfWords' : res.locals.countOfWords
});
}
However, the result that the Controller returns is a Query object and not an integer. So, I am seeing There are [object Object] documents in your database on the web page instead of something like There are 12 documents in your database.
What makes it even more confusing to me : When I replace the return result statement with console.log(result), I see the expected number in the console.
function countAllWords() {
myModel.estimatedDocumentCount({}, (err, result) => {
console.log(result); // displays the number as expected
});
}
My question is, how can ensure that I pass the number back to the Router instead of an object so that it can be displayed on the web page ?
I am using the latest versions of NodeJS, ExpressJS and Mongoose.
Many thanks for your help.
simply use async await and count() in mongoose:
async countAllWords()=>{
let countOfmymodel = await userModel.count({})
}

Set Variable to result of Mongoose Find

I'm trying to do something like this
function retrieveUser(uname) {
var user = User.find({uname: uname}, function(err, users) {
if(err)
console.log(err);
return null;
else
return users[0];
return user;
But this returns a document instead of a user object. The parameter users is an array of user objects matching the query, so how would I store one of the objects into a variable that my function could return?
The function User.find() is an asynchronous function, so you can't use a return value to get a resultant value. Instead, use a callback:
function retrieveUser(uname, callback) {
User.find({uname: uname}, function(err, users) {
if (err) {
callback(err, null);
} else {
callback(null, users[0]);
}
});
};
The function would then be used like this:
retrieveUser(uname, function(err, user) {
if (err) {
console.log(err);
}
// do something with user
});
Updated on 25th Sept. 2019
Promise chaining can also be used for better readability:
Model
.findOne({})
.exec()
.then((result) => {
// ... rest of the code
return Model2.findOne({}).exec();
})
.then((resultOfModel2FindOne) => {
// ... rest of the code
})
.catch((error) => {
// ... error handling
});
I was looking for an answer to the same question.
Hopefully, MongooseJS has released v5.1.4 as of now.
Model.find({property: value}).exec() returns a promise.
it will resolve to an object if you use it in the following manner:
const findObject = (value) => {
return Model.find({property: value}).exec();
}
mainFunction = async => {
const object = await findObject(value);
console.log(object); // or anything else as per your wish
}
Basically, MongoDB and NodeJS have asynchronous functions so we have to make it to synchronous functions then after it will work properly as expected.
router.get('/', async function(req, res, next) {
var users = new mdl_users();
var userData = []; // Created Empty Array
await mdl_users.find({}, function(err, data) {
data.forEach(function(value) {
userData.push(value);
});
});
res.send(userData);
});
In Example, mdl_users is mongoose model and I have a user collection(table) for user's data in MongoDB database and that data storing on "userData" variable to display it.In this find function i have split all documents(rows of table) by function if you want just all record then use direct find() function as following code.
router.get('/', async function(req, res, next) {
var users = new mdl_users();
var userData = await mdl_users.find();
res.send(userData);
});

Categories