How to query on start of server in mongoose? - javascript

Start.js:
const express = require('express')
const app = express()
const port = 3000
mongoose.connect('mongodb://localhost:27017/myapp', {useNewUrlParser: true}); //to connect with mongodb..not exact code I used but this
Now lets say I have stored some data in mongodb....in Books collection stored in model books
I call the model and fetch from it:
const bookdetails = Books.find({ }).exec()
I tried :
var respo;
bookdetails.then(function(result) {
console.log(result) //gives the value stored in bookdetails
respo = result;
})
console.log(respo) //...but value not stored in here...it gives undefined
But console.log(bookdetails) it gives....Promise { } instead of all the data stored inside book collection. How can I fetch data on start of server....if I'm using through routes or calling api it is working perfectly fine
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

You can add a callback that will execute after the promise is resolved or use async/await
let bookDetails ;
Books.find()
.exec(function (err, book) {
if(err)
throw new Error(err)
else
bookDetails = book
});
or
const bookdetails = await Books.find({ })

Related

Node.js Express show a Json file with Class Method

Just started with node.js and express and i was trying to show a json file containing an array of 3 objects with a class method
Here is the Class structure
const fs = require('fs')
class GrupoArchivo {
constructor(ruta) {
this.ruta = ruta
this.productos = []
}
_leer() {
return fs.promises.readFile(this.ruta, 'utf-8')
.then(texto => {
const productosComoArray = JSON.parse(texto)
this.productos = productosComoArray
})
}
async obtenerTodas() {
await this._leer()
return [...this.productos]
}
}
module.exports = GrupoArchivo
And here is the Js file with the express server
With the second "app.get" i was trying to get the method showing the json file with no luck
const express = require("express");
const GrupoArchivo = require('./GrupoArchivo.js')
const path = require("path");
const app = express();
app.get("/", (req, res)=>{
res.sendFile(path.join(__dirname + "/index.html"))
})
const grupo = new GrupoArchivo('./productos.json')
app.get("/productos", (req, res)=>
res.json(grupo.obtenerTodas()) //this returned me an {}
)
app.listen(8080, ()=>{
console.log("server listening on port", 8080)
})
All async functions return a promise, so when you call it, you have to use await or .then() to get the resolved value from that promise. You can add async and await like this:
app.get("/productos", async (req, res) => {
try {
res.json(await grupo.obtenerTodas());
} catch(e) {
console.log(e);
res.sendStatus(500);
}
});
Note, this also adds error handling so you can catch any errors from grupo.obtenerTodas().

Cannot access variable using await-async function

I tried using Async-Await in NodeJs RESTful API but I seem to get an error I cannot resolve.
Here is my db.js:
const User = require('../models/User'),
user = {};
user.findUserByUsername = async function (username) => {
try {
const user = await User.findOne({username});
if (user)
return {data: user, status: 200};
return {message: `Cannot find user with username: ${username}`, status: 404};
} catch (err) {
return err;
}
};
module.exports = user;
And here is my api.js:
const express = require('express'),
router = express.Router(),
user = require('../db/db');
router.get('/user', async (req, res, next) => {
const user = await user.findUserByUsername(req.query.username);
// ^
// Cannot access 'user' before initialization
if (!user.status)
return next(user);
res.status(user.status);
res.doc = user.status === 404 ? user.message : user.data;
next();
});
module.exports = router;
When making a HTTP request, my server is crashing at that point. Where is my mistake?
You're mixing your variable names up. You have user as an import, but you also have user as a variable you're trying to assign to as a result of findUserByUsername.
Use different variable names, and follow the capitalization convention for this sort of database lookup:
const express = require('express'),
router = express.Router(),
User = require('../db/db');
router.get('/user', async (req, res, next) => {
const user = await User.findUserByUsername(req.query.username);

Node GET request is hanging unable to finish the request and the page keep loading

SOLVED
I am currently building an app with Node - Express - MongoDB - ejs.
I have a books router that should render the books ejs file and books list from MongoDB.
Here's the books.js code:
const express = require("express");
const router = express.Router();
const { MongoClient } = require("mongodb");
router.route("/").get(async (req, res, next) => {
const url = "mongodb://localhost:27017";
const dbName = "Library";
let client;
try {
client = await MongoClient.connect(url, { useUnifiedTopology: true });
const db = client.db(dbName);
const books = await db.collection("books").find().toArray();
res.render({
title: "Books",
books,
});
} catch (err) {
res.send(err);
}
});
module.exports = router;
It is supposed to get the data from the MongoDB and send it back to the books page instead I get this error
{ "code": "ERR_INVALID_ARG_TYPE" }
It seems you are not calling your async mongo function. You are only declaring your function. You need to call it by placing () after your declaration like so:
(async function mongo() {
// Your code
})();
So applying that change to your code would result in the following:
const express = require("express");
const router = express.Router();
const { MongoClient } = require("mongodb");
/* GET Books page. */
router.route("/").get((req, res, next) => {
const url = "mongodb://localhost:27017";
const dbName = "Library";
(async function mongo() {
let client;
try {
client = await MongoClient.connect(url, { useUnifiedTopology: true });
const db = client.db(dbName);
const books = await db.collection("books").find().toArray();
res.render({
title: "Books",
books,
});
} catch (err) {
console.log(err);
}
})();
});
module.exports = router;
Because of this your request would indeed timeout as the code within the async function is not called.
Hope this answer was helpful 👍
You define a function called mongo but then you never call it.
Since you never call it, you never call res.render.
Even if you did call it, in the catch branch you never send an error response either.
It looks like you intended it to be an IIFE but forgot the () afterwards. There's no need for that though, you can just make the function you pass as the second argument to get() async instead.
router.route("/").get(async (req, res) => {
const url = "mongodb://localhost:27017";
const dbName = "Library";
try {
const client = await MongoClient.connect(url, { useUnifiedTopology: true });
const db = client.db(dbName);
const books = await db.collection("books").find().toArray();
res.render({
title: "Books",
books,
});
} catch (err) {
console.log(err);
res.status(500).json({error: err})
}
});

Reusing postgresql pool in other node javascript files

I am creating nodejs backend app with postgresql database. What I want is when once I create connection to database in my db.js file, that I can reuse it in other files to execute queries.
This is my db.js file
const pool = new Pool({
user: 'us',
host: 'localhost',
database: 'db',
password: 'pass',
port: 5432,
})
pool.on('connect', () => {
console.log('connected to the Database');
});
module.exports = () => { return pool; }
And this is how I tried to use it in index.js file
const db = require('./db.js')
app.get('/', (request, response) => {
db().query('SELECT * FROM country'), (error, results) => {
if (error) {
response.send(error)
}
console.log(results)
response.status(201).send(results)
}
})
There aren't any errors, and when I go to this specific page, it's keep loading. Nothing in console also.
But, if I write a function in my db.js file and do something like pool.query(...), export it, and in my index.js I write app.get('/', exportedFunction), everything is working fine.
Is there any way not to write all my (like 50) queries in just one (db.js) file, because I want to organise my project a little bit?
To streamline your project structure entirely, if you're starting from scratch maybe try this :
index.js
const express = require('express');
const app = express();
const PORT = 8080;
const bodyparser = require('body-parser');
const baseRouter = require('../your-router');
app.use(bodyparser.json());
app.use(express.json());
app.use('/', baseRouter);
app.listen(PORT, function () {
console.log('Server is running on PORT:', PORT);
});
your-router.js
const Router = require('express');
const router = Router();
const getCountries = require('../handlers/get');
router.get('/check-live', (req, res) => res.sendStatus(200));
// route for getCountries
router.get('/countries', getCountries);
src/handler/get.js
const YourService = require('./service/your-service');
function getCountries(request, response) {
const yourService = new YourService();
yourService.getCountries(request)
.then((res) => { response.send(res); })
.catch((error) => { response.status(400).send({ message: error.message }) })
}
module.exports = getCountries;
src/service/your-service.js
const connectionPool = require('../util/dbConnect');
class yourService {
getCountries(req) {
return new Promise(((resolve, reject) => {
connectionPool.connect((err, db) => {
if (err) reject(err);
let query = format('SELECT * FROM country'); // get inputs from req
db.query(query, (err, result) => {
if (err) reject(err);
resolve(result);
})
});
}));
}
}
module.exports = yourService;
dbConnect.js
const pgCon = require('pg')
const PGUSER = 'USER'
const PGDATABASE = 'localhost'
let config = {
user: PGUSER,
database: PGDATABASE,
max: 10,
idleTimeoutMillis: 30000
}
let connectionPool = new pgCon.Pool(config);
module.exports = connectionPool;
Please consider this as a basic example, refactor your code to use callbacks/async awaits (in the above example you can just use callbacks not needed to convert into promise), if needed - you can have DB-layer calls from the service layer in order to extract DB methods from the service layer.

Returning undefined object when doing a query

I'm building an application on Node.js that works with MongoDB through mongoose. The connection is perfect, I can add new documents, the problem is definitely not in the connection.
I'm building all the functions that work with mongoose in a separate .js file, which I called from dbconfig.js.
dbconfig.js
const mongoose = require('mongoose');
// Models
const User = require('./models/User');
const Category = require('./models/Category');
var database_name = "htm";
mongoose.Promise = global.Promise;
// Connection with database_name
var connect = () => {
mongoose.connect("mongodb://localhost/"+database_name, {useNewUrlParser: true}).then(() =>{
console.log("Conectado ao database: " + database_name);
}).catch((erro) => {
console.log("Erro ao se conectar ao database: " + database_name +" - "+ erro);
});
mongoose.model('users', User);
mongoose.model('categories', Category);
}
var getCategory = () => {
const Ref = mongoose.model('categories');
Ref.find().then((categories) => {
return categories;
})
}
module.exports = {
connect: connect,
getCategory: getCategory
}
The problem is in the getCategory () function, when I call it in my app.js (my main file of this project node.js), it returns only undefined. And I know that the variable categories are filled out because I inserted a console.log (categories); and got the following result:
[ { _id: 5c7ea6fb91526418ec3ba2fd,
name: 'UNHAS',
slug: 'unhas',
__v: 0 } ]
app.js
const express = require('express');
const app = express();
const categoriesRouter = require('./routes/categories');
const handlebars = require('express-handlebars');
const path = require('path');
const configDB = require('./dbconfig')
// Config
// Template Engine
app.engine('handlebars', handlebars({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
// Start Database Connection
configDB.connect();
// Public
app.use(express.static(path.join(__dirname, "public")));
// Routes
app.use('/categorias', categoriesRouter);
app.get('/', (req, res) => {
var categories = configDB.getCategory();
res.render('home', categories);
});
app.listen(3001, () =>{
console.log("Servidor iniciado na porta 3001");
});
Whenever the variable categories is received in my app.js it arrives as undefined.
Can someone help me?
You are not properly using the Promise object returned from getCategory() in your express router:
app.get('/', (req, res) => {
var categories = configDB.getCategory(); <-- this is a Promise, not a synchronous value
res.render('home', categories);
});
Instead, you can use async/await to help bridge the gap between your currently synchronous code and the asynchronous Promise-based database interface you have:
app.get('/', async (req, res) => {
var categories = await configDB.getCategory();
res.render('home', categories);
});
Inspired by a response given by #jakemingolla who suggested async-await, I started using callback to return the 'categories' object and everything worked perfectly.
function in my file dbconfig.js
const getCategoryList = (callback) => {
CategoryRef.find().then((categories) => {
callback(categories);
})
}
calling the function in my app.js file
app.get('/', (req, res) => {
database.getCategoryHomeList((categories) => {
res.render('home', {categories: categories});
})
});

Categories

Resources