Cache MongoDB connection khi làm việc với Next.js

Để kết nối với MongoDB, thông thường ta sẽ làm như sau:
const { MongoClient } = require('mongodb')
// Connection URIconst uri = 'mongodb://127.0.0.1:27017'
// Create a new MongoClientasync functionconnectDb() {
  try {
    const client = new MongoClient(uri)
    await client.connect()
    const db = client.db('database_name')
    console.log('Connected successfully to server')
    return db
  } catch (err) {
    console.error(err)
    throwError(err)
  }
}
Khi dùng Next.js, mình thường dùng Typescript, vì vậy nó có thể viết lại kiểu:
import { Db, MongoClient } from 'mongodb'

const MONGO_URI = 'mongodb://127.0.0.1:27017'

export async functionconnectDb(): Promise<Db> {
  const client: MongoClient = new MongoClient(MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  } as any)
  await client.connect()
  return client.db('database_name')
}
Sau đó, để sử dụng trong API Routes của Next.js ta import vào và dùng như bình thường:
import type { NextApiRequest, NextApiResponse } from 'next'
import { connectDb } from '../../lib/database'

export default async functionhandler(req: NextApiRequest, res: NextApiResponse) {
  try {
    awaitconnectDb()
    res.status(200).json({ message: 'Connection successful!' })
  }catch(err) {
    res.status(500).json({ name: 'Failedddddd' })
  }
}
Mở terminal, gõ yarn dev để start server:
notion image
notion image
Lúc này, MongoDB chưa kết nối (do chưa gọi API). Trong MongoDB, để kiểm tra thông tin về số lượng kết nối, ta dùng lệnh db.serverStatus().connections như sau:
notion image
Ta có thể thấy đang có 4 kết nối tới Database (không cần quan tâm). Giờ ta sẽ thử gọi api và kiểm tra lại số lượng kết nối:
notion image
notion image
Gọi đến API này liên tục, kiểm tra lượng kết nối trên MongoDB sẽ thấy current connections tăng lên liên tục, bằng với số lần gọi:
notion image
 
Tất nhiên là ta sẽ không muốn cứ có một request đến thì lại có một connection được mở ra. Để giải quyết việc này, ta sẽ lưu connection đến mongo vào global, sau đó kiểm tra xem nó đã tồn tại chưa, nếu chưa thì mới connect:
import { Db, MongoClient } from 'mongodb'

const MONGO_URI = 'mongodb://127.0.0.1:27017'

declare global {
  var mongo: any
}
let cached = global.mongo
if (!cached) {
  cached = global.mongo = { conn: null }
}

export async functionconnectDb(): Promise<Db> {
  if (cached.conn) return cached.conn
  const client: MongoClient = new MongoClient(MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  } as any)
  await client.connect()
  cached.conn = client.db('database_name')
  return cached.conn
}