Connection Mongodb with nodejs - node.js

I've tried to develop a server with nodejs that is link with NOSQL DB, in particular I've developped it with MONGODB. I'm not sure I manage to connect it well due to the fact if I run the code below it should return the id of the element inserted but it prints in output a blank, in the case I substitute the async with a normal development it return the following error "
MongoError: Topology is closed, please connect " .I've tried to use the lines of code with /the comment below the code/ but it returns another error.
I think I don't connect well mongodb with my server but I don't know I follow the commands deliver in mongodb step by step.(create a cluster(free),create a user,create a db and then a collection and then connect use the information set before.)
I said it because I refresh the cluster on mongodb but I don't obtain any change
const MongoClient = require('mongodb').MongoClient;
const password = encodeURIComponent('22');
const user=encodeURIComponent('id');
const dbs = encodeURIComponent('users');
const uri = "mongodb+srv://${user}:${password}#cluster/${dbs}?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true ,useUnifiedTopology:true, connectTimeoutMS: 30000 , keepAlive: 1});
(async()=>{
await client.connect();
const databse=client.db("users");
const collection=databse.collection("readers");
const result= await collection.insertOne( {
"name":"Chocolate",
"ingredients":[
"eggs","chocolates"
]
});
console.log(result.insertedId);
//client.close();
});
/*
client.connect(err => {
const collection2 = client.db("users").collection("readers");
// perform actions on the collection object
var myobj = { name: "Ajeet Kumar", age: "28", address: "Delhi" };
collection2.insertOne(myobj, function(err, res) {
if (err) throw err;
console.log("1 record inserted");
//client.close();
});
});
*/

I see a few problems with the code.
There is no reason for you to use encodeURIComponent with static strings. But hopefully, that's just a placeholder for some real credentials that are going to come from an environment variable.
The variable uri is being assigned with a static string that contains a templating pattern, but it is using double quotes instead of backticks, so it won't interpolate the variables, which in turn will generate an invalid connection string.
The same variable uri, after having replaced the double quotes " with the backticks ` might still not work because of the strange hostname "cluster" that should come from some sort of settings of env var as well.
The code seems to have the intent of using an Immediately Invoked Function Expression (IIFE for short) but it is in fact not even calling the function because the parenthesis pair is missing after the function block.
Assuming your credentials are correct the updated code below should do the trick for you:
const MongoClient = require('mongodb').MongoClient
const password = encodeURIComponent('22')
const user = encodeURIComponent('id')
const dbName = encodeURIComponent('users')
const host = process.env.MONGO_HOST || 'localhost' // or whatever is the hostname you want
const uri = `mongodb+srv://${user}:${password}#${host}/${dbName}?retryWrites=true&w=majority`
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, connectTimeoutMS: 30000, keepAlive: 1 })
;(async () => {
await client.connect()
const databse = client.db('users')
const collection = databse.collection('readers')
const doc = {
name: 'Chocolate',
ingredients: [
'eggs', 'chocolates'
]
}
const result = await collection.insertOne(doc)
console.log({ result })
console.log(result.insertedId)
client.close()
})()

Related

Document must be a valid JavaScript object in Nodejs

Simply trying to set a new field to the value of an existing field in the same document without iterating (can do iteration but aggregation pipeline seems more efficient)
The aggrgation expression comes from mongodb aggregation builder and it previews fine there.
Code
const { MongoClient } = require('mongodb');
const agg = [
{
'$match': {}
}, {
'$set': {
'old_price': '$price'
}
}, {}, {}];
const url= '...y';
const client = new MongoClient(url);
async function main() {
const client = await MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true });
const dbName = 'mongodbVSCodePlaygroundDB';
const collname='test';
const coll = client.db(dbName).collection(collname);
const rset = await coll.updateMany(agg);
console.log(rset);
await client.close();
}
main()
.then(console.log('ok'))
.catch(console.error)
.finally(() => client.close());
ERROR: MongoInvalidArgumentError: Document must be a valid JavaScript object
Occurs at this line:
const rset = await coll.updateMany(agg);
Any pointers on getting this to work?
Tried a number of variations with quotes and square braces

MongoNotConnectedError: MongoClient must be connected to perform this operation. How to handle this error?

cmd
How can i solve this. Just showing MongoClient must be connected to perform this operation
at getTopology ..... at collection.insertOne .... at maybePromise..
const express = require('express');
const {MongoClient} = require('mongodb');
const password = 'NLJXkuGFhUd68#9';
const uri = "mongodb+srv://organicUser:NLJXkuGFhUd68#9#cluster0.px7rc.mongodb.net/organicdb?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
const app = express();
app.get('/', (req, res) => {
res.send("Hello, I am Working");
})
client.connect(err => {
const collection = client.db("organicdb").collection("products");
// perform actions on the collection object
const product = {name: "Modhu", price: 120, quantity: 30};
collection.insertOne(product)
.then(result => {
console.log("One product added");
})
console.log("database connected");
});
app.listen(8000)
Just comment the code or remove client.close()
finally {
// await client.close();
}
I had the same issue and I have changed the method to be await and async, and I added await to the operation.
So the operation will be finished then the connection will be close
I needed to replace # with %40 in the database password
As I'm struggling with this, the author is referring to the idea that if your password contains certain characters, you must change them out for percent based codes: If the username or password includes the following characters:
: / ? # [ ] #
those characters must be converted using percent encoding.
https://www.mongodb.com/docs/manual/reference/connection-string/

How can I use the same mongodb connection throughout the app?

I'm trying this approach, but I'm not sure if that creates a new connection every time.
getMongoClient.js
const { MongoClient } = require('mongodb');
const serverURL = process.env['mongoServerURL']
module.exports = async function (){
const mongoClient = await new MongoClient(serverURL);
await mongoClient.connect();
return mongoClient;
}
then in the app.js
const getMongoClient = require("./_helpers/getMongoClient.js")
module.exports = getMongoClient();
then in a database service.js
async function syncGuilds(client){
const mongoClient = await require("../app.js")
... some database operations
}
module.exports = syncGuilds
Node modules are singleton by themselves, you don't need to worry about them. When your modules is once evaluated, it won't be evaluated again. So you will always receive same instance of the module i.e it won't create multiple instance of mongo connection.
You can check this and this link for more details.
It won't create a new connection every time, If you want you can specify max connection pool size in options default value is 5. Check below link
https://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html#connection-pool-configuration
const mongodb = require("mongodb");
let client = new mongodb.MongoClient(
"url",
{
tls: true,
auth: { user: "myuser", password: "mypassword" },
useNewUrlParser: true,
useUnifiedTopology: true,
poolSize: 1,
maxPoolSize: 1,
}
);

Best practice running queries in Node.js with MongoDB driver 3.6?

The official documentation of the Node.js Driver version 3.6 contains the following example for the .find() method:
const { MongoClient } = require("mongodb");
// Replace the uri string with your MongoDB deployment's connection string.
const uri = "mongodb+srv://<user>:<password>#<cluster-url>?w=majority";
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
const database = client.db("sample_mflix");
const collection = database.collection("movies");
// query for movies that have a runtime less than 15 minutes
const query = { runtime: { $lt: 15 } };
const options = {
// sort returned documents in ascending order by title (A->Z)
sort: { title: 1 },
// Include only the `title` and `imdb` fields in each returned document
projection: { _id: 0, title: 1, imdb: 1 },
};
const cursor = collection.find(query, options);
// print a message if no documents were found
if ((await cursor.count()) === 0) {
console.log("No documents found!");
}
await cursor.forEach(console.dir);
} finally {
await client.close();
}
}
To me this somewhat implies that I would have to create a new connection for each DB request I make.
Is this correct? If not, then what is the best practise to keep the connection alive for various routes?
You can use mongoose to set a connection with your database.
mongoose.connect('mongodb://localhost:27017/myapp', {useNewUrlParser: true});
then you need to define your models which you will use to communicate with your DB in your routes.
const MyModel = mongoose.model('Test', new Schema({ name: String }));
MyModel.findOne(function(error, result) { /* ... */ });
https://mongoosejs.com/docs/connections.html
It's 2022 and I stumbled upon your post because I've been running into the same issue. All the tutorials and guides I've found so far have setups that require reconnecting in order to do anything with the Database.
I found one solution from someone on github, that creates a class to create, save and check if a client connection exist. So, it only recreates a client connection if it doesn't already exist.
const MongoClient = require('mongodb').MongoClient
class MDB {
static async getClient() {
if (this.client) {
return this.client
}
this.client = await MongoClient.connect(this.url);
return this.client
}
}
MDB.url='<your_connection_url>'
app.get('/yourroute', async (req, res) => {
try {
const client = await MDB.getClient()
const db = client.db('your_db')
const collection = db.collection('your_collection');
const results = await collection.find({}).toArray();
res.json(results)
} catch (error) {
console.log('error:', error);
}
})

Node.js + Arangodb to make a connection and get a query

I am new to backend service. I have been trying to make a connection to arangodb from node server. I have a created a basic query in arangodb. the user auth in arangodb is so complicated and there are very few tutorials for node and arangadb combo. I have posted my code below. I have found this example online.
DataService.js
var arangojs = require('arangojs');
// Const variables for connecting to ArangoDB database
const host = '192.100.00.000'
const port = '8529'
const username = 'abcde'
const password = 'abcde'
const path = '/_db/_system/_api/'
const databasename = 'xyzm_app'
// Connection to ArangoDB
var db = new arangojs.Database({
url: `http://${host}:${port}${path}${databasename}`,
databaseName: databasename
});
db.useBasicAuth(username, password);
//console.log(db);
module.exports = {
getAllControllers : function(){
return db.query('For x IN {user_details} RETURN NEW {
id: x._user_details/7977010,
name: x.char_ctrl_username,
email:x.char_ctrl_email
}')
.then(cursor => {
return cursor.all()
});
}
query in db
From the arangojs README:
// Or using a fully qualified URL containing the database path
const db = new Database({
url: `http://${username}:${password}#${host}:${port}/_db/${database}`,
databaseName: false // don't automatically append database path to URL
});
databaseName: string (Default: _system)
Name of the active database.
If this option is explicitly set to false, the url is expected to contain the database path and the useDatabase method can not be used to switch databases.
So you either specify the full path like http://host:port/_db/dbname and set databaseName: false, or you use http://host:port and either specify databaseName: "dbname" or useDatabase("dbname").
/_api should not be part of the path, ever. arangojs knows where to find the API endpoint and does it for you.
var arangojs = require('arangojs');
// Const variables for connecting to ArangoDB database
const host = '127.0.0.1'
const port = '8529'
const username = 'xyz'
const password = 'xyz'
const databasename = 'sgcdm_app'
// Connection to ArangoDB
db = new arangojs.Database({
url: `http://${host}:${port}`,
databaseName: databasename
});
db.useBasicAuth(username, password);
db.listCollections().then(function(res) {
res.forEach((coll, i) => {
console.log(`${i+1}. ${coll.name} (ID=${coll.id}, system=${coll.isSystem})`)
});
}, function(err) {
const res = err.response.body;
console.log(`Error ${res.errorNum}: ${res.errorMessage} (HTTP ${res.code})`);
});
On success (database exists):
1. first (ID=264349479, system=false)
2. test (ID=264349463, system=false)
On error (unknown database):
Error 1228: database not found (HTTP 404)
cross-post from GitHub

Resources