MongoDB Academy · Lektion

Anforderungsanalyse und Schemaentwurf

Lernende übertragen Anwendungsanforderungen in ein MongoDB-Schema, entscheiden zwischen Einbettung und Referenzierung und wenden geeignete Design-Patterns an.

Lektion 1 von 413 Schritte

Anforderungsanalyse und Schemaentwurf ist eine kostenlose MongoDB Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des MongoDB Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.

Das Abschlussprojekt: Entwurf einer echten Anwendung

In dieser Abschlusslektion wenden Sie Ihr gesamtes Wissen aus dem MongoDB-Kurs an, um eine produktionsreife Anwendung von Grund auf zu entwerfen. Wir erstellen eine Multi-Vendor-E-Commerce-Plattform – eine Domäne, die umfangreich genug ist, um Entscheidungen zwischen Einbetten und Referenzieren, die Indexplanung, den Entwurf von Aggregationen und Sicherheitsaspekte zu behandeln. Der Prozess beginnt mit der Anforderungsanalyse, die alle nachfolgenden Schemaentscheidungen bestimmt.

Schritt 1: Funktionale Anforderungen erfassen

Beginnen Sie damit, die zentralen Entitäten und Vorgänge der Anwendung aufzulisten. Für unsere E-Commerce-Plattform sind dies: Entitäten – Users, Vendors, Products, Orders, Reviews, Carts; Vorgänge – Produkte nach Kategorie durchsuchen, nach Schlüsselwörtern suchen, Bestellungen aufgeben, Zahlungen verarbeiten, Lieferungen verfolgen und Bewertungen verfassen. Jeder Vorgang entspricht einer oder mehreren MongoDB-Abfragen, und diese Abfragen bestimmen die Schemaentscheidungen.

// Requirement analysis output (pseudocode spec)
const requirements = {
  reads: [
    'Get product by slug (very high frequency)',
    'List products by category + sort/filter (high frequency)',
    'Search products by keyword (high frequency)',
    'Get order history for a user (medium frequency)',
    'Get order detail (medium frequency)'
  ],
  writes: [
    'Create order (medium frequency)',
    'Update order status (medium frequency)',
    'Add product review (low frequency)',
    'Update product inventory (high frequency)'
  ]
}

Schritt 2: Zugriffsmuster identifizieren

Zugriffsmuster sind die konkreten Abfragen, die Ihre Anwendung ausführen wird. Dokumentieren Sie sie vor dem Entwurf des Schemas präzise – das Schema sollte den Abfragen dienen, nicht umgekehrt. Erfassen Sie für jedes Muster: die Filterfelder, Sortierfelder, projizierten Felder und die geschätzte Häufigkeit. Häufig verwendete Muster bestimmen die Indexierungs- und Einbettungsentscheidungen. Bei selten verwendeten Mustern kann der zusätzliche Aufwand durch Joins oder eine Aggregationspipeline akzeptabel sein.

// Access pattern register
const accessPatterns = [
  {
    name: 'Product page',
    filter: { slug: 1 },
    projection: 'all except internal fields',
    frequency: 'very high',
    decision: 'index on slug; embed top 5 reviews'
  },
  {
    name: 'Category listing',
    filter: { categoryId: 1, price: 1 },
    sort: { price: 1, createdAt: -1 },
    frequency: 'high',
    decision: 'compound index { categoryId, price, createdAt }'
  }
]

Die Products-Collection entwerfen

Das Produktdokument wird im System am häufigsten gelesen. Wenden Sie die gelernten Muster an: Computed Pattern für vorab berechnete Statistiken (avgRating, reviewCount); Subset Pattern, um nur die fünf besten Bewertungen einzubetten; Extended Reference, um den Namen und das Logo des Anbieters neben vendorId einzubetten. Dadurch entfallen bei 95 % der Darstellungen von Produktseiten Joins.

// Product document schema (simplified)
{
  _id: ObjectId(),
  slug: 'wireless-headphones-pro',
  name: 'Wireless Headphones Pro',
  categoryId: ObjectId(),
  vendor: {
    _id: ObjectId(),         // reference for updates
    name: 'AudioTech Ltd',   // Extended Reference
    logoUrl: '...'           // Extended Reference
  },
  price: 149.99,
  stock: 234,
  avgRating: 4.3,           // Computed Pattern
  reviewCount: 892,          // Computed Pattern
  topReviews: [ /* 5 most recent */ ],  // Subset Pattern
  tags: ['audio', 'wireless', 'headphones'],
  schema_version: 1
}

Die Orders-Collection entwerfen

Bestellungen sind ein klassischer Fall für ein Snapshot-Dokument: Sie halten den Stand von Preisen und Adressen zum Zeitpunkt des Kaufs fest, nicht den aktuellen Stand. Betten Sie die vollständige Lieferadresse ein (keine Referenz auf die aktuelle Adresse des Benutzers), ebenso den Produktschnappschuss (Name, Preis und Bild zum Kaufzeitpunkt) sowie den Namen des Anbieters. So bleiben Bestellungen korrekt, auch wenn sich Preise ändern oder Anbieter ihre Profile aktualisieren.

// Order document schema
{
  _id: ObjectId(),
  userId: ObjectId(),
  status: 'processing',  // 'pending', 'processing', 'shipped', 'delivered', 'refunded'
  createdAt: new Date(),
  shippingAddress: {
    name: 'Alice Smith',
    street: '42 Elm St',
    city: 'Istanbul',
    country: 'TR'
  },
  items: [
    {
      productId: ObjectId(),     // reference for linking
      slug: 'wireless-...',
      name: 'Wireless Headphones Pro',  // snapshot
      price: 149.99,             // price at purchase time
      quantity: 1,
      imageUrl: '...'
    }
  ],
  subtotal: 149.99,
  tax: 27.00,
  total: 176.99
}

Das Entscheidungsframework für den Schemaentwurf anwenden

Wenden Sie für jede Beziehung die Entscheidungs-Checkliste an: Wie oft wird sie gemeinsam abgerufen? (Immer: einbetten, selten: referenzieren); Wie oft ändern sich die referenzierten Daten? (Selten: einbetten, häufig: referenzieren); Wird das eingebettete Array unbeschränkt wachsen? (Ja: referenzieren, begrenzt: einbetten); Wird nach den Daten unabhängig abgefragt? (Ja: separate Collection, immer über das übergeordnete Dokument abgerufen: einbetten).

// Decision table for our e-commerce schema
const decisions = [
  { entity: 'Order items',       decision: 'embed',     reason: 'always fetched with order; price snapshot required' },
  { entity: 'Shipping address',  decision: 'embed',     reason: 'snapshot at purchase time; changes do not affect order' },
  { entity: 'Product reviews',   decision: 'separate + subset', reason: 'grows unbounded; top-5 subset in product doc' },
  { entity: 'Vendor details',    decision: 'extended ref', reason: 'name/logo read on every product page; changes rarely' },
  { entity: 'Category tree',     decision: 'separate',  reason: 'queried independently; used for breadcrumbs' }
]

Schema-Validierung für kritische Collections

Fügen Sie den Collections products und orders JSON-Schema-Validatoren hinzu, um zu verhindern, dass fehlerhaft formatierte Dokumente Ihre Daten beschädigen. Erzwingen Sie Pflichtfelder (price muss eine positive Zahl sein, status muss einem der gültigen Enum-Werte entsprechen) und setzen Sie validationAction: 'error', damit ungültige Schreibvorgänge sofort abgelehnt werden, statt nur eine Warnung auszugeben.

db.runCommand({
  collMod: 'orders',
  validator: {
    $jsonSchema: {
      bsonType: 'object',
      required: ['userId', 'status', 'items', 'total', 'createdAt'],
      properties: {
        status: {
          bsonType: 'string',
          enum: ['pending', 'processing', 'shipped', 'delivered', 'refunded']
        },
        total: { bsonType: 'double', minimum: 0 },
        items: { bsonType: 'array', minItems: 1 }
      }
    }
  },
  validationAction: 'error'
})

Die Indexmenge planen

Definieren Sie für jedes häufig verwendete Zugriffsmuster Indizes. Verwenden Sie für zusammengesetzte Indizes die ESR-Regel (Equality → Sort → Range). Erstellen Sie Indizes nur für häufig ausgeführte Abfragen – ungenutzte Indizes beeinträchtigen die Schreibperformance und verbrauchen RAM. Dokumentieren Sie den Zweck jedes Index, damit das Team redundante Indizes entfernen kann, wenn sich die Zugriffsmuster weiterentwickeln.

// Products collection indexes
db.products.createIndex({ slug: 1 }, { unique: true })  // product page lookup
db.products.createIndex({ categoryId: 1, price: 1, _id: 1 })  // category listing + keyset pagination
db.products.createIndex({ tags: 1 })  // tag filter
db.products.createIndex({ 'vendor._id': 1 })  // vendor store page

// Orders collection indexes
db.orders.createIndex({ userId: 1, createdAt: -1 })  // user order history
db.orders.createIndex({ status: 1, createdAt: 1 })   // fulfillment queue

Gleichzeitige Bestandsaktualisierungen verarbeiten

Eine zentrale Herausforderung im E-Commerce ist das Verhindern von Überverkäufen: Zwei Benutzer dürfen nicht beide den letzten verfügbaren Artikel kaufen können. Verwenden Sie MongoDBs atomare Methode findOneAndUpdate mit der Prüfbedingung stock: { $gt: 0 }. Die Aktualisierung ist nur erfolgreich, wenn Bestand verfügbar ist, und die Verringerung erfolgt atomar – eine Race Condition ist somit ausgeschlossen.

// Atomically reserve stock — returns null if out of stock
const product = await db.collection('products').findOneAndUpdate(
  { _id: productId, stock: { $gte: quantity } },  // guard: enough stock
  { $inc: { stock: -quantity } },
  { returnDocument: 'after', projection: { stock: 1, name: 1, price: 1 } }
)

if (!product) {
  throw new Error('Insufficient stock')
}
// Proceed to create order with product snapshot

Aggregationspipeline für Berichte

Entwerfen Sie eine Aggregationspipeline für eine Verkaufsübersicht, die den Umsatz pro Anbieter für die letzten 30 Tage ausgibt. Dies ist ein klassischer Fall, in dem die Aggregationspipeline eine komplexe Berechnung auf Anwendungsseite ersetzt. Die Pipeline filtert aktuelle Bestellungen, entpackt die Artikel, gruppiert nach Anbieter und sortiert nach dem Gesamtumsatz.

// Revenue by vendor, last 30 days
const since = new Date(Date.now() - 30 * 86400000)

db.orders.aggregate([
  { $match: { status: 'delivered', createdAt: { $gte: since } } },
  { $unwind: '$items' },
  {
    $group: {
      _id: '$items.vendorId',
      totalRevenue: { $sum: { $multiply: ['$items.price', '$items.quantity'] } },
      orderCount: { $addToSet: '$_id' }
    }
  },
  { $addFields: { orderCount: { $size: '$orderCount' } } },
  { $sort: { totalRevenue: -1 } },
  { $limit: 20 }
])

Das Schema mit explain() testen

Validieren Sie vor dem Übergang in die Produktion jede kritische Abfrage mit explain('executionStats'). Stellen Sie sicher, dass alle häufig verwendeten Abfragen im gewinnenden Plan IXSCAN (nicht COLLSCAN) anzeigen, dass docsExamined nahe an nReturned liegt und dass totalKeysExamined angemessen ist. Jede Abfrage mit COLLSCAN oder einem hohen Verhältnis von docsExamined zu nReturned benötigt einen Index.

// Validate the category listing query
const stats = db.products.find(
  { categoryId: ObjectId('...'), price: { $lte: 200 } }
).sort({ price: 1 }).explain('executionStats')

const plan = stats.executionStats
console.log('Stage:', plan.executionStages.inputStage.stage)  // should be IXSCAN
console.log('Keys examined:', plan.totalKeysExamined)          // should be small
console.log('Docs examined:', plan.totalDocsExamined)          // should equal nReturned
console.log('Docs returned:', plan.nReturned)

Schnelltest

Testen Sie Ihr Verständnis der Konzepte aus dieser Lektion zu MongoDB & NoSQL Databases.

Lektionsrückblick

In dieser Lektion haben Sie gelernt: Anforderungsanalyse und die Dokumentation von Zugriffsmustern kommen vor dem Schemaentwurf – das Schema dient den Abfragen, nicht umgekehrt; ein gutes Produktdokument kombiniert Extended Reference, Computed Pattern und Subset Pattern, um Joins im häufig genutzten Lesepfad zu vermeiden; und atomare Aufrufe von findOneAndUpdate mit Prüfbedingungen verhindern Überverkäufe, ohne Transaktionen zu benötigen. Als Nächstes definieren wir die Indexstrategie und validieren jeden Index mit explain().

Kostenlos starten

Lerne JavaScript mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
30
Lektionen
120

Häufig gestellte Fragen

Ist die Lektion „Anforderungsanalyse und Schemaentwurf“ kostenlos?

Ja — der vollständige Text von „Anforderungsanalyse und Schemaentwurf“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des MongoDB Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Anforderungsanalyse und Schemaentwurf“?

Lernende übertragen Anwendungsanforderungen in ein MongoDB-Schema, entscheiden zwischen Einbettung und Referenzierung und wenden geeignete Design-Patterns an. Du übst MongoDB Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um MongoDB Academy zu starten?

Keine Vorkenntnisse erforderlich. MongoDB Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Anforderungsanalyse und Schemaentwurf“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser MongoDB Academy-Lektion Code schreiben und ausführen?

Ja. Jede MongoDB Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Anforderungsanalyse und Schemaentwurf
  2. Indexstrategie und Validierung des Abfrageplaners
  3. Skalierungsplan: Vom Replikatsatz zum Sharded Cluster
  4. Sicherheits-Härtung und Checkliste für den Produktivbetrieb
← Zurück zu MongoDB Academy