Using Node driver v5 - when is MongoClient.connect() required?

I have some confusion. I’ve succesfully implemented a few CRUD applications that connect to DBs hosted on Mongo Atlas. Every time, I do this:

const client  = new MongoClient(<connectionString>);
const db = client.db(<dbName>)

And then I’m off to the races with queries on db.

For the first time, I’ve considered it crucial to carry out queries within a transaction. So I know I’m dealing with sessions now, and upon some research, to deal with a session I’m supposed to use client.connect().

I’m confused because I’ve never used the connect() method - but according to MongoDB documentation I shouldn’t even be able to interact with my database without establishing connection.

So what gives? It really seems like the MongoClient constructor is automatically establishing connection to me - but I can’t find any documentation to back that up.

Tangentially (but also to the actual need I have), if I’m connecting to a db fine with client.db(), does that mean that I’m also likely to succeed with client.startSession().

Thanks for any help.

Edit to add:
And further - I’m never closing a connection (I’m never opening one in the first place that I can tell…) - would it be any different when working with a session? I know I have to end the session.

1 Like

The MongoClient constructor creates a client instance, but it doesn’t actually connect to the database. It is recommended to call .connect() method to explicitly connect to the database. The .db() method, however, will automatically connect to the database if there is no established connection, so in most cases, you do not need to call .connect() method.

For transactions, it is required to use sessions, and the MongoClient.startSession() method is used to start a new session. It is recommended to end the session by calling .endSession() method after the transaction is completed.

In general, it’s a good practice to explicitly manage the connections and sessions in your application, to ensure the correct connection pooling and release resources when they are no longer needed.

Thank you for your reply.

Typically, should a connection be established for each query and then closed upon completion of the query?

1 Like

Hi @Michael_Jay2

The node driver automatically calls connect() since version 4.7 (see NODE-4192). This is also mentioned in the code example in the Connection Guide documentation page:

// Connect the client to the server (optional starting in v4.7)
await client.connect();

However:

This is not correct. This code:

async function main() {
  const client = new MongoClient('mongodb://localhost:27017?replicaSet=replset', {useUnifiedTopology: true});

  const db = client.db('test')
  console.log(db)

  const session = client.startSession();
  console.log(session)
}
main().then(() => console.log('done'))

will print the relevant db and session objects to the console, but if you check the mongod logs, there are no connection accepted.

Once you do some operation by e.g. doing an insertOne() using the session, then you should see a line similar to this in the mongod log:

{“t”:{“$date”:“2023-02-07T10:06:46.318+11:00”},“s”:“I”, “c”:“NETWORK”, “id”:22943, “ctx”:“listener”,“msg”:“Connection accepted”,“attr”:{“remote”:“127.0.0.1:53615”,“uuid”:“7f90e2a3-9a79-491e-a72b-e7ef0e857ed8”,“connectionId”:50,“connectionCount”:4}}

which means that only when an operation is involved, the connection is made.

Regarding your follow-up question:

You should create the client object using MongoClient() once for the lifetime of the app, and call client.close() only during teardown of the app. During the lifetime of the app, you can put the client object in a global variable so it’s accessible to the whole app.

This is because all official MongoDB drivers manages a connection pool via the client object, and will automatically reuse, add, or remove individual connections as needed. Connecting/disconnecting after every operation is an anti-pattern and should be avoided.

Best regards
Kevin

3 Likes

Thank for taking me to school, Kevin.

By what I’m reading in your repsonse, it is also not necessary (or important) to actively call client.connect() because if a session is started and a query is executed in that session, then the connection is auto-established. Right?

Hi @Michael_Jay2

Yes you are correct. Since connect() is optional, it will be auto-called whenever an operation needed to be done in the database, like inserting a document (with or without a session).

With regard to calling client.close(), I would say that it’s best practice to call this when you’re doing teardown in the app. This is to ensure that all resources are cleaned up in both the app side and the database side.

For a small experiment, you can try this type of code similar to the one I posted earlier:

async function main() {
  const client = new MongoClient('mongodb://localhost:27017?replicaSet=replset', {useUnifiedTopology: true});

  const session = client.startSession();

  await session.withTransaction(async () => {
    const coll = client.db('test').collection('foo')
    await coll.insertOne({ abc: 1 }, { session })
  })
  await session.endSession()  // try removing this
  await client.close()        // or this
}
main().then(() => console.log('done'))

If you remove client.close(), I believe you’ll find that the script will just wait indefinitely when you run it, requiring you to CTRL-C to exit it. If you leave the client.close() there, the script will exit after it’s done. I tend to think that since the intent is for the script to exit, calling client.close() there is a better scenario.

Hope this helps!

Best regards
Kevin

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.