Cant get Query by method find() Mongoose - javascript

Faced the following problem when I am trying to instantiate a Query using the find method. As a result, I get a query variable containing an object instead of Query and Query's methods are not available to me.
Controller code:
const hModel = require("../models/hModel");
const asyncHandler = require("../middleware/async");
exports.getAll = asyncHandler(async (req, res, next) => {
let query = await hModel.find({ booked: "false" });
query = query.select("location"); // TypeError: query.select is not a function
console.log(query instanceof Query); // false
res.status(200).json({ success: true, data: query });
});
asyncHandler:
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next);
module.exports = asyncHandler;
How can I get this to work properly?

(Posting this after discussion)
The problem was:
Since you await the response from .find({ booked: false }), you already have the "result" instead of "query" in query object. Hence, you will not find the select method on the result (query).
You should wait for the entire query to resolve if that's the intention: const data = await hModel.find({ booked: false}).select('location')
const hModel = require("../models/hModel");
const asyncHandler = require("../middleware/async");
exports.getAll = asyncHandler(async (req, res, next) => {
const resolvedData = await hModel.find({'booked': 'false'})
.select('location');
res.status(200).json({ success: true, data: resolvedData });
});

Try this.
const hModel = require("../models/hModel");
const asyncHandler = require("../middleware/async");
exports.getAll = asyncHandler(async (req, res, next) => {
let query = await hModel.findOne({'booked': 'false'});
console.log("Query Res", query); //make sure you have the right response from db.
query = query.location;
res.status(200).json({ success: true, data: query });
});

Try this:
const hModel = require("../models/hModel");
const asyncHandler = require("../middleware/async");
exports.getAll = async (req, res, next) => {
try {
let query = await hModel.find({'booked': 'false'}, 'location');
res.status(200).json({success: true,data: query});
} catch (error) {
next(error);
}
};

Related

axios post data successfully but failed to assign location after response success instead res.json rendered to client as html page

axios script.js file
const creatClient = async (client) => {
try {
const res = await axios({
method: 'POST',
withCredentials: true,
url: '/[url]',
data: client,
}).then(location.assign('/[newUrl]'));
} catch (error) {
console.log(error);
}
};
submitbtn.addEventListener('click', (e) => {
e.preventDefault;
const name = document.getElementById('name').value;
const phone = document.getElementById('phone').value;
const createdATT = new Date(document.getElementById('date').value);
const followUp = new Date(document.getElementById('date2').value);
const images = document.getElementById('img').value;
const insurance = document.getElementById('insurance').value;
const client = { name, phone, insurance, images, createdATT, followUp };
console.log(client);
client ? creatClient(...client) : console.log('no object created');
});
controller file
the console log for req.body [Object: null prototype] {*** the object ***}
const multer = require('multer');
const Client = require('../models/clientModel');
const multerStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'public/img');
},
filename: (req, file, cb) => {
const ext = file.mimetype.split('/')[1];
cb(null, `user-${Date.now()}.${ext}`);
},
});
const multerFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image')) {
cb(null, true);
} else {
cd(console.log('select image'), false);
}
};
const upload = multer({
storage: multerStorage,
fileFilter: multerFilter,
});
exports.uploadImages = upload.single('images');
//
exports.createClients = async (req, res, next) => {
try {
if (req.file) req.body.images = req.file.filename;
const newClient = { ...req.body };
await Client.create(req.body).then(
res.status(200).json({
status: 'success',
newClient,
})
);
} catch (err) {
console.log(err);
}
};
also with postman sending request give success response with no errors
i've tried location.replace() but also it didn't work for me
and is there another trick from server to get to the desired location out from client side
then accepts a callback as a parameter.
then(() => location.assign('/[newUrl]'))

Connect mangoDB Atlas with nodejs

I can't connect to MongoDB database, yet I tried everything ! I have successfully replaced the password.
const mongoose = require("mongoose");
mongoose
.connect(
"mongodb+srv://vibess:0KksWIBp6slcBLm0#cluster0.iuvoi.mongodb.net/?retryWrites=true&w=majority",
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
}
)
.then(() => console.log("Connected !!"))
.catch(() => console.log("Not connected!"));
Here is the Database
MangoDB
You will need another function to complete the operation. the function is usually called run then you need to write all the operations of your server in the scope of this function. here is an example of a server of mine Also you need to declare the name of your database before text retrywrites=true
//connect to mongodb
const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}#cluster0.qtoag.mongodb.net/Teletale?retryWrites=true&w=majority`;
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
async function run() {
try {
await client.connect((err) => {
const db = client.db("Teletale");
const djiPackages = db.collection("Devices");
const bookingsCollection = db.collection("bookings");
const testimonialCollection = db.collection("testimonials");
const usersCollection = db.collection("users");
// ==============GET API ====================
//GET API
app.get("/", (req, res) => {
res.send("Welcome to Teletale");
});
//GET API (dji Package)
app.get("/Devices", async (req, res) => {
const result = await djiPackages.find({}).toArray();
res.send(result);
});
//GET API (users)
app.get("/users", async (req, res) => {
const result = await usersCollection.find({}).toArray();
res.send(result);
});
// verify admin data form database
app.get("/users/:email", async (req, res) => {
const email = req.params.email;
const query = { email: email };
const user = await usersCollection.findOne(query);
let isAdmin = false;
if (user?.role === "admin") {
isAdmin = true;
}
// localhost:5000/users/admin#admin.com will show true
res.json({ admin: isAdmin });
});
//GET API (Bookings)
app.get("/bookings", async (req, res) => {
let query = {};
const email = req.query.email;
if (email) {
query = { email: email };
}
const result = await bookingsCollection.find(query).toArray();
res.send(result);
});
//GET Dynamic (Bookings)
app.get("/bookings/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await bookingsCollection.findOne(query);
res.send(result);
});
//GET Dynamic (products)
app.get("/Devices/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await djiPackages.findOne(query);
res.send(result);
});
//GET (testimonials)
app.get("/testimonials", async (req, res) => {
const result = await testimonialCollection.find({}).toArray();
res.send(result);
});
// ==========================POST API=========================
//POST API (dji Package)
app.post("/Devices", async (req, res) => {
const newTours = req.body;
const result = await djiPackages.insertOne(newTours);
res.send(result);
});
//POST API (users)
app.post("/users", async (req, res) => {
const user = req.body;
const result = await usersCollection.insertOne(user);
console.log(result);
res.send(result);
});
//POST API (Bookings )
app.post("/bookings", async (req, res) => {
const newBooking = req.body;
const result = await bookingsCollection.insertOne(newBooking);
res.send(result);
});
//POST API (Testimonials )
app.post("/testimonials", async (req, res) => {
const newBooking = req.body;
// console.log(newBooking);
const result = await testimonialCollection.insertOne(newBooking);
res.send(result);
});
// ======================DELETE API ========================
//DELETE API(Bookings)
app.delete("/bookings/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await bookingsCollection.deleteOne(query);
res.send(result);
});
//DELETE API(drone)
app.delete("/Devices/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await djiPackages.deleteOne(query);
res.send(result);
});
// =================Update API====================
app.put("/bookings/:id", async (req, res) => {
const id = req.params.id;
const newStatus = req.body;
const query = { _id: ObjectId(id) };
const options = { upsert: true };
const updateDoc = {
$set: {
data: newStatus.newData,
},
};
const result = await bookingsCollection.updateOne(
query,
updateDoc,
options
);
res.send(result);
});
//upsert Google user data
app.put("/users", async (req, res) => {
const user = req.body;
const filter = { email: user.email };
const options = { upsert: true };
const updateDoc = { $set: user };
const result = await usersCollection.updateOne(
filter,
updateDoc,
options
);
res.json(result);
});
// add admin role
app.put("/users/admin", async (req, res) => {
const user = req.body;
const filter = { email: user.email };
const updateDoc = { $set: { role: "admin" } };
const result = await usersCollection.updateOne(filter, updateDoc);
res.json(result);
});
});
} finally {
// await client.close();
}
}

Can i use route inside a controller in express js?

So I have something like this in one of my controllers:
module.exports.authToken = (req, res, next) => {
const token = req.cookies.jwt;
//console.log(token);
if (!token) {
return res.sendStatus(403);
}
try {
const data = jwt.verify(token, "secret token");
console.log(data);
req.userId = data.id;
return next();
} catch {
return res.sendStatus(403);
}
};
and it's called by a route:
router.get("/protected", authController.authToken, (req, res) => {
return res.json({ user: { id: req.userId, role: req.userRole } });
});
and I want to get a JSON response of that route in one of my other controllers. I tried some things but none of it worked.
What I would do is abstract the response out to a function for re-use:
// the function will just return the data without writing it to the response
function protectedRoute(req) {
return {user: {id: req.userId, role: req.userRole}};
}
router.get("/protected", authController.authToken, (req, res) => {
// in the actual handler you can return the response
return res.json(protectedRoute(req));
});
// make sure the middleware is still being run
router.get("/other_route", authController.authToken, (req, res) => {
// use the same function to get the response from /protected
const protectedResponse = protectedRoute(req);
// do stuff with it
});

How do you re-route multiple Express.js paths and return a single result?

I have several .get requests that I normally call, like this:
notesController
controller.get('/customers/', async (req, res, next) => {
const customers = await Customer.find();
res.status(200).send(customers);
});
controller.get('/documents/', async (req, res, next) => {
const orders = await Order.find();
res.status(200).send(orders);
});
In certain circumstances, I'd like to be able to call both at once, like this:
controller.get('/version/', async (req, res, next) => {
const ver = await Version.findById(req.headers.sub);
if (req.headers.dbversion === ver.dbversion) {
res.status(200).send({ versionMatch: true });
} else {
req.url = '/customers/';
const custData = await controller.handle(req, res, next);
req.url = '/orders/';
const orders = await controller.handle(req, res, next);
res.status(200).send({ customers: custData, docs: invoices });
}
});
But this doesn't work. Adding a console message in my .get('/customers') function, I can see that it is being called, but isn't returning any data. My desired result is that I make one API call, and if the conditions are met, it returns both sets of data at once. How do I best achieve that?
This is not possible with express. Your best bet is make the functions that handle the request standalone functions, and when your conditions are met call them to get both data sets.
controller.get('/customers/', async (req, res, next) => {
const customers = findCustomers(args);
if (condition is met) {
const orders = findOrders();
}
res.status(200).send({ customers, orders });
});
controller.get('/documents/', async (req, res, next) => {
const orders = findOrders(args);
res.status(200).send(orders);
});
function findCustomers(args) {
const customers = await Customer.find();
return customers;
}
function findOrders(args) {
const orders = await Order.find();
return orders
}

[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I'm working with PostgreSQL and NodeJS with its "PG Module".
CRUD works but sometimes doesn't update automatically the views when i save or delete some item. this is my code and I think that the error is here but i cannot find it, i tried everything :'(
Error Message:
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2, $3)',
[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}
module.exports = controller;
PD: CRUD works but sometimes appears that error.
This error occurs when you sent a response before and then you try to send response again. For this you have to check if there is any piece of code that is sending your response twice. Sometimes it happens due to asynchronous behavior of nodejs. Sometimes a process will be in event loop and we send response and when it finishes execution response will be sent again. So You can use callbacks or async await to wait for execution.
Callback
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = (request, response) => {
pool.query('SELECT * FROM recipes', (err, result) => {
if (err) {
return next(err);
}
return response.render('recipes', { data: result.rows });
});
};
controller.save = (req, res) => {
pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',
[req.body.name, req.body.ingredients, req.body.directions],function(err,resp)
{
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
};
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],function(err,resp){
if(err){
console.log(err)
}else{
return res.redirect('/');
}
});
}
module.exports = controller;
Or You can also use async await to wait for execution and then send response.
Async/Await
const controller = {};
const { Pool } = require('pg');
var connectionString = 'postgres://me:system#localhost/recipebookdb';
const pool = new Pool({
connectionString: connectionString,
})
controller.list = async(request, response) => {
try{
const result = await pool.query('SELECT * FROM recipes');
return response.render('recipes', { data: result.rows });
}
catch(err){
return next(err);
}
};
controller.save = async(req, res) => {
try{
await pool.query('INSERT INTO recipes(name, ingredients, directions) VALUES ($1, $2,$3)',[req.body.name, req.body.ingredients, req.body.directions]);
return res.redirect('/');
}
catch(err){
return next(err);
}
};
controller.delete = async(req, res) => {
try{
await pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id]);
return res.redirect('/');
}catch(err){
console.log(err);
}
}
module.exports = controller;
Check res.send() should not call two times.
In Controller
const getAll = function(req, res){
res.send(service.getAll(req,res));
}
In Service
const Type = require("../models/type.model.js");
exports.getAll = (req, res) => {
Type.getAll((err, data) => {
res.send(data);
});
};
Above res.send(data); two-time calling will create a problem. better to use
const getAll = function(req, res){
service.getAll(req,res);
}
You need to embed your response in the callback to the query. Since the call is asynchronous, sending the response earlier will terminate the call stack never waiting for the webapi(Behaviour may vary).
controller.delete = (req, res) => {
pool.query('DELETE FROM RECIPES WHERE ID = $1', [req.params.id],(err, result)
=> {
// error handling can be done accordingly
return res.redirect('/');
})
}

Categories

Resources