Skip to content

Project Image Embeds

We previously stored project tags as embedded sub-documents. Let’s do the same for projectImages.

Each project can have zero, one, or multiple projectImages, so we need an array.

Neo-Retro isometric diagram showing a MongoDB Project Document containing an array of embedded Project Image Subdocuments, with physical image files stored on a local server hard drive.

Fig 1: Document Structure vs Physical Storage

In Mongoose, arrays of Objects are called Subdocuments. We can create a standalone schema specifically for the visual shape of this embedded data.

data/projects.js
const mongoose = require('mongoose');
// A sub-schema explicitly designed to shape items inside an array
const projectImageSchema = new mongoose.Schema(
{
originalName: String,
filename: String,
altText: String, // Optional descriptive text
caption: String, // Optional display string
isFeatured: { type: Boolean, default: false },
uploadedAt: { type: Date, default: Date.now },
},
{ _id: false } // Avoid MongoDB generating unique nested IDs inside this embedded array unless specifically needed!
);
const projectSchema = new mongoose.Schema({
// ... other fields
// Array of strictly shaped subdocuments!
projectImages: [projectImageSchema],
});
Professor Solo

Why use an embedded projectImageSchema instead of a separate referenced media collection? A project’s projectImages fundamentally exist to support that specific project. They operate in the context of the parent project. Furthermore, fetching a Project instantly gives you all its image metadata without expensive populate() joins.


Now that our data model is ready, let’s meet multer, the middleware responsible for actually catching these binary file uploads.