Getting "Promise { <pending> }" error at "Log.save();" - Mongodb - node.js

I am following MongoDB Atlas Blog tutorial to add info into mongodb but I am getting the above mentioned error. I have tried to resolve this error, even tried to then but still getting the same issue...
Following is my connection file
async function main(){
/**
* Connection URI. Update <username>, <password>, and <your-cluster-url> to reflect your cluster.
* See https://docs.mongodb.com/ecosystem/drivers/node/ for more details
*/
const uri = "mongodb+srv://an:abc#abc-2yzxs.mongodb.net/test?retryWrites=true&w=majority";
const client = new MongoClient(uri);
try {
// Connect to the MongoDB cluster
await client.connect();
await createListing(client,
{
msg: client.msg
}
);
return client;
} catch (e) {
console.error(e);
} finally {
await client.close();
}
}
main().catch(console.error);
async function createListing(client, newListing){
const result = await client.db("mydb").collection("mycollection").insertOne(newListing);
console.log(`New listing created with the following id: ${result.insertedId}`);
}
and following is my schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const mySchema = new Schema(
{
msg: {
type: String
}
}
);
let a = mongoose.model("mycollection", mySchema);
module.exports = a;
My Controller:
const Log = require('../models/mySchema');
require('../connection');
function createListing(data){
let Log = new Log({ msg: data});
var err = Log.save();
console.log("err is : ", err)
}
exports.createListing = createListing;
this is how I'm calling from server file
let log = require('./controllers/myController');
log.createListing(data);

Personally I wouldn't use mongoose, although you tutorial does. I just use mongodb.
import { connect } from 'mongodb'
async function main() {
// try-catch
const MONGO = 'mongodb+srv://an:abc#abc-2yzxs.mongodb.net/testretryWrites=true&w=majority'
const client = await connect(MONGO, {
useNewUrlParser: true,
useUnifiedTopology: true })
const mongo = client.db()
const Log = mongo.collection('Log')
await Log.insertOne({ message: 'test' })
}
I know it's different from the problem you have but I just don't know why mongoose is needed. It's not really.

you need to use await before Log.save() to log actual value returning by the function instead of promise pending you are getting.
async function createListing(data){
let Log = new Log({ msg: data});
let err = await Log.save();
console.log("err is : ", err)
}

Related

Promise.all() throwing error while connecting to database Error: timeout exceeded when used with Node-Postgres

I have Node.js express app with Postgres as a database. I'm using pg for database communication from the app.
This is how my db.service looks like
import { Pool } from 'pg';
const dbConfig = {/*my valid db configuration*/};
const pool = new Pool(dbConfig);
export const connectDB = async () => {
let client;
try {
client = await pool.connect();
} catch (error) {
console.error('error while connecting to database', error);
process.exit(1);
}
return client;
};
I have two queries as below
#1.
export const fetchUser = async (email) => {
const client = await connectDB();
const query = `
SELECT full_name FROM app.users
WHERE email = '${email}'
`;
let result;
try {
result = await client.query(query);
if (result.rowCount) {
return result.rows[0].full_name;
}
} catch (error) {
} finally {
await client.release();
}
return result;
};
#2
export const fetchWallet = async (email) => {
const client = await connectDB();
const query = `
SELECT wallet_money FROM app.user_wallet
WHERE email = '${email}'
`;
let result;
try {
result = await client.query(query);
if (result.rowCount) {
return result.rows[0].wallet_money;
}
} catch (error) {
} finally {
await client.release();
}
return result;
};
Now from one of my controller.js if I call these function separate await, no issues
ctrl.js
const fullName = await fetchUser('some#gmail.com');
const walletMoney = await fetchWallet('some#gmail.com');
No issues this way, however if I merge them into a single promise
const $0= fetchUser('some#gmail.com');
const $1= fetchWallet('some#gmail.com');
const result = await Promise.all([$0, $1]);
this throws the below error
error while connecting to database Error: timeout exceeded when trying
to connect at Error
Please suggest why this error is popping up & how can I get rid of it?
Thanks!
That's happening because you are trying to connect to DB separately for every query.Try to create one connection and use it for all queries!

Node.JS receive data from MongoDB on get request

I'm trying send data from a MongoDB server to the client on a GET request. I'm using an express server and want to send all the documents in a specific collection when a GET request is received.
I know MongoDB is asynchronous, so I query an asynchronous function with a promise. I am able to log to console all the documents in the MongoDB Collection but when I return it the data becomes undefined. I have a database called 'testDB' and I want to return all the documents in a specific collection ('testCollection').
app.get('/getData', (req, res) => {
returnData().then(result => {
console.log(result); //This logs undefined
res.send(result); //This sends undefined
})
});
async function returnData() {
const uri = "mongodb+srv://" + "username" + ":" + "password" + "#" + "connection url" + "/?retryWrites=true&w=majority";
//Connect to the database and return all documents in the collection
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
});
try {
await client.connect();
const database = client.db('testDB');
const collection = database.collection('testCollection');
const query = {};
const options = {};
const cursor = collection.find(query, options);
await cursor.toArray().then((docs) => {
console.log(docs); // <- This works and logs all the data to console
return docs;
});
} catch (e) {
console.error(e);
} finally {
await client.close();
}
}
EDIT:
I tried this and it returns undefined.
try {
await client.connect();
const database = client.db('testDB');
const collection = database.collection('testCollection');
const query = {};
const options = {};
const cursor = collection.find(query, options);
await cursor.toArray().then((docs) => {
return cursor.toArray();
});
} catch (e) {
console.error(e);
} finally {
await client.close();
}
I tried this and I get [MongoPoolClosedError]: Attempted to check out a connection from closed connection pool
try {
await client.connect();
const database = client.db('testDB');
const collection = database.collection('testCollection');
const query = {};
const options = {};
const cursor = collection.find(query, options);
return cursor.toArray();
} catch (e) {
console.error(e);
} finally {
await client.close();
}
Don't open and close the mongo client on each GET. Connect once and export that connection to your other modules. In terms of the Express request/response. You hand it off something like below.
app.get('/getData', myAsyncFunction)
async function index (req, res) {
let r = await db.collection("testDB").find(query).toArray();
return res.send(r);
}

Why can't I get the error VersionError: No matching document found for id

I want to intentionally generate the VersionError: No matching document found for id .... error in mongoose.
Based on what I read in this question here: Mongoose - Version Error: No matching document found for id
it seems like Mongoose will try to protect against duplicate save() because it has some kind of version control.
To try to intentionally generate this error, I wrote this script:
// file: app.js
const dotenv = require('dotenv');
dotenv.config();
const mongoose = require('mongoose');
const opts = {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: true,
authSource: 'admin',
};
const schema = mongoose.Schema({
serialNumber: { type: String },
customId: { type: String },
});
const Cms = mongoose.model('Cms', schema);
const run = async () => {
try {
await mongoose.connect(process.env.MONGODB_URL, opts);
const cms1 = await Cms.findOne({});
const cms2 = await Cms.findOne({});
const randomString = new Date().toString();
cms1.serialNumber = `${randomString}AA`;
cms1.customId = `${randomString}AA`;
await cms1.save();
cms2.serialNumber = `${randomString}BB`;
await cms2.save();
} catch (e) {
console.log('err', new Date(), e.toString());
}
/* eslint-disable no-process-exit */
process.exit();
};
run();
I made sure I had exactly 1 record in my cms collection. Then I ran node app.js. I did not get any errors and I see the cms record in my mongo was updated.
I updated my run() to use a setTimeout() like this:
const run = async () => {
try {
await mongoose.connect(process.env.MONGODB_URL, opts);
const cms = await Cms.findOne();
let randomString = new Date().toString();
setTimeout(async () => {
randomString = new Date().toString();
cms.serialNumber = `${randomString}BB`;
// cms.customId = `${randomString}BB`;
await cms.save();
/* eslint-disable no-process-exit */
process.exit();
}, 2000);
cms.serialNumber = `${randomString}AA`;
cms.customId = `${randomString}AA`;
await cms.save();
} catch (e) {
console.log('err', new Date(), e.toString());
}
};
The node app.js ran successfully again and mongoose also saved the record inside the setTimeout.
How do I intentionally generate the VersionError: No matching document found for .... error? What am I missing?

Connecting to mongodb in nodejs

I am first to use MongoClient to connect mongodb in nodejs, in each js file I use it like following
'use strict'
//part 1
const { MongoClient } = require('mongodb');
const dbconfig = require('../config/index');
const Mongodb = {
client: new MongoClient(dbconfig.product.dbUrl, {
useNewUrlParser: true,
useUnifiedTopology: true,
}),
oper: null,
db: null,
dbName: '',
};
const dbConnect = async (dbName = dbconfig.product.dbName) => {
if (Mongodb.oper) {
if (dbName !== Mongodb.dbName) {
Mongodb.db = Mongodb.client.db(dbName);
Mongodb.dbName = dbName;
}
return Mongodb.db;
}
Mongodb.oper = await Mongodb.client.connect();
return await dbConnect(dbName);
};
//part 2
const db = await dbConnect();
let info = await db.collection.find({});
//more code
The situation is that there is a lot of duplicate code, such as part 1, and I want to put part 1 into a file and import it where needed. I have no idea how to do, give me some ideas please, thank you.
You only need to connect to db once. My advice would be - google and try mongoose. I find it easier. Google some examples and read the docs.
Create a JS module that exports the connect function using module.exports then require it where necessary, something like this:
// mongo.js
const { MongoClient } = require('mongodb');
const dbconfig = require('../config/index');
const client = new MongoClient(dbconfig.product.dbUrl, {
useNewUrlParser: true,
useUnifiedTopology: true
});
let databasePromise;
async function _connect() {
try {
await client.connect();
} catch (e) {
console.error(e);
await closeConnection();
throw e;
}
return client.db();
}
function connect() {
if (!databasePromise) {
databasePromise = _connect();
}
return databasePromise;
}
async function close() {
await client.close();
databasePromise = undefined;
}
isConnected() {
return client.isConnected();
}
module.exports = {
connect,
close,
isConnected,
}
// index.js
const { connect } = require('./mongo');
(async () => {
const db = await connect();
const results = await db.collection('collection1').find({});
console.log(results);
})();
// file2.js
const { connect } = require('./mongo');
(async () => {
const db = await connect();
const results = await db.collection('collection2').find({});
console.log(results);
})();
Note, this code is not tested so it might need adjustments.

Delete a MongoDB document in Express JS

I'm staggered by how much I'm struggling to delete a document in MongoDB from Express JS. I'm finding the mix of documentation and methods including deleteOne, findByIdAndRemove, some tutorials say you need to declare an ObjectId, and some don't. Madness.
Anyway, below is my code. I have a function to connect to the database:
const withDB = async (operations, res) => {
try {
const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
const db = client.db('database-name');
await operations(db);
client.close();
} catch (error) {
res.status(500).json({ message: 'Error connecting to db', error });
}
}
And then the below is my delete command:
app.delete('/api/reports/delete-report/:id', async (req, res) => {
//call withDB function above
withDB(async (db) => {
//delete command
const result = await db.collection('reports').deleteOne( { _id : new MongoClient.ObjectId(req.params.id) } );
//get reports
const reportInfo = await db.collection('reports').find().toArray()
//put returned reports into the result provided
res.status(200).json(reportInfo);
}, res);
});
For my troubles I get the message 'Error connecting to db'. If I make the delete command:
const result = await db.collection('reports').deleteOne( { _id : req.params.id } );
I just get the contents of the database returned, but there's no deletion.
The issue is:
new MongoClient.ObjectId(req.params.id)
You don't want to create another mongoclient. It needs to be
new ObjectId(req.params.id)
and make sure you import that class:
const { MongoClient, ObjectId } = require('mongodb');

Resources