Facing issue while fetching latest data's in nodejs - javascript

I am facing the issue while fetching the latest data from MongoDB. every 3 hours I am pushing the data to the MongoDB when I fetch the latest data's I am facing an issue.
Here is the Schema
var abc = new Schema({
item_name: String,
uploadedDate: String, //"6-29-2019"
date : Date
});
Fetch the latest data's
req.body.uploadedDate = "7-2-2019" String
router.post('/todayList', (req, res, next) => {
abc.find({ "uploadedDate": { "$eq": req.body.uploadedDate} })
.then(product => {
let final = funct.duplicate(product, 'item_name'); here i am filter duplicate object
var result = [];
final.forEach(comp => {
abc.find({item_name": comp.item_name, "uploadedDate": { "$eq":
req.body.uploadedDate} }) // here i am fetching the latest uploaded data based on the item_name and pushing to the 'result'
.sort({"date":-1})
.limit(1)
.exec((err, docs) => {
console.log(docs); //i am getting the latest data here
result.push(docs);
});
})
//but here the value of 'result' is empty array
res.status(200).json({
data: result
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
I am not able to find why it's giving an empty array. please help me with this

The code inside the for loop is asynchronous.
Therefore, the response is sent with an empty result, before the queries in the for loop are done running.
You should make the code wait for the queries to finish running before sending the response.
router.post('/todayList', (req, res, next) => {
abc
.find({ uploadedDate: { $eq: req.body.uploadedDate } })
.then(product => {
let final = funct.duplicate(product, 'item_name')
var promises = []
final.forEach((err, documents) => {
promises.push(
new Promise((resolve, reject) => {
if (err) return reject(err)
abc
.find({ item_name: comp.item_name, uploadedDate: { $eq: req.body.uploadedDate } })
.sort({ date: -1 })
.limit(1)
.exec((err, docs) => {
if (err) return reject(err)
resolve(docs)
})
})
)
})
Promise.all(promises).then(result => {
res.status(200).json({
data: result
})
})
})
.catch(err => {
console.log(err)
res.status(500).json({
error: err
})
})
})

Related

Node JS throwing cannot set headers after they are sent to the client, after using mongoose.removeOne

I have a method that deletes products and before it does it check if the user who is trying to delete the product is the user who created it. When i execute it with Insomnia it successfully removes the product but i get an error on the console saying cannot set headers after they are sent to the client.
My method:
exports.deleteProduct = (req, res) => {
const id = req.params.productId;
Product.deleteOne({ _id: id, userId: req.user._id }, () => {
return res.status(401).json("Not authorized");
})
.then(() => {
return res.status(200).json("Product deleted");
})
.catch((err) => {
return res.status(500).json({
error: err,
});
});
};
I'm pretty sure this is happening because I'm chaining a .then() and .catch() after executing it.
I tried to do this but it didn't work because the err parameter that I'm sending to the callback function is null.:
exports.deleteProduct = (req, res) => {
const id = req.params.productId;
Product.deleteOne({ _id: id, userId: req.user._id }, (err) => {
if (err) {
return res.status(401).json("Not authorized");
}
return res.status(200).json("Product deleted");
});
};
When i tried this second approach I always got the 200 status, meanwhile the product didn't delete.
Any idea how to deal with this?
You can try something like this:
Product.deleteOne({ _id: id, userId: req.user._id }, (err, result) => {
if(err) {
return "something"
}
return "something else"
});
or: in async / await way
try {
await Product.deleteOne({ _id: id, userId: req.user._id });
} catch (err) {
// handle error here
}
By the way, why you are passing userId at the deleteOne method?

NodeJS API does't not delete nor update a data in mongodb

I am trying to update my mongoDB data, so far, the API is able to retrieve data and post a new data to MongoDb, but when i try to update or delete data, I get a success message saying either the data is updated or deleted, but the data still remains the same. It doesn't get updated nor deleted.
What could be the issue?
/* eslint-disable no-console */
const express = require('express');
const mongoose = require('mongoose');
const router = express.Router();
// importing community schema
const Community = require('../models/communitySchema');
// *Communities Route.
// fetch Communities upon request
router.get('/community', (req, res) => {
Community.find()
.then((communities) => {
console.log(communities);
res.status(200).send({ communities });
// res.send({ community });
})
.catch((err) => {
res.status(500).send({
message: err.message || 'Something wrong while retrieving Communities.'
});
});
});
// Fetch a single Community upon request
router.get('/community/:id', (req, res) => {
Community.findOne({
_id: mongoose.Types.ObjectId(req.params.id)
})
.then((community) => {
res.status(200).json(community);
})
.catch((error) => {
res.status(404).json({
error
});
});
});
// Updating a Community
router.put('/community/:id', (req, res) => {
const community = new Community({
_id: req.params.id,
name: req.body.title,
population: req.body.population,
location: req.body.location
});
Community.updateOne({ _id: mongoose.Types.ObjectId(req.params.id) }, community)
.findOne({ _id: mongoose.Types.ObjectId(req.params.id) })
.then(() => {
res.status(201).json({
message: 'Community updated successfully!',
community
});
})
.catch((error) => {
res.status(400).json({
error
});
});
});
// Deleting A community
router.delete('/community/:id', (req, res) => {
Community.deleteOne({ _id: mongoose.Types.ObjectId(req.params.id) })
.findOne({ _id: mongoose.Types.ObjectId(req.params.id) })
.then((community) => {
console.log(community);
res.status(200).json({
message: `${community} Community Deleted`
});
})
.catch((error) => {
res.status(400).json({
error
});
});
});
// Create Community
router.post('/community', (req, res) => {
// new instance of community to recieve request from client
const community = new Community({
name: req.body.name,
population: req.body.population,
location: req.body.location
});
// save the comunity details to databse
community
.save()
.then(() => {
console.log(community);
res.status(200).send({ community });
// res.send({ community });
})
// throw error if community detais is not saved
.catch((err) => {
res.status(500).send({
message: err.message || 'Something wrong while adding Community.'
});
});
});
module.exports = router;
In update, you don't need to create a new mongoose object and pass it to the update, you just need to pass a normal javascript object to the update part in updateOne query
also, you don't need to do findOne after that updateOne
if you need to get the document after the update you can use findOneAndUpdate() and pass { new: true } as the options to get the document after the update
your update route may be something like that
// Updating a Community
router.put('/community/:id', (req, res) => {
const community = { // normal object
// _id: req.params.id, // we don't need to update the _id
name: req.body.title,
population: req.body.population,
location: req.body.location
};
Community.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(req.params.id) }, // filter part
{ $set: community }, // update part
{ new: true } // options part, new: true means return the document after the update
)
.then(updatedCommunity => {
res.status(201).json({
message: 'Community updated successfully!',
community: updatedCommunity
});
})
.catch((error) => {
res.status(400).json({
error
});
});
});
Regarding the delete, also here you don't need to do findOne after deleteOne, If the document has been deleted, then findOne will not find anything, as the document with _id = req.params.id has been already deleted in the prior deletOne
it may be something like that
// Deleting A community
router.delete('/community/:id', (req, res) => {
Community.deleteOne({ _id: mongoose.Types.ObjectId(req.params.id) })
.then(() => {
// console.log(community);
res.status(200).json({
message: 'Community Deleted'
});
})
.catch((error) => {
res.status(400).json({
error
});
});
});
hope it helps

Firebase Querying?

I have an issue querying in my firebase database. I am trying to get all data of an authenticated user from my endpoint ".../api/user".
This is the route in my code:
// GET DATA OF USER
router.route("/user").get(FBAuth, getAuthenticatedUser);
Here I use a middleware which decodes the token and sets it in the req.user, and of course verifies if the user is authenticated:
// FBAuth middleware
module.exports = (req, res, next) => {
admin
.auth()
.verifyIdToken(idToken)
.then((decodedToken) => {
req.user = decodedToken;
return db
.collectionGroup("users")
.where("idUser", "==", req.user.uid)
.limit(1)
.get();
})
.then((data) => {
req.user.name = data.docs[0].data().name
return next();
})
.catch((err) => {
console.error("Error while verifying token", err);
return res.status(403).json(err);
});
};
All the above works fine, but after the req.user set successfully, we go to the function "getAuthenticatedUser" which doesn't work:
//Controller
exports.getAuthenticatedUser = (req, res) => {
let userData = {};
db.collectionGroup("users")
.where("email", "==", req.user.email) //".where("idUser", "==", req.user.uid)" nothing works here
.limit(1)
.get()
.then((doc) => {
if (doc.exists) { // Always goes to the else no matter what query I do
userData.credentials = doc.data();
return db
.collection("comptes")
.doc(req.user.name)
.collection("courses")
.get();
}else{
return res.status(400).json({email: 'Email not found => ' + req.user.email});
// the req.user.email does exist and contain the right email, and also exists in the database...
}
})
.then((data) => {
if (data.exists) {
userData.courses= [];
data.forEach((doc) => {
userData.courses.push(doc.data());
});
}
return res.json(userData);
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
I don't see how the query can work for the logging, for the middleware but not for the actual controller which must use this setup before cause it is a private route?
I finally fixed it, if anyone has the same issue here is the solution:
exports.getAuthenticatedUser = (req, res) => {
let userData = {};
db.collectionGroup("users")
.where("email", "==", req.user.email)
.limit(1)
.get()
.then((doc) => {
if (doc.docs[0].exists) { // <----- doc.docs contain a list of data
userData.credentials = doc.docs[0].data();
return db
.collection("comptes")
.doc(req.user.name)
.collection("courses")
.get();
}
})
.then((data) => {
if (data.exists) {
userData.courses= [];
data.forEach((doc) => {
userData.courses.push(doc.data());
});
}
return res.json(userData);
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};

Firebase get request returning empty array?

I believe it may just be an error in my logic, but i'm not sure where the problem is exactly and I am looking for help debugging. I am using Firebase Cloud Firestore. I am trying to query through my "follows" collection to return all data where the key "senderHandle" is equal to the params handle and then push that data to the empty array followData. Then, loop through each followData and make a document query call to the "posts" collection. Then, loop through each of the returned documents from the "posts" collection and push each data to the empty array "posts".
When I try to return the posts array though it returns empty. My overall goal is to get all of the users the params handle follows, loop through each user to get their posts, and then push their posts into an empty array.
Functions code:
// fetch home-specific posts (of users following)
exports.getHomePosts = (req, res) => {
let posts = [];
let followData = [];
// get following users
const followDocument = db
.collection("follows")
.where("senderHandle", "==", req.params.handle);
followDocument
.get()
.then((data) => {
if (data.query.size == 0) {
return res.status(400).json({ error: "Not following any users" });
} else {
data.forEach((doc) => {
followData.push(doc.data());
});
}
})
.then(() => {
followData.forEach((follow) => {
db.collection("posts")
.where("userHandle", "==", follow.receiverHandle)
.where("location", "==", "explore")
.get()
.then((data) => {
data.forEach((doc) => {
posts.push({
postId: doc.id,
body: doc.data().body,
userHandle: doc.data().userHandle,
createdAt: doc.data().createdAt,
commentCount: doc.data().commentCount,
likeCount: doc.data().likeCount,
userImage: doc.data().userImage,
});
});
});
});
return res.json(posts);
})
.catch((err) => {
res.status(500).json({ error: err.message });
});
};
followData returned:
[
{
"receiverHandle": "John Doe",
"senderHandle": "bear"
},
{
"senderHandle": "bear",
"receiverHandle": "Yikies"
},
{
"receiverHandle": "bear",
"senderHandle": "bear"
},
{
"receiverHandle": "anon",
"senderHandle": "bear"
},
{
"senderHandle": "bear",
"receiverHandle": "BigYikes"
}
]
There are multiple issues with this code.
You are not waiting promise to be resolved.
Multiple returns statements
You would not create global arrays like posts and followData[you can return in then for next callback]
Code:
// fetch home-specific posts (of users following)
exports.getHomePosts = (req, res) => {
const followDocument = db
.collection("follows")
.where("senderHandle", "==", req.params.handle);
followDocument
.get()
.then((data) => {
if (data.query.size == 0) {
throw new Error("NOT_FOUND");
} else {
return data.map((doc) => doc.data());
}
})
.then((followData) => {
const promises = followData.map((follow) => {
return db
.collection("posts")
.where("userHandle", "==", follow.receiverHandle)
.where("location", "==", "explore")
.get();
});
Promise.all(promises).then((results) => {
const posts = results
.map((data) => {
return data.map((doc) => ({
postId: doc.id,
body: doc.data().body,
userHandle: doc.data().userHandle,
createdAt: doc.data().createdAt,
commentCount: doc.data().commentCount,
likeCount: doc.data().likeCount,
userImage: doc.data().userImage,
}));
})
.flat();
return res.json(posts);
});
})
.catch((err) => {
if (err.message === "NOT_FOUND") {
return res.status(400).json({ error: "Not following any users" });
}
res.status(500).json({ error: err.message });
});
};

Why don't changes made to a global variable in a foreach function callback reflect oustide the callback

I'm trying to retrieve some documents from mongoDB atlas, below is the code:
get('/:page/bucket_names', (req, res) => {
var page = req.params.page;
var pageBuckets = [];
MongoClient.connect(uri, (err, client) => {
if (err) res.send('error:' + err);
const db = client.db("cms");
db.collection(page).find({ $or: [{ type: 'single' }, { type: 'carousel' }, { type: 'freelist' }] }, (err, result) => {
if (err) res.send('error');
else {
result.forEach(el => {
pageBuckets.push(el);
console.log(pageBuckets) //1
})
console.log(pageBuckets) //2
}
})
client.close();
})
})
The first console.log outputs the updated pageBuckets array but the second console.log outputs an empty array. I'm not able to understand what the problem is.
Turns out the 2nd console.log was getting executed before the foreach loop , so fixed it with the below code:
result.forEach(el =>{
pageBuckets.push(el);
console.log(pageBuckets) //1
}).then(() =>{
console.log(pageBuckets); //2
})

Categories

Resources