use mongodb in express
Validating environment variables
Forgetting to set one of your environment variables might cause your application to malfunction. To prevent it, we can verify them. use envalid npm package
pnpm i envalid body-parser @types/body-parser
// src/utils/validateEnv.ts
import {
cleanEnv, str, port,
} from 'envalid';
function validateEnv() {
cleanEnv(process.env, {
MONGO_PASSWORD: str(),
MONGO_PATH: str(),
MONGO_USER: str(),
PORT: port(),
});
}
// src/server.ts
import 'dotenv/config';
import App from './app';
import validateEnv from './utils/validateEnv';
import PostsController from './controller/posts/post.controller';
validateEnv();
const app = new App(
[
// new PostsController(),
],
);
app.listen();
// src/app.ts
import * as bodyParser from 'body-parser';
import express from 'express';
import * as mongoose from 'mongoose';
import Controller from './interfaces/controller.interface';
class App {
public app: express.Application;
constructor(controllers: Controller[]) {
this.app = express();
this.connectToTheDatabase();
this.initializeMiddlewares();
this.initializeControllers(controllers);
}
public listen() {
this.app.listen(process.env.PORT, () => {
console.log(`App listening on the port ${process.env.PORT}`);
});
}
private initializeMiddlewares() {
this.app.use(bodyParser.json());
}
private initializeControllers(controllers: Controller[]) {
controllers.forEach((controller) => {
this.app.use('/', controller.router);
});
}
private connectToTheDatabase() {
const {
MONGO_USER,
MONGO_PASSWORD,
MONGO_PATH,
} = process.env;
mongoose.connect(`mongodb://${MONGO_USER}:${MONGO_PASSWORD}${MONGO_PATH}`);
}
}
export default App;
Model
// src/models/posts/post.interface.ts
export interface Post {
author: string;
content: string;
title: string;
}
// src/models/posts/post.model.ts
import * as mongoose from 'mongoose';
import {Post} from './post.interface';
const postSchema = new mongoose.Schema<Post>({
author: String,
content: String,
title: String,
});
const postModel = mongoose.model<Post & mongoose.Document>('Post', postSchema);
export default postModel;
Saving a document
// src/service/posts/post.service.ts
import express from "express";
import { Post } from "../../models/posts/post.interface";
import postModel from "../../models/posts/post.model";
export async function createPost(request: express.Request, response: express.Response) {
const postData: Post = request.body;
const createdPost = new postModel(postData);
const savedPost = await createdPost.save();
response.send(savedPost);
}
Retrieving all documents
// src/service/posts/post.service.ts
...
export async function getAllPosts(request: express.Request, response: express.Response) {
const posts = await postModel.find();
response.send(posts);
}
The ability to call the then method on the Query can be a bit misleading, but remember that postModel.find() does not return the promise itself. Please note that the find method does not cause the query to be executed, it happens after you call the then function. You can also do it by calling the exec function that returns a promise.
postModel.find().exec()
Retrieve a certain document
// src/service/posts/post.service.ts
...
export async function getPostById(
request: express.Request,
response: express.Response
) {
const id = request.params.id;
const post = await postModel.findById(id).exec();
response.send(post);
}
Replacing a document
// src/service/posts/post.service.ts
...
export async function modifyPost(request: express.Request, response: express.Response) {
const id = request.params.id;
const postData: Post = request.body;
const post = await postModel.findByIdAndUpdate(id, postData, { new: true }).exec();
response.send(post);
}
Removing a document
// src/service/posts/post.service.ts
...
export async function deletePost(request: express.Request, response: express.Response) {
const id = request.params.id;
const post = await postModel.findByIdAndDelete(id).exec();
if (post) {
response.send(200);
} else {
response.send(404);
}
}
The controller
// src/controller/posts/post.controller.ts
import * as express from 'express';
import Controller from '../../interfaces/controller.interface';
import * as postService from '../../service/posts/post.service';
class PostsController implements Controller {
public path = '/posts';
public router = express.Router();
private postService = postService;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(this.path, this.getAllPosts);
this.router.get(`${this.path}/:id`, this.getPostById);
this.router.patch(`${this.path}/:id`, this.modifyPost);
this.router.delete(`${this.path}/:id`, this.deletePost);
this.router.post(this.path, this.createPost);
}
private getAllPosts = (request: express.Request, response: express.Response) => {
this.postService.getAllPosts(request, response);
}
private getPostById = (request: express.Request, response: express.Response) => {
this.postService.getPostById(request, response);
}
private modifyPost = (request: express.Request, response: express.Response) => {
this.postService.modifyPost(request, response)
}
private createPost = (request: express.Request, response: express.Response) => {
this.postService.createPost(request, response);
}
private deletePost = (request: express.Request, response: express.Response) => {
this.postService.deletePost(request, response);
}
}
export default PostsController;
Summary
this is a simple demo for CRUD with express and mongodb. you can test it in postman. and view mongodb with mongo compass.