The problem and sheet management system has been refactored to eliminate redundancy by implementing a proper many-to-many relationship between problems and sheets.
- Each problem had a
sheetIdfield - Same problem in multiple sheets = multiple duplicate documents
- Updating a problem in one sheet didn't update it in others
- Wasteful database storage
- Problems exist independently without sheet references
- SheetProblem junction table manages the many-to-many relationship
- Same problem can belong to multiple sheets without duplication
- Single source of truth for each problem
-
server/models/problem.model.js- Removed
sheetIdandorderfields - Added
unique: truetotitlefield - Problems now exist independently
- Removed
-
server/models/sheetProblem.model.js✨ NEW- Junction table for many-to-many relationship
- Fields:
sheetId,problemId,order - Unique compound index on
(sheetId, problemId)
-
server/controllers/problem.controller.jscreateProblem()- Creates independent problemsaddProblemToSheet()- Adds existing problem to a sheetremoveProblemFromSheet()- Removes from sheet (doesn't delete problem)deleteProblem()- Deletes problem from all sheetsmarkProblemComplete()- Now requires bothproblemIdandsheetId
-
server/controllers/problemSheet.controller.js- Updated
deleteProblemSheet()- Deletes SheetProblem relations - Updated
getSheetProblems()- Uses aggregation with SheetProblem junction - Updated
getSheetMetrics()- Works with new architecture
- Updated
server/middleware/validateProblem.js- Removed
ordervalidation (now in SheetProblem)
- Removed
-
server/scripts/seedBlind75.js✨ NEW- Complete Blind 75 problem set (all 75 problems)
- Creates problems independently
- Links them to sheet via SheetProblem
-
server/scripts/migrateProblemArchitecture.js✨ NEW- Migrates existing data from old to new architecture
- Includes rollback functionality
cd server
node scripts/migrateProblemArchitecture.jsThis will:
- Find all problems with
sheetId - Create SheetProblem relationships
- Remove
sheetIdandorderfrom problems
Rollback (if needed):
node scripts/migrateProblemArchitecture.js --rollbackcd server
node scripts/seedBlind75.jsThis creates all 75 Blind 75 problems and the sheet.
Clear Blind 75:
node scripts/seedBlind75.js -dOld Way:
POST /api/sheets/:sheetId/problems
Body: { title, difficulty, platform, platformLink, order, ... }New Way:
// Step 1: Create problem independently
POST /api/problems
Body: { title, difficulty, platform, platformLink, ... }
// Step 2: Add to sheet(s)
POST /api/sheets/:sheetId/problems/:problemId
Body: { order: 1 } // optionalOld Way:
PUT /api/problems/:problemId/completeNew Way:
PUT /api/sheets/:sheetId/problems/:problemId/complete
Body: { completed: true }// New endpoint - removes problem from sheet WITHOUT deleting it
DELETE /api/sheets/:sheetId/problems/:problemId✅ No Duplication - Each problem stored once
✅ Consistency - Updates propagate to all sheets
✅ Flexibility - Easy to add/remove problems from sheets
✅ Better Data Integrity - Single source of truth
✅ Storage Efficiency - Reduced database size
✅ Maintainability - Easier to manage problems
{
_id: ObjectId,
title: String (unique),
description: String,
difficulty: 'easy' | 'medium' | 'hard',
platform: String,
platformLink: String,
tags: [String],
hints: [{hintNumber, content}],
solution: {content: {python, javascript, ...}, explanation},
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
sheetId: ObjectId (ref: ProblemSheet),
problemId: ObjectId (ref: Problem),
order: Number,
notes: String, // Optional sheet-specific notes
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
name: String (unique),
slug: String,
description: String,
icon: String,
totalProblems: Number,
isActive: Boolean,
createdAt: Date,
updatedAt: Date
}The seed script includes all 75 problems categorized as:
- Array (10 problems)
- Binary (5 problems)
- Dynamic Programming (11 problems)
- Graph (8 problems)
- Interval (6 problems)
- Linked List (6 problems)
- Matrix (4 problems)
- String (9 problems)
- Tree (13 problems)
- Heap (2 problems)
All problems include:
- Title, difficulty, platform, platform link
- Tags for categorization
- Detailed description
- Run Migration - Convert existing data
- Seed Blind 75 - Import the complete problem set
- Update Frontend - Adjust API calls if needed
- Test Thoroughly - Verify all CRUD operations work
For questions or issues, refer to the migration and seed scripts.