Wat is een Schema en Model?

💡 Analogie: Schema = inschrijfformulier

Je wilt leden toevoegen aan sportschool. Je maakt formulier met velden:

Naam: [verplicht, max 50 letters]
Leeftijd: [verplicht, getal, min 16]
Email: [verplicht, moet @ hebben]

Schema in MongoDB doet hetzelfde: welke velden + welke regels.
Model is het object waarmee je formulieren invult en ophaalt.

Waarom handig?

Zonder schema:

  • Workout zonder titel → geaccepteerd
  • "appel" bij reps → geaccepteerd
  • App crasht door foute data

Met schema:

  • Title vergeten → Error: "Title required"
  • "appel" bij reps → Error: "Must be number"
  • Data is altijd correct!

Workout Schema Maken

Schema voor workouts: titel, herhalingen (reps), gewicht (load).

Maak model bestand

Nieuw bestand in src/models/:

src/models/Workout.js

Model begint met hoofdletter!

Schrijf code:

// src/models/Workout.js
import mongoose from 'mongoose';

const Schema = mongoose.Schema;

// Schema = regels voor workout
const workoutSchema = new Schema({
  title: {
    type: String,
    required: true
  },
  reps: {
    type: Number,
    required: true
  },
  load: {
    type: Number,
    required: true
  }
}, {
  timestamps: true
});

// Model = object voor maken/ophalen/aanpassen/verwijderen
const Workout = mongoose.model('Workout', workoutSchema);

export default Workout;
Betekenis:
  • type: String - Moet tekst zijn
  • type: Number - Moet getal zijn
  • required: true - Moet ingevuld worden
  • timestamps: true - Voegt automatisch createdAt/updatedAt toe

Workout zonder titel?

Automatisch error:

Validation failed: title: Path `title` is required.

Mongoose checkt het voor je!

Dit is handig!

Zonder schema kan iedereen alles in database gooien. Met schema zeg je: alleen deze velden, met deze types.

Extra validatie (optioneel)

Extra regels toevoegen:

title: {
  type: String,
  required: true,
  trim: true,        // Verwijdert spaties
  maxlength: 100     // Max 100 tekens
},
reps: {
  type: Number,
  required: true,
  min: 1             // Min 1 (geen 0 of negatief)
}

Basis versie hierboven werkt prima!

Wat doet timestamps?

Mongoose voegt 2 velden toe:

  • createdAt - Wanneer aangemaakt?
  • updatedAt - Wanneer aangepast?

Voorbeeld:

{
  "_id": "...",
  "title": "Squats",
  "reps": 15,
  "load": 50,
  "createdAt": "2024-11-25T10:00:00.000Z",
  "updatedAt": "2024-11-27T14:30:00.000Z"
}

Model in Routes Gebruiken

Model is klaar, gebruik in routes om data op te slaan/ophalen.

Stap 1: Importeer model

Bovenaan src/routes/workoutRoutes.js:

import Workout from '../models/Workout.js';

Stap 2: Vervang dummy POST

Vervang door echte database code:

// POST nieuwe workout
router.post('/', async (req, res) => {
  const { title, load, reps } = req.body;

  try {
    const workout = await Workout.create({ title, reps, load });
    res.status(201).json(workout);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});
Regel voor regel:
  • async (req, res) - Kan wachten op database
  • const { title, load, reps } - Haal data uit POST
  • try { } - Probeer dit
  • await Workout.create() - Sla op en wacht
  • res.status(201) - Status 201 (Created)
  • catch (error) - Als fout, stuur error

Waarom async en await?

Database operaties zijn langzaam. Duurt even voordat MongoDB opslaat.

Probleem zonder await:

Code stuurt response VOORDAT workout is opgeslagen. Gebruiker denkt het is gelukt, maar staat er niet!

Zonder await (FOUT):

// NIET DOEN!
router.post('/', (req, res) => {
  const workout = Workout.create({ title, reps, load }); 
  res.json(workout); // TE SNEL!
  // workout is undefined hier!
});

Met await (GOED):

// WEL DOEN!
router.post('/', async (req, res) => {
  const workout = await Workout.create({ title, reps, load }); 
  res.json(workout); // Nu écht opgeslagen!
});

💡 Simpel gezegd:

await = "wacht tot klaar voordat verder"
async = "deze functie gebruikt await"

Waarom try/catch?

Wat als fout? Iemand vergeet veld of database is offline. Met try/catch vang je error op.

💡 Simpel gezegd:

try { } = "Probeer dit"
catch (error) { } = "Als fout, stuur error terug"

Zonder try/catch crasht server bij elke fout!

Testen met Postman

POST route slaat data op. Maar hoe testen?

Probleem:

In browser kun je alleen GET. Geen POST, PATCH of DELETE.

Postman is programma waarmee je ALLE requests test (GET, POST, PATCH, DELETE). Je kunt JSON data meesturen.

Postman installeren

  1. Ga naar postman.com/downloads
  2. Download en installeer
  3. Open Postman (klik "Skip and go to app")

POST Request Testen

Test of je workout kunt toevoegen.

Stap 1: Nieuwe request

  • Klik "New" of "+" voor nieuwe tab
  • Selecteer POST
  • URL: http://localhost:4000/api/workouts

Stap 2: Body instellen

  • Klik tab "Body"
  • Selecteer "raw"
  • Kies "JSON" uit dropdown

Stap 3: JSON data

{
  "title": "Squats",
  "reps": 10,
  "load": 50
}

Stap 4: Versturen

Klik "Send" en kijk naar antwoord.

Gelukt! Je ziet:

{
  "_id": "6543e8f2d1a2c3b4e5f67890",
  "title": "Squats",
  "reps": 10,
  "load": 50,
  "createdAt": "2024-11-22T12:30:00.000Z",
  "updatedAt": "2024-11-22T12:30:00.000Z",
  "__v": 0
}

Status: 201 Created

Foutmelding? Check:

  • Server draait? (npm run dev)
  • "Body" → "raw" → "JSON" geselecteerd?
  • Aanhalingstekens rond velden?
  • URL correct?

GET Request Testen

Check of workout écht is opgeslagen.

In Postman:

  • Nieuwe tab (klik "+")
  • Methode GET
  • URL: http://localhost:4000/api/workouts
  • Klik Send

Je ziet array met workouts:

[
  {
    "_id": "6543e8f2d1a2c3b4e5f67890",
    "title": "Squats",
    "reps": 10,
    "load": 50,
    "createdAt": "2024-11-22T12:30:00.000Z",
    "updatedAt": "2024-11-22T12:30:00.000Z"
  }
]

In MongoDB Atlas:

Bekijk data visueel:

  1. Ga naar MongoDB Atlas
  2. Klik "Database"
  3. Klik "Browse Collections"
  4. Zie workout-dbworkouts → je data!

💡 Postman tips:

  • Maak "Collection" voor al je requests
  • Geef requests namen (bijv. "Create Workout")
  • Zo hoef je niet steeds URLs in te typen!

Problemen oplossen

❌ "Validation failed: title required"

Probleem: Title niet meegestuurd

Check:

  • Postman Body tab - "raw" en "JSON"?
  • JSON heeft "title", "reps" en "load"?
  • Correcte body:
{
  "title": "Squats",
  "reps": 10,
  "load": 50
}

❌ "Cannot find module Workout.js"

Probleem: Routes vindt model niet

Check:

  • Bestaat src/models/Workout.js? (hoofdletter W!)
  • Onderaan Workout.js: export default Workout;?
  • Bovenaan routes: import Workout from '../models/Workout.js';?
  • Pad klopt? Van routes naar models is ../models/

❌ Status 500 Internal Server Error

Probleem: Fout in server code

Check:

  • Kijk in terminal waar npm run dev draait
  • Lees error message
  • Veelvoorkomende fouten:
    • Vergeten async?
    • Vergeten await voor Workout.create()?
    • Geen try/catch?

❌ Geen data in Postman na POST

Check:

  • Welke status? 201 = gelukt! 400/500 = lees error
  • Check MongoDB Atlas: Database → Browse Collections
  • GET request naar /api/workouts - zie je workout?

💡 Wat is __v veld?

Version number van Mongoose. Houdt bij hoeveel keer document is gewijzigd. Gewoon negeren!

Checklist

✅ Check of je hebt:

  • src/models/Workout.js aangemaakt (hoofdletter!)
  • Schema met title, reps, load
  • timestamps: true toegevoegd
  • Model geëxporteerd
  • Model geïmporteerd in workoutRoutes.js
  • POST route gebruikt Workout.create()
  • async en await gebruikt
  • Postman geïnstalleerd
  • POST request werkt (status 201)
  • GET toont nieuwe workout
  • Data zichtbaar in MongoDB Atlas

Samenvatting

Je hebt:

  1. Schema gemaakt (title, reps, load)
  2. Model gemaakt voor opslaan/ophalen
  3. POST route aangepast voor echte database
  4. Postman geïnstalleerd
  5. Eerste workout opgeslagen!

Volgende Stap

Model klaar en POST werkt! Nu maken we alle CREATE en READ routes compleet.

CREATE & READ Controllers →

Maak alle routes voor data ophalen en opslaan