Every second run throws: MongoError: Topology was destroyed - javascript

I am building a REST API but every second time I load my site I get a MongoError: Topology was destroyed. Can someone help me fixing this? I have a feeling that there is something wrong with the asynchronous running.
const client = new MongoClient(apiconfig.mongoUrl, {
useNewUrlParser: true
});
app.get("/api/:object", (req, res) => {
mongodb(req.params["object"], async (collection: Collection) => {
if (collection !== undefined) {
let result = await collection.find().toArray();
res.send(result);
}
else {
res.sendStatus(404);
}
});
});
const mongodb = (coll: string, operation: (collection: Collection) => Promise<void>) => {
client.connect((err) => {
const db = client.db("VaorraJS");
db.collections().then((collections) => {
operation(collections.find((collection) => collection.collectionName === coll)).then(() => {
client.close();
});
}).catch((error) => {
console.log("ERROR: " + error);
});
});
}
app.listen(5000);

I would suggest the use Mongoose
you are creating DB connection for every request, which is not the correct way
const MongoClient = require('mongodb').MongoClient;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = '<some db>';
// Use connect method to connect to the server
let db;
MongoClient.connect(url, function (err, client) {
assert.equal(null, err);
console.log("Connected successfully to server");
db = client.db(dbName);
});
app.get("/api/:object", async(req, res) => {
const collection = db.collection(req.params["object"]);
let result = await collection.find().toArray();
res.send(result);
});

Related

Executing mysql query suspends process and code after won't be executed

I'm asking help as I'm trying to get 2 different sets of data from a mysql db. I've written 2 separate functions using promisify. Unfortunately when I execute this node file only the first function gets executed and shown in the console. After some debugging I think it's await query(...) the cause of this problem. After this query (the one inside getSources() ) is executed, the process is suspended and I've got to terminate it. I also tried using mysql2 and moving con.end() to a different line unsuccesfully. Of course any help we'll be appreciated.
import mysql from 'mysql';
import { promisify } from 'util';
import express from 'express';
import path from 'path';
const sql = "SELECT `id` FROM `probes` WHERE `country`= ?";
const sql1 = "SELECT `fqdn` FROM `anchors` WHERE `country`= ?";
let sources = []; //sources
let targets = []; //targets
const app = express();
const __dirname = path.resolve();
app.use(express.urlencoded( {extended: true} ));
app.use(express.static(__dirname));
const con = mysql.createConnection({
host:'localhost',
user:'root',
password:'',
database:'probes&anchors'
});
const query = promisify(con.query).bind(con);
const getSources = async (from) => {
console.log("I'm in getSources");
con.connect((err)=>{
if(err){
console.log("Connection not proper");
}else{
console.log("connected");
}
});
await query(sql, [from], (err, rows) => {
console.log("error in query: "+ err);
if (err) throw err;
rows.forEach((v) => {
sources.push(v.id);
});
console.log(sources);
con.end(err => {
if(err) console.log(`${err.toString()}`)
console.log('con ended')
});
});
};
const getTargets = async (to) => {
console.log("I'm in getTargets");
con.connect((err)=>{
if(err){
console.log("Connection not proper");
}else{
console.log("connected");
}
});
await query(sql1, [to], (err, rows) => {
console.log(err);
if (err) throw err;
rows.forEach((v) => {
targets.push(v.fqdn);
});
con.end(err => {
if(err) console.log(`${err.toString()}`)
console.log('con ended')
});
});
};
app.post('/', async function(req,res){
await getSources(req.body.from_country);
await getTargets(req.body.to_country);
console.log(sources);
console.log(targets);
res.send("Loaded");
});
app.get('/', (req, res) => res.send('Hello World! From Node.js'));
app.listen(8000, () => console.log('Example app listening on port 8000!'));

Middleware is breaking redis / express setup

I'm using redis for the first time, and I can't quite figure out why my middleware 'cache' function is breaking my code? It works great without it, displays in the browser, if I go to my terminal and check for a key value pair it works great.
Here is my setup:
const express = require("express");
const redis = require("redis");
const axios = require("axios").default;
const PORT = process.env.PORT || 5000;
const REDIS_PORT = process.env.PORT || 6379;
const client = redis.createClient(REDIS_PORT);
client.connect();
const app = express();
function setResponse(username, repos) {
return `<h2>${username} has ${repos} Github repos</h2>`;
}
// make req to github
async function getRepos(req, res, next) {
try {
console.log("fetching data...");
const { username } = req.params;
const response = await axios.get(
`https://api.github.com/users/${username}`
);
const data = response.data;
const repos = data.public_repos;
// set to redis
client.set(username, repos);
res.send(setResponse(username, repos));
} catch (err) {
console.log(err);
res.status(500);
}
}
// Cache middleware
function cache(req, res, next) {
const { username } = req.params;
client.get(username, (err, data) => {
if (err) throw err;
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
}
app.get("/repos/:username", cache, getRepos);
app.listen(5000, () => {
console.log(`App listening on port ${PORT}`);
});
Any advice would be much appreciated!
Your cache function
function cache(req, res, next) {
const { username } = req.params;
client.get(username, (err, data) => {
if (err) throw err;
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
});
}
uses node redis 3 "logic" so it's hanging
redis 4 is promise led, so you need to use async/await or .then/.catch
So something like this should work for the .then/.catch approach
// Cache middleware
function cache(req, res, next) {
console.log('caching for', req.params);
const { username } = req.params;
client.get(username)
.then((data) => {
if (data !== null) {
res.send(setResponse(username, data));
} else {
next();
}
})
.catch(err => {
if (err) throw err;
});
}
This will solve your initial problem of "why it's getting stuck"

Cannot retrieve all entries from MongoDB collection

i'm trying to retrieve all entires from mongo yet I keep on getting an error that I couldn't find any while having there are some entries.
const { MongoClient } = require('mongodb');
const url = 'mongodb://localhost:27017';
const dbName = 'toy_db';
tryMongo();
function tryMongo() {
MongoClient.connect(url, (err, client) => {
if (err) return console.log('Cannot connect to DB');
console.log('Connected successfully to server');
const db = client.db(dbName);
const collection = db.collection('toy');
collection.find().toArray((err, docs) => {
if (err) return console.log('cannot find toys');
console.log('found these:');
console.log(docs);
});
client.close();
});
}
this is the error i'm getting :
Server listening on port 3030!
Connected successfully to server
cannot find toys
I have also added a picture of mongo
appreciating any kind of help!
You are closing mongo connection before you get response from server. Move client.close(); inside toArray callback.
const { MongoClient } = require('mongodb');
const url = 'mongodb://localhost:27017';
const dbName = 'toy_db';
tryMongo();
function tryMongo() {
MongoClient.connect(url, (err, client) => {
if (err) return console.log(err);
console.log('Connected successfully to server');
const db = client.db(dbName);
const collection = db.collection('toy');
collection.find().toArray((err, docs) => {
if (err) {
console.log(err);
} else {
console.log('found these:');
console.log(docs);
}
client.close();
});
});
}

How to modify common mongodb query to async with try and catch

This is my code with written with express js
this query works but I think that using async is more reliable than this
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const url = "mongodb://localhost:27017/nodejs_crud";
const db_n = "nodejs_crud"
const client = new MongoClient(url, { useUnifiedTopology: true });
app.get("/", async (req, res) => {
// this is myquery code with right result
client.connect((err) => {
assert.equal(null, err);
const db = client.db(db_n)
db.collection("list").find({}).toArray((err, result) => {
if(err) throw res.send({ status: "Error when react data", bool: false}).status(450);
res.send(result).status(200);
})
})
});
Try this, not exactly the same as yours, but will give you the idea on how to use async/await with try/catch
const MongoClient = require('mongodb').MongoClient;
const url = "mongodb://localhost:27017/nodejs_crud";
const db_n = "nodejs_crud"
const client = new MongoClient(url, { useUnifiedTopology: true });
app.get('/', async (req, res) => {
// Connect client if it's not connected
if(!client.isConnected()) {
await client.connect();
// you can also catch connection error
try {
await client.connect();
catch(err) {
return res.status(500).send();
}
}
const db = client.db(db_n);
try {
// Run queries
const result = db.collection("list").find({});
res.json(await result.toArray());
} catch (err) {
// Catch any error
console.log(err.message);
res.status(450).send();
}
});
I have not tested this, but try something along the lines of:
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const url = "mongodb://localhost:27017/nodejs_crud";
const db_n = "nodejs_crud"
let client;
const getDb = async () => {
// If we don't have a client, create one.
if (!client) client = new MongoClient(url, { useUnifiedTopology: true });
// If we are not connected, then connect.
if (!client.connected()) await client.connect();
// Get our database
return client.db(db_n);
}
app.get("/", async (req, res) => {
try {
const db = await getDb();
const results = await db.collection("list").find({}).toArray();
res.send(result).status(200);
} catch (err) {
res.send({ status: "Error when react data", bool: false}).status(450);
}
});

Node JS MongoDB collection.find.toArray returns no value

I'm building a website that lets people write sticky notes and print it to them on the screen. I want to store the sticky notes inside a mongoDB with a db called stickyNotes and a collection called stickyNotes which currently has two documents.
I have a variable called stickyNotes which suppose to get the documents from the stickyNotes collection on the db but when I use the collection.find.toArray from the mongodb library to enter the documents to the stickyNotes variable in an asynchronous way, it shows an empty array value.
This is my server.js file:
const express = require("express");
const mongo = require("mongodb").MongoClient;
const app = express();
let stickyNotes = [];
//mongodb get all sticky notes
const mongoUrl = "mongodb://localhost:27017";
mongo.connect(mongoUrl, { useNewUrlParser: true }, async function(
err,
connection
) {
if (err) {
console.error(err);
} else {
console.log("Succesfully connected to the database");
const db = connection.db("stickyNotes");
const stickyNotesCollection = db.collection("stickyNotes");
stickyNotes = await stickyNotesCollection.find({}).toArray();
}
connection.close();
});
console.log(stickyNotes);
app.use(express.static("./src/public"));
app.get("/sticky-notes", (req, res) => {
console.log("Got a request for sticky notes");
res.json(stickyNotes);
});
const port = 3000;
app.listen(port, () => {
console.log(`App is running on port ${port}`);
});
Can try with:
stickyNotesCollection.find({}, (err, result) => {
if (err) throw err;
stickyNotes = result;
});
or find result in array:
collection.find().toArray(function(err, result) {
console.log(result);
});
or iterate:
collection.find().each(function(err, result) {
//once result
});

Categories