Processing a database query in Javascript - javascript

I'm using Express and Handlebars to display a value set by the user and stored in the database.
Handlebars is set up to display the value "{{userMotto}}".
Express does the following:
function isUserAuthenticated(req, res, next) {
if (!req.user) {
res.render('index', {
user: req.user
});
} else {
currentUser = req.user.username;
userMottoCaught = queryDatabase("motto", currentUser);
next();
}
}
I want it to set the value of "userMottoCaught" to whatever it finds in the database. The query itself is this:
function queryDatabase(dbCollection, dbUID) {
this.dbCollection = dbCollection;
this.dbUID = dbUID;
return MongoClient.connectAsync(hiddenkeys.mongodbUri)
.then(function(db) {
return db.collection(dbCollection).findOneAsync({
_id: dbUID
});
})
.then(function(item) {
console.log("Found: ");
console.log(item);
return dbQueryResult;
})
.catch(function(err) {
//err
});
}
The problem is that I cannot for the life of me get the dbQueryResult out and return it to function queryDatabase itself. Probably because it's being returned to a sub function right now instead of the main function, I think. I highly suspect this can be easily resolved but I'm just at a loss on how to fix this. I am using Bluebird here to see if I could solve this with promises, but I'm not sure this is the right route either. I've also looked into callbacks but I cannot for the life of me figure out how to apply either concept to my code to solve my problem.
Later on when I render the page I do this to render it on the page:
router.get('/', isUserAuthenticated, function(req, res) {
res.render('dashboard', {
user: req.user,
userMotto: userMottoCaught
});
});
Currently this yields on the page: "Motto: [object Promise]", because I haven't returned the proper value to the main function.
Is there anyone out there with some wise words?
Cheers,
Dean

i think you need to make a callback here
function isUserAuthenticated(req, res, next) {
if (!req.user) {
res.render('index', {
user: req.user
});
} else {
currentUser = req.user.username;
userMottoCaught = queryDatabase("motto", currentUser,function(err,data){
userMottoCaught = data
next();
});
}
}
and the definition of queryDatabase should look like
function queryDatabase(dbCollection, dbUID,cb) {
this.dbCollection = dbCollection;
this.dbUID = dbUID;
return MongoClient.connectAsync(hiddenkeys.mongodbUri)
.then(function(db) {
return db.collection(dbCollection).findOneAsync({
_id: dbUID
});
})
.then(function(item) {
console.log("Found: ");
console.log(item);
dbQueryResult = JSON.stringify(item.motto);
cb(null,dbQueryResult)
})
.catch(function(err) {
//err
cb(err);
});
}

Related

JS file not pulling model.findByPk() using "/:id"?

I'm trying to pull items from my database using each item's id, but am receiving an empty object when running it through Insomnia. For example, in the code below, I would like to pull a category by ID, but also include any associated Products.
Any idea what I might be doing wrong? Thank you in advance!
router.get('/:id', async (req, res) => {
try {
const oneCategory = await Category.findByPk({
include: [{ model: Product }]
});
// console.log(oneCategory);
if (!oneCategory) {
res.status(404).json({ message: 'No category found with that id!' });
return;
}
res.status(200).json(oneCategory);
} catch (error) {
res.status(500).json(error);
}
});
When calling the findByPk method, you need to pass the key you are looking for. In this particular case, the code should look like this:
router.get('/:id', async (req, res) => {
try {
const oneCategory = await Category.findByPk(req.params.id, {
include: [{ model: Product }]
});
if (!oneCategory) {
res.status(404).json({ message: 'No category found with that id!' });
return;
}
res.status(200).json(oneCategory);
} catch (error) {
res.status(500).json(error);
}
});
So just grab the id from the URL with req.params.id and pass it to findByPk. However, it could be a good idea to check so that the id is in fact an integer before doing so :)

Nodejs variable prints on console but not on the view

the code is this
module.exports = {
index: function (req, res, next) {
//get an array of all users in user collection
Notification.find(function foundNotification(err, notifications) {
if (err) return next(err);
var elusuario=[];
User.findOne(2, function foundUser (err, user) {
if (err) return next(err);
if (!user) return next();
console.log(user);
console.log("----------------------------");
elusuario = user;
console.log(elusuario);
});
res.view({
notifications: notifications,
elusuario: elusuario
});
})
}
};
That is the controller and in the console prints elusuario good but in the view the user hasn't values. why?
i think is something is something related to the globals variables. but i dont know
thanks
EDIT
all right so the method is async. what im trying to do is find the notifications and the user by her user.id and get the user.name so what if i do this
module.exports = {
index: function (req, res, next) {
//get an array of all users in user collection
Notification.find(function foundNotification(err, notifications) {
if (err) return next(err);
User.find(function foundUser (err, users) {
if (err) return next(err);
var usuarios_locotes = [];
_.each(notifications, function (notification) {
_.each(users, function (user) {
if(notification.token_user==user.token){
console.log(user.token);
usuarios_locotes.push(user);
console.log(usuarios_locotes);
};
});
});
res.view({
notifications: notifications,
users: usuarios_locotes
});
});
})
}
};
it still not working? the __.each is an async funtion to?
sorry for all this maybe stupid questions
The method findOne of User object runs asynchronously. Because of this, you are rendering the view before the findOne returns the user object.
If you put a console.log before the render.view, it'll print the output before the console.log inner findOne method.
When the code is running, the function foundNotification is not executed before you call the res.view. My advice for you is read about Promises.
You can change your code as below to work:
function (req, res, next) {
//get an array of all users in user collection
Notification.find(function foundNotification(err, notifications) {
if (err) return next(err);
var elusuario=[];
User.findOne(2, function foundUser (err, user) {
if (err) return next(err);
if (!user) return next();
console.log(user);
console.log("----------------------------");
elusuario = user;
console.log(elusuario);
res.view({
notifications: notifications,
elusuario: elusuario
});
});
});
}
the findOne Method is an asynchrone method,so it's executed without provinding the res.view with the appropriate data
try to wrap the whole logic in the same function, it may look ugly but it ll do the thing for now
All right so.. first really thanks to everybody. I solve this shit.
I know this is not the right way to do this but it works, so for my proposes it's fine.
the problem after the EDIT was that in the view I'm trying to write an object with parameters but what I've was sending was vector of vector so changing this line:
usuarios_locotes.push(new Object(users[h]));
I can send a vector of objects.
So.. anyway thanks cause later i will change my code to do it better and efficient
This was my first post so sorry for not read the first steps of how to use this haha cause i think i have been make a lot of mistakes.
And sorry for my English :C

Trying to create a function nodejs express

Im trying to create a function so i dont use the same code again and again but i keep getting internal error.I get the data and then i get the internal error so if i change something i need to refresh the page to be updated.I cant understand why i get the error.Here is the error
GET http://localhost:3000/api/pages 500 (Internal Server Error)
Object {data: "", status: 500, config: Object, statusText: "Internal Server Error"}
code:
function Get(some,that,res){
return some.find(function(err,that) {
if (!err) {
return res.send(that);
} else {
return res.send(500, err);
}
});
};
router.get('/pages', sessionCheck, function() {
Get(Page,pages,res);
});
UPDATE: i might doing something wrong so lets take it from the start.How can i create a function that do that so i dont reuse the same code again and again.
router.get('/pages', function(request, response) {
return Page.find(function(err, pages) {
if (!err) {
return response.send(pages);
} else {
return response.send(500, err);
}
});
});
and here is my full code
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Page= require('../models/page.js');
var bcrypt = require('bcrypt-nodejs');
function Get(some,that,response){
return some.find(function(that,err) {
if (!err) {
return response.send(that);
} else {
return response.send(500, err);
}
});
};
router.get('/pages', sessionCheck, function(request,response) {
Get(Page,pages,response);
});
router.METHOD will first call your function sessionCheck. You will then need to call next() within sessionCheck to call the next function, in which you are not defining any parameters (typically you would define req, res).
If you are using express your function call should probably be:
function someGetFunc(req, res, next)
You have res as the third parameter, so that might be the problem.
Now the Get function you have above is internal to an anonymous function that doesn't take in params, so what you are passing into it are either undefined or reference global scope variables.
ok i fixed it like that i shouldnt have left the function empty it required res,req
function Get(Some,that,res){
return Some.find(function(err,that) {
if (!err) {
return res.send(that);
} else {
return res.send(500, err);
}
});
};
router.get('/pages', sessionCheck,function(req,res) {
Get(Page,pages,res);
});

Mongoose.findOne doesn't return anything, why?

I need to return the search results from Mongoose.findOne to variable
results = Lang.findOne({page: params.page,lang: params.lang, param: params.param}, function(err, lang) {
if( err || !lang) {
console.log("No translation!");
} else {
return lang.trans;
};
}
Is there a way to do this? I tried several hours to find a solution with async. functions and nothing ...
I also found articles where it was said that this is impossible, but is there any alternative for realize this?
It's really important to me because I need this to my multilingual project, I need to get the translation:
res.render('index',{titleGen : req.__({page:'home', lang:req.locale, param:'hello'})});
Here is the solution:
exports.getLang = getLang = function(params,callback){
console.log('received: '+params.page+' + '+params.lang+' + '+params.param);
Lang.findOne({page: params.page, lang: params.lang, param: params.param},function(err, lang){
if(err)
console.log(err)
else{
callback(lang.trans);
}
});
}
and routing:
router.get('/', function(req, res) {
req.__({page:'home', lang:req.locale, param:'hello'},function(text){
res.render('index',{titleGen : text });
})
});

Retrieving data from MongoDB using NodeJS with Express

Okay, so in the past few days I started messing with Node (because I think I should learn something that is actually useful and might get me a job). Right now, I know how to serve pages, basic routing and such. Nice. But I want to learn how to query databases for information.
Right now, I'm trying to build an app that serves as a webcomic website. So, in theory, the application should query the database when I type in the url http://localhost:3000/comic/<comicid>
I have the following code in my app.js file:
router.get('/', function(req, res) {
var name = getName();
console.log(name); // this prints "undefined"
res.render('index', {
title: name,
year: date.getFullYear()
});
});
function getName(){
db.test.find({name: "Renato"}, function(err, objs){
var returnable_name;
if (objs.length == 1)
{
returnable_name = objs[0].name;
console.log(returnable_name); // this prints "Renato", as it should
return returnable_name;
}
});
}
With this setup I get console.log(getName()) to output "undefined" in the console, but I have no idea why it doesnt get the only element that the query can actually find in the database.
I have tried searching in SO and even for examples in Google, but no success.
How the hell am I supposed to get the parameter name from the object?
NodeJs is async. You need a callback or Promise.
router.get('/', function(req, res) {
var name = '';
getName(function(data){
name = data;
console.log(name);
res.render('index', {
title: name,
year: date.getFullYear()
});
});
});
function getName(callback){
db.test.find({name: "Renato"}, function(err, objs){
var returnable_name;
if (objs.length == 1)
{
returnable_name = objs[0].name;
console.log(returnable_name); // this prints "Renato", as it should
callback(returnable_name);
}
});
}
The getName function is making an asynchronous call to Mongo with db.test.find. You can see this by adding a console.log after the async function. Like this:
function getName(){
db.test.find({name: "Renato"}, function(err, objs){
var returnable_name;
if (objs.length == 1) {
returnable_name = objs[0].name;
console.log(returnable_name);
return returnable_name;
}
});
console.log('test'); // <!-- Here
}
In all likeliness, this will output:
test
Renato
You need to provide a callback to your getName function.
router.get('/', function(req, res) {
getName(function(err, name) {
res.render('index', {
title: name,
year: date.getFullYear()
});
})'
});
function getName(cb){
db.test.find({name: "Renato"}, function(err, objs){
if(err) cb(err);
var returnable_name;
if (objs.length == 1) {
returnable_name = objs[0].name;
return cb(null, returnable_name);
} else {
// Not sure what you want to do if there are no results
}
});
}

Categories

Resources