npm install mongoose
const mongoose = require('mongoose');
const imageSchema = new mongoose.Schema({
name: {
type: String,
required: [true,
'Image name is required'],
trim: true,
maxlength: [200,
'Name cannot exceed 200 characters'],
},
width: {
type: Number,
required: true,
min: [1, 'Width must be at least 1'],
},
height: {
type: Number,
required: true,
min: [1, 'Height must be at least 1'],
},
format: {
type: String,
enum: ['png', 'jpeg', 'webp', 'gif'],
default: 'png',
},
filters: [{
name: String,
value: Number,
}],
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // Reference to User model
},
tags: [String],
fileSize: Number,
}, {
timestamps: true,
// Adds createdAt and updatedAt automatically
});
const Image = mongoose.model(
'Image', imageSchema
);
app.post('/api/images', async (req, res) => {
try {
const image = await Image.create(req.body);
res.status(201).json(image);
} catch (error) {
if (error.name === 'ValidationError') {
res.status(400)
.json({ error: error.message });
} else {
res.status(500)
.json({ error: 'Server error' });
}
}
});
| Input | Expected |
|---|---|
| No name field | 400: "Image name is required" |
| width: "banana" | 400: Cast to Number failed |
| format: "bmp" | 400: not a valid enum value |
| width: 0 | 400: "Width must be at least 1" |
| All valid data | 201: Document created |
const userSchema = new mongoose.Schema({
name: {
type: String, required: true
},
email: {
type: String, required: true,
unique: true, lowercase: true
},
password: {
type: String, required: true,
minlength: 8
},
}, { timestamps: true });
git switch -c feature/PIXELCRAFT-046-mongoose
git add server/models/ server/routes/
git commit -m "Add Mongoose schemas with validation (PIXELCRAFT-046)"
git push origin feature/PIXELCRAFT-046-mongoose
# PR → Review → Merge → Close ticket ✅
Data modeling is one of the most impactful architectural decisions.
How you structure data determines what queries are fast, what's impossible, and what breaks at scale.