NextJS + MongoDB setup

Prerequisites: Set-up NextJS si Set-up Cloud Storage MongoDB

1. Initializarea conexiunii NextJS - MongoDB

Pentru ca scopul nostru este configurarea si utilizarea tehnologiilor cloud, nu invatarea unor noi limbaje de programare, majoritatea codului "boilerplate" si functiilor utile vor fi puse la dispozitie de mine si le puteti folosi in proiecte.

1.1. Adaugarea fisierului .env

In fisierul .env vom stoca date secrete (cum ar fi connection string-ul pentru BD), care nu ne dorim sa fie versionate cu git (stocate in cod) si sa ajunga publice.

  • Accesati proiectul NextJS

  • Modificati fisierul .gitignore. Adaugati pe ultima linie: .env

  • In root-ul proiectului, creati fisierul .env

# .env
NODE_ENV=development

NEXT_ATLAS_URI=mongodb+srv://<user>:<password>@cluster0.8qqv1kp.mongodb.net/?retryWrites=true&w=majority
NEXT_ATLAS_DATABASE=<your_database_name>
  • Copiati continutul de mai sus si inlocuiti userul, parola si numele bazei de date create (ATENTIE: Numele bazei de date !== Numele colectiei create). Save

2.2 Configurarea conexiunii la BD

  • In terminal, in folderul proiectului curent, rulati npm i mongodb

  • Creati in root-ul proiectului un folder cu denumirea lib

  • In folderul lib, creati fisierul mongodb.js

  • Copy and paste the following

// lib/mongodb.js
import { MongoClient, } from 'mongodb';

const uri = process.env.NEXT_ATLAS_URI;
const options = {
	useUnifiedTopology: true,
	useNewUrlParser: true,
};

let mongoClient = null;
let database = null;

if (!process.env.NEXT_ATLAS_URI) {
	throw new Error('Please add your Mongo URI to .env.local');
}

export async function connectToDatabase() {
	try {
		if (mongoClient && database) {
			return { mongoClient, database, };
		}
		if (process.env.NODE_ENV === 'development') {
			if (!global._mongoClient) {
				mongoClient = await (new MongoClient(uri, options)).connect();
				global._mongoClient = mongoClient;
			} else {
				mongoClient = global._mongoClient;
			}
		} else {
			mongoClient = await (new MongoClient(uri, options)).connect();
		}
		database = await mongoClient.db(process.env.NEXT_ATLAS_DATABASE);
		return { mongoClient, database, };
	} catch (e) {
		console.error(e);
	}
}
  • In root-ul proiectului, creati folderul js

  • In folderul js, creati folderul utils

  • In folderul utils, creati fisierul functions.js

  • Copy and paste the following

// js/utils/functions.js
import {connectToDatabase,} from '@/lib/mongodb.js';

export const getCollection = async collectionName => {
	const {database,} = await connectToDatabase();
	return database.collection(collectionName);
};

2.3 Configurarea API-ului NextJS

  • Tot in folderul utils, creati fisierul apiMethods.js

// js/utils/apiMethods.js
export const sendOk = (res, data) => {
	res.status(200).json(
		{
			'data': data,
		}
	);
};

export const sendNotFound = (res, message) => {
	res.status(404).json(
		{
			'error': message,
		}
	);
};

export const sendBadRequest = (res, message) => {
	res.status(400).json(
		{
			'error': message,
		}
	);
};

export const sendUnauthorized = (res, message) => {
	res.status(401).json(
		{
			'error': message,
		}
	);
};

export const sendMethodNotAllowed = res => {
	res.status(405).json(
		{
			'error': 'Method not allowed',
		}
	);
};
  • Pana acum, structura de fisiere din proiect ar trebui sa arate astfel

  • In folderul pages/api creati fisierul records.js. Acesta va reprezenta ruta /api/records si va asigura conexiunea si accesul backend - baza de date

// pages/api/records.js
import {sendMethodNotAllowed, sendOk,} from '@/js/utils/apiMethods.js';
import {getCollection} from "@/js/utils/functions";
import {ObjectId,} from 'mongodb';
const COLLECTION_NAME = 'records';

const getRecords = async () => {
	const collection = await getCollection(COLLECTION_NAME);
	return collection.find({}).toArray();
}

const getRecord = async (id) => {
	const collection = await getCollection(COLLECTION_NAME);
	return collection.findOne({_id: new ObjectId(id)});
}

const postRecord = async (record) => {
	const collection = await getCollection(COLLECTION_NAME);
	return collection.insertOne(record);
}

const putRecord = async (record) => {
	const collection = await getCollection(COLLECTION_NAME);
	const id = record._id;
	delete record._id;
	return collection.updateOne({_id: new ObjectId(id)}, {$set: record});
}

const deleteRecord = async (id) => {
	const collection = await getCollection(COLLECTION_NAME);
	return collection.deleteOne({_id: new ObjectId(id)});
}

export default async function handler(req, res) {

	const isAllowedMethod = req.method === 'GET' || req.method === 'POST' || req.method === 'PUT' || req.method === 'DELETE';
	if(!isAllowedMethod) {
		return sendMethodNotAllowed(res);
	}

	if(req.method === 'GET' && req.query.id) {
		const id = req.query.id;
		const record = await getRecord(id);
		return sendOk(res, record);
	}
	else if(req.method === 'GET') {
		const records = await getRecords();
		return sendOk(res, records);
	}
	else if(req.method === 'POST') {
		const record = req.body;
		const result = await postRecord(record);
		return sendOk(res, result);
	}
	else if(req.method === 'PUT') {
		const record = req.body;
		const result = await putRecord(record);
		return sendOk(res, result);
	}
	else if(req.method === 'DELETE') {
		const id = req.query.id;
		const result = await deleteRecord(id);
		return sendOk(res, result);
	}
}

Last updated