Result after find query in mongodb not produced - javascript

After running the code, it shows "products is not defined".Where products is supposed to be result of find() query in "products" collection in mongodb. When I run the same query outside the loop, it shows the desired result. How to solve the problem.
Likes.find({"user_id": data.user_id},function(err, likes) {
if(likes === undefined) return res.notFound();
if (err) return next(err);
likedProducts = likes;
for(var key in likedProducts)
{
product_ids = likedProducts[key]['product_id'];
console.log(product_ids);
Products.find({"_id": product_ids},myCallback(err,products));
}
// return res.json(200, {'success': true, 'count': countNo, 'data': productDetails});
function myCallback(err, product_found) {
if(product_found === undefined) return res.notFound();
if (err) return next(err);
// productDetails = product_found;
console.log(product_found);
}
});

Related

Check if same genre exist in mysql database

Hi everyone I am new to mysql and would like to test if the same genre exist in a database and if it does it returns a status code and if the genre does not exist the genre is added into the database. I am currently having the following issues, it is able to check if the genre exist and return the status code but when entering a different genre it reacts the same way as if the genre exist :
file 1
Insertgenre:function(genre,description,callback){
var dbConn=db.getConnection();
// connects to the mysql database (contains an asyn function that returns a callback)
dbConn.connect(function(err){
if(err){
console.log(err);
return callback(err,result);
}else{
// Query for get all rows from genre table where genre = entered genre
var checkSql = 'SELECT genre FROM genre WHERE genre = ?';
dbConn.query(checkSql, [genre], function(err1, result) {
if(err) {
return callback(err,result);
}else {
// Checking if the result length is more than 0.
if(result.length > 0) {
return callback(err1,result);
}else {
var sql="insert into genre(genre,description) values(?,?)";
dbConn.query(sql,[genre,description],function(err,result){
dbConn.end();
if(err) {
console.log(err);
}
return callback(err,result);
}
}
}
});
file 2
app.post('/genre', function(req,res){
var genre = req.body.genre;
var description = req.body.description;
genreDB.Insertgenre(genre,description,function(err,err1,result){
if(err){
//console.log(err)
res.type('json');
res.statusCode=500;
res.send(`{"Result":"Internal Error"}`);
}if(err1){
console.log(err1)
res.type('json');
res.statusCode=422;
res.send(`{"Result":"The genre name provided already exists"}`);
}
else{
res.type("json");
res.statusCode=204;
//res.send(result);
console.log(result);
res.send(`{"Affected Rows":"${result.affectedRows}"}`);
}
});
});
Your callback function expects err to be a normal database error, and err1 to indicate that the genre already exists.
You need to call callback() with 3 arguments to match what it expects.
You also have a typo. In the second query, the callback function's argument is err1, but you used if(err).
And in file 2, you should use else if(err1) since all these conditions are mutually exclusive.
Insertgenre: function(genre, description, callback) {
var dbConn = db.getConnection();
// connects to the mysql database (contains an asyn function that returns a callback)
dbConn.connect(function(err) {
if (err) {
console.log(err);
return callback(err, false, result);
} else {
// Query for get all rows from genre table where genre = entered genre
var checkSql = 'SELECT genre FROM genre WHERE genre = ?';
dbConn.query(checkSql, [genre], function(err1, result) {
if (err1) {
return callback(err1, false, result);
} else {
// Checking if the result length is more than 0.
if (result.length > 0) {
return callback(null, true, result);
} else {
var sql = "insert into genre(genre,description) values(?,?)";
dbConn.query(sql, [genre, description], function(err, result) {
dbConn.end();
if (err) {
console.log(err);
}
return callback(err, false, result);
}
}
}
});
});
})

array push results in empty array javascript

I am trying to store API results into an array.
The data is displayed in console, but on pushing the data into an array, the array is still empty.
Here's the code:
app.post('/fetchFavoriteTweets/', verifyToken, function(req, res) {
var favorites = [];
dbConn.then( function (database) {
var dbo = database.db("twitter_search");
dbo.collection('users').findOne(
{ _id: ObjectId(req.userId) }, function(err, result) {
if(err) throw err;
if(!result.hasOwnProperty('favorite_tweets')) {
res.status(404).json({msg:'record not found'});
}
else {
result.favorite_tweets.forEach(function (tweet) {
T.get('statuses/show', {id: tweet.id}, function(err, data, response) {
if(!err){
favorites.push(data);
console.log(data); //this returns data
} else {
console.log(err);
}
});
});
console.log(favorites);
// res.status(200).json({msg:'success', data:favorites});
}
});
}).catch(function(e){console.log(e)})
});
It looks like you're defining the favorites array within the scope of the function callback. Try putting var favorites = []; above you app.post() call instead.
Also, keep in mind that it will only have a value after the callback is complete, so any synchronous code later down the line will only see the empty array value.
I've updated your code to get favorites by storing separately the promise and call it afterwards:
UPDATE
As you can see in the demo, i have 2x console.log at the bottom, the first one(C1) is contained in the promise favoritesPromise () and the second (C2) is after the promise.
Synchronous actions will never wait for asynchronus actions to take place, therefore in my example C2 will always be outputted before C1, even if console.log(1 ... ) is before console.log(2 ... ), they'll appear reversed in the console.
In the promise i added a setTimeout of 1ms to mock a request, it was all it took to achieve the current output. Another thing you can test is removing the setTimeout then output will change a bit, your promise becomes synchronus until it reaches resolve(favorites), that means favorites has all the data by now, but when resolve takes place, it becomes async, and in your console you will still see C2 first (but now with data) and C1 second.
In my earlier answer i tried to implement this reasoning to your code.
Keep it async folks!
var favorites = [];
var favoritesPromise = () => {
return new Promise((resolve, reject) => {
console.log('Retrieving data from the internet.');
// This timeout mocks your request to anything that is async or promie
setTimeout(() => {
console.log('Request done')
let resultFavorite_tweets = [{
id: 1,
name: 'a dog'
}, {
id: 2,
name: 'a cat'
}];
resultFavorite_tweets.forEach(item => {
favorites.push(item.name);
})
resolve(favorites);
// if you have an error use
// reject(err)
}, 1);
});
}
favoritesPromise().then(favList => {
console.log(1, 'this will always contain data from the internet, but will always be last', favList);
})
console.log(2, 'this will be empty (unless you remove setTimeout), but will always be first', favorites);
app.post('/fetchFavoriteTweets/', verifyToken, function(req, res) {
const favoritesPromise = () => {
return new Promise((resolve, reject) => {
var favorites = [];
dbConn.then(function(database) {
var dbo = database.db("twitter_search");
dbo.collection('users').findOne({
_id: ObjectId(req.userId)
}, function(err, result) {
if (err) reject(err);
if (!result.hasOwnProperty('favorite_tweets')) {
res.status(404).json({
msg: 'record not found'
});
} else {
result.favorite_tweets.forEach(function(tweet) {
T.get('statuses/show', {
id: tweet.id
}, function(err, data, response) {
if (!err) {
favorites.push(data);
console.log(data); //this returns data
} else {
console.log(err);
reject(err);
}
});
resolve(data);
});
console.log(favorites);
// res.status(200).json({msg:'success', data:favorites});
}
});
}).catch(function(e) {
reject(e)
})
});
}
// Here you call the promise to retrieve "favorites"
favoritesPromise().then(favoritesList => {
console.log('your favorites array', favoritesList)
})
})
Try next code
app.post('/fetchFavoriteTweets/', verifyToken, function (req, res) {
var favorites = [];
dbConn.then(function (database) {
var dbo = database.db("twitter_search");
dbo.collection('users').findOne(
{ _id: ObjectId(req.userId) }, function (err, result) {
if (err) throw err;
if (!result.hasOwnProperty('favorite_tweets')) {
res.status(404).json({ msg: 'record not found' });
}
else {
// Counter
let count = result.favorite_tweets.length;
result.favorite_tweets.forEach(function (tweet) {
T.get('statuses/show', { id: tweet.id }, function (err, data, response) {
// Decrease count
count -= 1;
if (!err) {
favorites.push(data);
// Check if count is zero
if (count === 0) {
console.log(favorites);
res.status(200).json({msg:'success', data:favorites});
}
} else {
console.log(err);
}
});
});
}
});
}).catch(function (e) { console.log(e) })
});

Firebase Functions response returns null

tried get list of objects from s3(actually from wasabi) but in react always returns null
function code:
(using node 8)
exports.fetchWasabi = functions.https.onCall(() => {
const params =
{
Bucket: 'balde1-webcars',
};
s3.listObjectsV2(params, function(err, result) {
if (!err) {
console.log(result)
return result
} else {
console.log(err);
return err
}
});
});
react code:
componentDidMount(){
var Wasabi = firebase.functions().httpsCallable('fetchWasabi');
Wasabi().then(function(result) {
var res = result.data;
console.log(res)
}).catch(function(error) {
console.log(error)
});
}
when i check the log for the function i can see the result but it never reaches my browser apparently
You are not returning anything so you should add one more return like :
return s3.listObjectsV2(params, function(err, result) { ...

Node.js Error: Can't set headers after they are sent

I know this question already exists but the solutions I found didn't work for me. I am building a basic create function in Node.js. It first checks if the object already exists and if it doesn't, creates one. And I am getting this error even after I added else if and return to every condition. But it seems everything get executed regardless. This is my code:
controllers/shop.js:
var Shop = require('../models/shop').model;
module.exports = {
create: function(req, res) {
if(typeof(req) != 'object')
return res.status(400).send({error: Error.InvalidInput});
if(req.body.name === null) return res.status(400).json({error: Error.missingParameter('name')});
Shop.findOne({name: req.body.name}, function(err, shop){
if(err) return res.status(500).json({error: Error.unknownError});
else if (shop) return res.status(409).json({error: Error.alreadyExists('Shop')});
}).exec(Shop.create({name: req.body.name}, function(err, shop) {
if (err) return res.status(500).json({error: Error.unknownError});
else if (shop) return res.status(201).json(shop);
else if (!shop) return res.status(400).json({error: Error.createFailed('Shop')});
}));
},
}
Either you should pass a callback in the find method or use a function with exec but should not use both since they both are asynchronous and invoked at the same time.
You can refactor your code as below.
var Shop = require('../models/shop').model;
module.exports = {
create: function(req, res) {
if(typeof(req) != 'object')
return res.status(400).send({error: Error.InvalidInput});
if(req.body.name === null) return res.status(400).json({error: Error.missingParameter('name')});
Shop.findOne({name: req.body.name}, function(err, shop){
if(err) return res.status(500).json({error: Error.unknownError});
else if (shop) return res.status(409).json({error: Error.alreadyExists('Shop')});
else {
Shop.create({name: req.body.name}, function(err, shop) {
if (err) return res.status(500).json({error: Error.unknownError});
else if (shop) return res.status(201).json(shop);
else if (!shop) return res.status(400).json({error: Error.createFailed('Shop')});
});
}
});
},
}
Try setting variables for the response status and error/other messages in your if statements. then at the end of your create function return a single response object populated with the variables
var Shop = require('../models/shop').model;
module.exports = {
create: function(req, res) {
var status = 200;
var message = "";
if(typeof(req) != 'object')
status = 400;
message = Error.InvalidInput;
...
return res.status(status).send({error: message});
});
}));
},
}

MongoDB get an item out of db

So i have implemented a mongodb on my nodejs server. And what I have done is store users via:
function insertUser() {
var collection = dbb.collection('user');
var user1 = {name: user, token: token};
collection.insert(user1, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
}
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.find({name: devName}).toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found: ', result);
selectedUserToken = result.token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
So result will equal:
Found: [ { _id: 57be1cadc281c03ea116c9ab,
name: 'Austin Hunter',
token: 'dJyXVjMJk08kXWrua8SUjKb....SxACihKZoR53y_wOZmcFNKMmD5q99QNvsp3flL' } ]
My question is, how can I get that token out to equal selectedUserToken so I can send a push notification with gcm? Right now result.token is undefined.
You should use findOne() instead of find() since you only expect a single result back:
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.findOne({name: devName}, function (err, result) {
if (err) {
console.log(err);
} else if (result) {
console.log('Found: ', result);
selectedUserToken = result.token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
But if you wanted to leave your code as is with the find() you would just retrieve the first element of the resulting array retrieved by find()
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.find({name: devName}).toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found: ', result);
selectedUserToken = result[0].token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
Maybe result[0].token, because result is an array of user items.

Categories