Can't insert JSON file into MongoDB's collection throught Node driver - node.js

I'm trying to read files from my disk and push it into MongoDB's collections, but connection closing before it done and I get error: MongoError: Topology is closed, please connect.
async function launch() {
try {
await mongo.connect();
console.log("Connection established");
const database = mongo.db('task');
const firstCol = database.collection('first');
const secondCol = database.collection('second');
const insertIntoCollection = async (file, col) => {
fs.readFile(file, async function(err, data) {
if (err) throw err;
const json = JSON.parse(data);
const result = await col.insertMany(json);
console.log(result.insertCount);
});
}
await insertIntoCollection('data/first.json', firstCol);
await insertIntoCollection('data/second.json', secondCol);
} finally {
await mongo.close();
}
}
launch().catch(console.dir);
What am I doing wrong?

In the above case mongo client will close before the insertIntoCollection function trigger since it is a promise function and promise will not over before the finally trigger.I hope below code will fulfil your expectations.
async function launch() {
try {
await mongo.connect();
console.log("Connection established");
const database = mongo.db('task');
const firstCol = database.collection('first');
const secondCol = database.collection('second');
const insertIntoCollection = async (file, col) => {
return new Promise((resolve, reject) => {
fs.readFile(file, async (err, data) => {
try {
if (err) reject(err);
const json = JSON.parse(data);
const result = await col.insertMany(json);
console.log(result.insertCount);
resolve(result.insertCount)
} catch (err) {
reject(err)
}
});
})
}
await insertIntoCollection('data/first.json', firstCol);
await insertIntoCollection('data/second.json', secondCol);
} finally {
await mongo.close();
}
}
launch().catch(console.dir);

Related

Async await in typescript not working as expected

I wrote a method in typescript which is supposed to return collection list name of mongo db.
public async getTables(): Promise<String[]> {
let collectionNames = [];
const connection = await mongoose.connect("mongodb://localhost/test");
await mongoose.connection.on('open', async function () {
mongoose.connection.db.listCollections().toArray(function (err, tables) {
console.log(tables);
tables.forEach(element => {
collectionNames.push(element["name"]);
});
console.log(collectionNames);
mongoose.connection.close();
});
});
return collectionNames;
}
Problem is instead of awaiting it returns directly empty collection list name.What is the issue here.
Because you use "await" in here,
const connection = await mongoose.connect("mongodb://localhost/test");
So, you miss "open" event that mongoose connection emit.
You can remove "await" for your program run as you expected
public async getTables(): Promise<String[]> {
let collectionNames = [];
const connection = mongoose.connect("mongodb://localhost/test");
await mongoose.connection.on('open', async function () {
mongoose.connection.db.listCollections().toArray(function (err, tables) {
console.log(tables);
tables.forEach(element => {
collectionNames.push(element["name"]);
});
console.log(collectionNames);
mongoose.connection.close();
});
});
return collectionNames;
}
Or you can write as below
public getTables(): Promise<String[]> {
return new Promise(async (resolve, reject) => {
try {
let collectionNames = [];
const connection = await mongoose.connect("mongodb://localhost/test");
mongoose.connection.db.listCollections().toArray(function (err, tables) {
console.log(tables);
tables.forEach(element => {
collectionNames.push(element["name"]);
});
console.log(collectionNames);
mongoose.connection.close();
resolve(collectionNames);
});
} catch (e) {
reject(e);
}
})
}

mongodb method without function not working in nodejs

I don't know much Javascript and was making a nodejs app. My mongodb query in nodejs is working only when the query has a function method like .toArray
Here's the database.js file
const {MongoClient} = require('mongodb');
const uri = "mongodb+srv://name:pass#clusterurl/metro4?retryWrites=true&w=majority";
// all fields are correctly filled
const client = new MongoClient(uri);
try {
// Connect to the MongoDB cluster
client.connect(err =>{
if(err) throw err;
let db = client.db('metro4');
db.collection('Station').find().toArray(function(err, result){
if(err) throw err;
console.log(result);
});
let a = db.collection('Station').findOne({'_id':4});
if(a) {
console.log(a);
}
else{
console.log("No a\n");
}
module.exports = db;
});
} catch (e) {
console.error(e);
} finally {
client.close();
}
when I run the app, the db.collection('Station').find().toArray runs fine and output the result but the second query of findOne doesn't work.
Any help is appreciated.
The findOne method returns a Promise. You should handle its result in a callback function:
db.collection('Station').findOne({ _id: 4 }, function (err, a) {
if (err) {
console.log(err);
} else if (a) {
console.log(a);
} else {
console.log('No a\n');
}
});
Or using async - await:
client.connect(async (err) => {
...
let a = await db.collection('Station').findOne({ _id: 4 })
...
});
EDIT
To handle the import - export problem you should handle the datase connection operations separate async functions.
You may use the connection function to return the database instance:
const {MongoClient} = require('mongodb');
const uri = "mongodb+srv://name:pass#clusterurl/metro4?retryWrites=true&w=majority";
// all fields are correctly filled
const client = new MongoClient(uri);
const connectDB = async () => {
try {
// Connect to the MongoDB cluster
await client.connect();
return client.db('metro4');
} catch (e) {
throw e;
}
}
const disconnectDB = () => {
client.close();
}
module.exports = { connectDB, disconnectDB };
Then use these functions to handle your database related operations:
const { connectDB, disconnectDB } = require('../database');
const getStations = async () => {
const db = connectDB();
if (!db) return;
try {
const data = await db.collection('Station').find().toArray();
return data;
} catch (err) {
throw err;
} finally {
disconnectDB();
}
}
const getStation = async (id) => {
const db = connectDB();
if (!db) return;
try {
const data = await db.collection('Station').findOne({ _id: id});
return data;
} catch (err) {
throw err;
} finally {
disconnectDB();
}
}

MongoExpiredSessionError: Cannot use a session that has ended

I got the error when I trying to connect node to the database. I used the async function and try to apply the methods in other similar questions but still got it wrong. Here is my code:
const { MongoClient } = require('mongodb')
const url = "mongodb://localhost:27017"
const client = new MongoClient(url);
async function main(){
const dbName = 'my-react-admin'
try {
await client.connect();
console.log('Connect to database!')
const db = client.db(dbName);
db.collection('users').find({}).toArray((err, data) => {
if (err) throw err
console.log(data)
})
} catch (e) {
console.error(e);
} finally {
await client.close();
}
}
main().catch(console.error);
Thank you!
I found the answer, you just have to put client.close(); to
((err, data) => { if (err) throw err console.log(data) })
just like ((err, data) => {client.close();}).
it'll work.

Await Promise.all async does't work in my code

I have a lambda function with the structure below,
It used to work in older versions of nodejs but it doesn't work with the newer versions.
I know my code structure is quite messy and wrong but I can't get my head around it. I'm trying to use Promise.all but I'm obviously doing something wrong cause it's not getting executed at all.
By the way, I'm not getting any errors. The promise.all method never gets executed.
let AWS = require('aws-sdk');
exports.handler = async(event, context, callback) => {
let result = {};
try {
result = await getOrder(sql, 0);
result.map(
(dataField) => {
});
}
catch (error) {
console.log(error);
callback(error);
}
var today_result = [];
const groupKey = i => i.user_id + '_' + i.when;
const counts = _.countBy(followingsIDs, groupKey);
const isMulti = i => counts[groupKey(i)] > 1;
const multiPropkey = i => ({ multiplekey: isMulti(i) ? groupKey(i) : groupKey(i) });
const multiProp = i => ({ multiple: isMulti(i) ? counts[groupKey(i)] : 1 });
const updated = _.map(followingsIDs, i => _.extend(i, multiProp(i), multiPropkey(i)));
const uniqResult = _.uniq(updated, function(d) { return d.multiplekey });
// Doesn’t execute from here —>
await Promise.all(uniqResult.map(async(dataField) => {
console.log("test_");
dosomething()
if (true) {
let sql = `INSERT INTO ….`
result = await getOrder(sql, 0);
try {
const data = await sns.publish(params).promise();
}
catch (e) {
console.log(e.stack);
response.result = 'Error';
}
}
}));
// Till here <----
callback(null, uniqResult);
};
let getOrder = async(sql, params) => {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) throw err;
connection.query(sql, params, (err, results) => {
if (err) {
reject(err);
}
// console.log("-----Query Done!");
connection.release();
// console.log("-----Data: ", results);
resolve(results);
});
});
});
};
What are you awaiting to? The uniqResult is just declared as an empty array. Immediately after that you pass it to Promise.all. You need to fill it with Promises and then pass it to Promise.all.

Node.js MS SQL transaction

Can anyone help to implement MS SQL transactions in Node.js . I am try to execute multiple stored procedures inside a promise.
Method 1
const executeProcedure = async (data1, data2) => {
try {
// sql connection
let dbConn = new sql.ConnectionPool(config));
await dbConn.connect();
let transaction = new sql.Transaction(dbConn);
await transaction.begin().then(async()=> {
// tranaciton create
// begin tran
let result = await insertOperation(transaction, data1);
let result2 = await updateOperation(transaction, data2);
let result1 = await Promise.all([result, result2]);
await transaction.commit();
dbConn.close();
}).catch(async(err)=> {
await transaction.rollback();
dbConn.close();
throw err;
});
return {};
}
catch (error) {
throw(error);
}
}
method 2
const insertOperation = async (transaction,data1) => {
return new Promise((resolve, reject) => {
try {
var request = new sql.Request(transaction);
request.input('data1' , sql.NVarChar(40) , data1)
.execute('dbo.insertOperation').then((recordSet) => {
resolve(recordSet.recordsets);
}).catch((err) => {
reject(err);
});
}
catch (error) {
reject(error);
}
});
}
method 3
const updateOperation = async (transaction,data2) => {
return new Promise((resolve, reject) => {
try {
var request = new sql.Request(transaction);
request.input('data2' , sql.NVarChar(40) , data2)
.execute('dbo.updateOperation').then((recordSet) => {
resolve(recordSet.recordsets);
}).catch((err) => {
reject(err);
});
}
catch (error) {
reject(error);
}
});
}
Now I get this error
Can't rollback transaction. There is a request in progress.
anybody please help me to solve this problem
You make some unnecessary Promise wrapper.
Example below:
const insertOperation = async (request, data1) => {
request.input("data1", sql.NVarChar(40), data1);
const result = await request.execute("dbo.insertOperation");
return result.recordsets;
};
const updateOperation = async (request, data2) => {
request.input("data2", sql.NVarChar(40), data2);
const result = await request.execute("dbo.updateOperation");
return result.recordsets;
};
const executeProcedure = async (data1, data2) => {
// sql connection
const dbConn = new sql.ConnectionPool(config);
await dbConn.connect();
let transaction;
try {
transaction = new sql.Transaction(dbConn);
await transaction.begin();
const request = new sql.Request(transaction);
const results = await Promise.all([
insertOperation(request, data1),
updateOperation(request, data2),
]);
await transaction.commit();
return results;
} catch (err) {
await transaction.rollback();
throw err;
} finally {
await dbConn.close();
}
};
#ikhvjs please check the below use case as well
try {
request.input("data", sql.NVarChar(40), data1);
const result = await request.execute("dbo.insertOperation");
return result.recordsets;
} catch (err) {
throw err;
}
};
const updateOperation = async (request, data2) => {
try {
request.input("data", sql.NVarChar(40), data2);
const result = await request.execute("dbo.updateOperation");
return result.recordsets;
} catch (err) {
throw err;
}
};
const executeProcedure = async (data1, data2) => {
try {
// sql connection
const dbConn = new sql.ConnectionPool(config);
await dbConn.connect();
const transaction = new sql.Transaction(dbConn);
try {
await transaction.begin();
const request = new sql.Request(transaction);
const results = await Promise.all([
insertOperation(request, data1),
updateOperation(request, data2),
]);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
} finally {
await dbConn.close();
}
} catch (error) {
throw error;
}
};```

Resources