Node.js

ORM / Mongoose – Sequelize, Prisma & Mongoose

Model your data with an ORM or ODM: define Sequelize models and associations, write Prisma schemas and typed queries, and build Mongoose schemas with full CRUD operations.

Sequelize Model: Define a model with DataTypes and let Sequelize generate SQL DDL. Use sync({ alter: true }) in dev to auto-migrate.
📄src/models/User.js (Sequelize)
JS
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');

const User = sequelize.define('User', {
  id: {
    type:          DataTypes.INTEGER,
    primaryKey:    true,
    autoIncrement: true,
  },
  name: {
    type:      DataTypes.STRING(100),
    allowNull: false,
  },
  email: {
    type:      DataTypes.STRING,
    allowNull: false,
    unique:    true,
    validate:  { isEmail: true },
  },
  password: {
    type:      DataTypes.STRING,
    allowNull: false,
  },
  role: {
    type:         DataTypes.ENUM('user', 'admin'),
    defaultValue: 'user',
  },
}, {
  tableName:  'users',
  timestamps: true,          // adds createdAt, updatedAt
  paranoid:   true,          // adds deletedAt (soft delete)
});

module.exports = User;
Sequelize Associations: Define hasMany / belongsTo in an index.js that imports all models, so associations run once on startup.
📄src/models/index.js
JS
const User    = require('./User');
const Post    = require('./Post');
const Comment = require('./Comment');

// User ──< Post
User.hasMany(Post,    { foreignKey: 'userId', as: 'posts' });
Post.belongsTo(User,  { foreignKey: 'userId', as: 'author' });

// Post ──< Comment
Post.hasMany(Comment,   { foreignKey: 'postId', as: 'comments' });
Comment.belongsTo(Post, { foreignKey: 'postId' });

// User ──< Comment
User.hasMany(Comment,    { foreignKey: 'userId' });
Comment.belongsTo(User,  { foreignKey: 'userId', as: 'commenter' });

module.exports = { User, Post, Comment };
Prisma Schema: Define models in schema.prisma. Run npx prisma migrate dev to apply migrations and npx prisma generate to regenerate the client.
📄prisma/schema.prisma
PRISMA
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model User {
  id        Int      @id @default(autoincrement())
  name      String
  email     String   @unique
  password  String
  role      Role     @default(USER)
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  body      String   @db.Text
  published Boolean  @default(false)
  author    User     @relation(fields: [userId], references: [id])
  userId    Int
  createdAt DateTime @default(now())
}

enum Role {
  USER
  ADMIN
}
Prisma Queries: The generated client provides fully-typed, auto-completed methods. Use include to eager-load relations.
📄src/services/postService.js (Prisma)
JS
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();

// Find all published posts with author
const getPublishedPosts = () =>
  prisma.post.findMany({
    where:   { published: true },
    include: { author: { select: { id: true, name: true } } },
    orderBy: { createdAt: 'desc' },
  });

// Create a post
const createPost = (userId, data) =>
  prisma.post.create({
    data: { ...data, userId },
  });

// Update
const publishPost = (id) =>
  prisma.post.update({
    where: { id },
    data:  { published: true },
  });

// Soft-delete (Prisma doesn't have built-in; use a flag)
const deletePost = (id) =>
  prisma.post.delete({ where: { id } });

module.exports = { getPublishedPosts, createPost, publishPost, deletePost };
Mongoose Schema: Define schema shape, add virtual fields, pre-save hooks, and export the compiled Model.
📄src/models/User.js (Mongoose)
JS
const mongoose = require('mongoose');
const bcrypt   = require('bcryptjs');

const userSchema = new mongoose.Schema({
  name:     { type: String, required: true, trim: true },
  email:    { type: String, required: true, unique: true, lowercase: true },
  password: { type: String, required: true, minlength: 6 },
  role:     { type: String, enum: ['user', 'admin'], default: 'user' },
  avatar:   { type: String, default: null },
}, {
  timestamps: true,   // adds createdAt, updatedAt
});

// Pre-save hook: hash password
userSchema.pre('save', async function (next) {
  if (!this.isModified('password')) return next();
  this.password = await bcrypt.hash(this.password, 12);
  next();
});

// Instance method: compare password
userSchema.methods.comparePassword = function (plain) {
  return bcrypt.compare(plain, this.password);
};

// Virtual: full profile URL
userSchema.virtual('profileUrl').get(function () {
  return `/users/${this._id}`;
});

module.exports = mongoose.model('User', userSchema);
CRUD with Mongoose: Use .lean() for read-only queries to skip Mongoose document overhead, and { new: true } to return the updated document.
📄src/services/userService.js (Mongoose)
JS
const User = require('../models/User');

const getAll   = ()       => User.find().select('-password').lean();
const getById  = (id)     => User.findById(id).select('-password').lean();
const getByEmail = (email)=> User.findOne({ email }).lean();

const create   = (data)   => User.create(data);

const update   = (id, data) =>
  User.findByIdAndUpdate(id, data, { new: true, runValidators: true })
      .select('-password');

const remove   = (id)     => User.findByIdAndDelete(id);

// Paginated list
const paginate = async (page = 1, limit = 10) => {
  const skip  = (page - 1) * limit;
  const [data, total] = await Promise.all([
    User.find().skip(skip).limit(limit).select('-password').lean(),
    User.countDocuments(),
  ]);
  return { data, total, page, pages: Math.ceil(total / limit) };
};

module.exports = { getAll, getById, getByEmail, create, update, remove, paginate };