Skip to content

Commit

Permalink
Update to use the latest MongoDB best practices to limit connection p…
Browse files Browse the repository at this point in the history
…ooling issues. (#28350)

* Update to use the latest MongoDB best practices.

* lint-fix

Co-authored-by: Lee Robinson <me@leerob.io>
Co-authored-by: jj@jjsweb.site <jj@jjsweb.site>
  • Loading branch information
3 people committed Aug 25, 2021
1 parent 877f982 commit 220fa9c
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 47 deletions.
3 changes: 1 addition & 2 deletions examples/with-mongodb/.env.local.example
@@ -1,2 +1 @@
MONGODB_URI=
MONGODB_DB=
MONGODB_URI=
5 changes: 2 additions & 3 deletions examples/with-mongodb/README.md
Expand Up @@ -11,7 +11,7 @@ If you want to learn more about MongoDB, visit the following pages:

Once you have access to the environment variables you'll need, deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-mongodb&project-name=with-mongodb&repository-name=with-mongodb&env=MONGODB_URI,MONGODB_DB&envDescription=Required%20to%20connect%20the%20app%20with%20MongoDB)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-mongodb&project-name=with-mongodb&repository-name=with-mongodb&env=MONGODB_URI&envDescription=Required%20to%20connect%20the%20app%20with%20MongoDB)

## How to use

Expand Down Expand Up @@ -40,7 +40,6 @@ cp .env.local.example .env.local
Set each variable on `.env.local`:

- `MONGODB_URI` - Your MongoDB connection string. If you are using [MongoDB Atlas](https://mongodb.com/atlas) you can find this by clicking the "Connect" button for your cluster.
- `MONGODB_DB` - The name of the MongoDB database you want to use.

### Run Next.js in development mode

Expand All @@ -56,7 +55,7 @@ yarn dev

Your app should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions).

You will either see a message stating "You are connected to MongoDB" or "You are NOT connected to MongoDB". Ensure that you have provided the correct `MONGODB_URI` and `MONGODB_DB` environment variables.
You will either see a message stating "You are connected to MongoDB" or "You are NOT connected to MongoDB". Ensure that you have provided the correct `MONGODB_URI` environment variable.

When you are successfully connected, you can refer to the [MongoDB Node.js Driver docs](https://mongodb.github.io/node-mongodb-native/3.4/tutorials/collections/) for further instructions on how to query your database.

Expand Down
63 changes: 23 additions & 40 deletions examples/with-mongodb/lib/mongodb.js
@@ -1,49 +1,32 @@
import { MongoClient } from 'mongodb'

const MONGODB_URI = process.env.MONGODB_URI
const MONGODB_DB = process.env.MONGODB_DB

if (!MONGODB_URI) {
throw new Error(
'Please define the MONGODB_URI environment variable inside .env.local'
)
}

if (!MONGODB_DB) {
throw new Error(
'Please define the MONGODB_DB environment variable inside .env.local'
)
const uri = process.env.MONGODB_URI
const options = {
useUnifiedTopology: true,
useNewUrlParser: true,
}

/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections growing exponentially
* during API Route usage.
*/
let cached = global.mongo
let client
let clientPromise

if (!cached) {
cached = global.mongo = { conn: null, promise: null }
if (!process.env.MONGODB_URI) {
throw new Error('Please add your Mongo URI to .env.local')
}

export async function connectToDatabase() {
if (cached.conn) {
return cached.conn
if (process.env.NODE_ENV === 'development') {
// In development mode, use a global variable so that the value
// is preserved across module reloads caused by HMR (Hot Module Replacement).
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options)
global._mongoClientPromise = client.connect()
}

if (!cached.promise) {
const opts = {
useNewUrlParser: true,
useUnifiedTopology: true,
}

cached.promise = MongoClient.connect(MONGODB_URI, opts).then((client) => {
return {
client,
db: client.db(MONGODB_DB),
}
})
}
cached.conn = await cached.promise
return cached.conn
clientPromise = global._mongoClientPromise
} else {
// In production mode, it's best to not use a global variable.
client = new MongoClient(uri, options)
clientPromise = client.connect()
}

// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default clientPromise
10 changes: 8 additions & 2 deletions examples/with-mongodb/pages/index.js
@@ -1,5 +1,5 @@
import Head from 'next/head'
import { connectToDatabase } from '../lib/mongodb'
import clientPromise from '../lib/mongodb'

export default function Home({ isConnected }) {
return (
Expand Down Expand Up @@ -223,7 +223,13 @@ export default function Home({ isConnected }) {
}

export async function getServerSideProps(context) {
const { client } = await connectToDatabase()
const client = await clientPromise

// client.db() will be the default database passed in the MONGODB_URI
// You can change the database by calling the client.db() function and specifying a database like:
// const db = client.db("myDatabase");
// Then you can execute queries against your database like so:
// db.find({}) or any of the MongoDB Node Driver commands

const isConnected = await client.isConnected()

Expand Down

0 comments on commit 220fa9c

Please sign in to comment.