MongoDB Academy · Lektion

Outlier- und Tree-Structure-Patterns

Lernende verarbeiten Dokumente mit ungewöhnlich großen Arrays mithilfe des Outlier-Patterns und modellieren hierarchische Baumdaten mit Parent-Referenzen oder materialisierten Pfaden.

Lektion 4 von 413 Schritte

Outlier- und Tree-Structure-Patterns ist eine kostenlose MongoDB Academy-Lektion auf CoddyKit. Dies ist Lektion 4 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 Outlier-Problem

Die meisten MongoDB-Collections enthalten Dokumente, deren Größe einer vorhersehbaren Verteilung folgt. Gelegentlich gibt es jedoch Ausreißer – Dokumente, die stark vom Normalfall abweichen. Ein Beitrag in sozialen Medien, der viral geht, kann 50.000 Kommentare sammeln, während typische Beiträge 5–20 Kommentare haben. Ein bei einer prominenten Person beliebtes Produkt kann 10.000 Bewertungen erhalten. Wenn Sie Ihr Schema am Durchschnittsfall ausrichten und Ausreißer ignorieren, erreichen Dokumente irgendwann das Größenlimit von 16 MB oder verursachen Speicherengpässe.

Ausreißerdokumente erkennen

Bevor Sie Ihr Schema auf Ausreißer ausrichten, ermitteln Sie, ob diese in Ihren Daten tatsächlich vorkommen. Verwenden Sie eine Aggregationspipeline, um Dokumente mit ungewöhnlich großen Arrays zu finden. Legen Sie den Schwellenwert anhand Ihres erwarteten Normalbereichs fest: Wenn 99 % der Beiträge weniger als 100 Kommentare haben, sind Dokumente mit mehr als 1.000 Kommentaren Ausreißer, die eine besondere Behandlung verdienen.

// Find posts with outlier-level comment counts
db.posts.aggregate([
  {
    $project: {
      title: 1,
      commentCount: { $size: { $ifNull: ['$comments', []] } }
    }
  },
  { $match: { commentCount: { $gt: 1000 } } },
  { $sort: { commentCount: -1 } },
  { $limit: 10 }
])

Das Outlier Pattern: Overflow-Flag

Das Outlier Pattern hält den Normalfall schnell, indem Arrays bis zu einem Schwellenwert eingebettet werden. Außergewöhnliche Dokumente werden behandelt, indem ein hasOverflow-Flag gesetzt und die zusätzlichen Elemente in einer separaten Collection gespeichert werden. Der Anwendungscode prüft das Flag: Ist es false (der häufige Fall), verwendet er das eingebettete Array. Ist es true (der Ausreißerfall), führt er eine zusätzliche Abfrage an die Overflow-Collection aus.

// Normal post document (99% of posts)
{ _id: ObjectId(), title: 'Regular Post', comments: [/* up to 100 */], hasOverflow: false }

// Outlier post document
{
  _id: ObjectId(),
  title: 'Viral Post',
  comments: [/* first 100 comments */],
  hasOverflow: true  // more comments in overflow collection
}

// Overflow collection document
{ postId: ObjectId('...'), comments: [/* comments 101-5000 */] }

Lesen mit dem Outlier Pattern

Der Anwendungscode muss das Ausreißer-Flag explizit behandeln. Meistens ist das Flag false und Lesevorgänge sind schnell. Bei Ausreißerdokumenten führen Sie die zusätzliche Overflow-Abfrage aus. So bleibt der häufige Pfad optimiert, während außergewöhnliche Fälle korrekt behandelt werden, ohne normale Dokumente unnötig zu vergrößern oder das 16-MB-Limit zu erreichen.

async function getPostWithComments(postId) {
  const post = await db.collection('posts').findOne({ _id: postId })

  if (!post.hasOverflow) {
    return post  // fast path — all comments embedded
  }

  // Outlier path — fetch additional comments from overflow
  const overflow = await db.collection('postOverflow').findOne({ postId })
  return {
    ...post,
    comments: [...post.comments, ...(overflow?.comments ?? [])]
  }
}

Einführung in Tree-Structure-Patterns

Hierarchische Daten – Produktkategorien, Organisationsdiagramme, Dateisysteme und Kommentar-Threads – kommen in fast jeder Anwendung vor. MongoDB verfügt über keinen nativen Datentyp für Bäume, daher muss die Struktur im Dokumentschema modelliert werden. Es gibt vier gängige Tree-Patterns, die jeweils für unterschiedliche Abfragemuster optimiert sind: Parent References, Child References, Array of Ancestors und Materialised Paths.

Parent References: Einfache Hierarchie

Das Parent-Reference-Pattern speichert jeden Knoten mit einem einzelnen parent-Feld, das auf die _id des übergeordneten Knotens verweist. Wurzelknoten haben parent: null. Dies ist die einfachste Darstellung und entspricht der Funktionsweise von SQL-Bäumen mit Nested-Set- oder Adjazenzlisten-Modell. Sie ist effizient, um den direkten übergeordneten Knoten oder die direkten untergeordneten Knoten eines Knotens zu finden, erfordert für die Durchquerung mehrerer Ebenen jedoch rekursive Abfragen.

// Category tree with Parent References
db.categories.insertMany([
  { _id: 1, name: 'Electronics',   parent: null },
  { _id: 2, name: 'Phones',        parent: 1 },
  { _id: 3, name: 'Laptops',       parent: 1 },
  { _id: 4, name: 'Smartphones',   parent: 2 },
  { _id: 5, name: 'Feature Phones',parent: 2 }
])

// Find direct children of 'Electronics'
db.categories.find({ parent: 1 })

Array of Ancestors: Schnelles Finden von Vorgängern

Das Array-of-Ancestors-Pattern speichert den vollständigen Pfad von der Wurzel bis zum aktuellen Knoten in einem ancestors-Array. Dadurch lässt sich mit einer einfachen Prüfung der Array-Mitgliedschaft leicht feststellen, ob „X ein Vorgänger von Y ist“. Außerdem können Sie alle Nachfahren eines Knotens einfach finden, indem Sie nach Dokumenten suchen, deren ancestors-Array die _id dieses Knotens enthält. Der Nachteil besteht darin, dass beim Verschieben eines Teilbaums alle Dokumente der Nachfahren aktualisiert werden müssen.

// Array of Ancestors pattern
db.categories.insertMany([
  { _id: 1, name: 'Electronics',   ancestors: [] },
  { _id: 2, name: 'Phones',        ancestors: [1] },
  { _id: 4, name: 'Smartphones',   ancestors: [1, 2] }  // root→Electronics→Phones
])

// Find all descendants of Electronics (id=1)
db.categories.find({ ancestors: 1 })

// Check if Electronics is an ancestor of Smartphones
db.categories.findOne({ _id: 4, ancestors: 1 })  // not null = yes

Materialised Paths: Baum auf Zeichenfolgenbasis

Das Materialised-Path-Pattern speichert den vollständigen Pfad als Zeichenfolge (z. B. '/Electronics/Phones/Smartphones'). Es ermöglicht Präfixabfragen, um alle Knoten unterhalb eines Teilbaums zu finden, sowie reguläre Ausdrücke, um innerhalb von Pfadsegmenten zu suchen. Dieses Pattern eignet sich besonders für Dateisystempfade oder URL-Hierarchien. Es ist sowohl für die Suche nach Vorgängern als auch für das Auflisten von Nachfahren effizient, kann beim Umbenennen oder Verschieben von Knoten jedoch fehleranfällig sein.

// Materialised Path pattern
db.categories.insertMany([
  { _id: 1, name: 'Electronics', path: ',1,' },
  { _id: 2, name: 'Phones',      path: ',1,2,' },
  { _id: 4, name: 'Smartphones', path: ',1,2,4,' }
])

// Find all descendants of Phones (id=2) — path contains ',2,'
db.categories.find({ path: /,2,/ })

// Find the full path ancestors of Smartphones
db.categories.find({ _id: { $in: [1, 2] } })  // parse path and lookup ids

Das passende Tree-Pattern auswählen

Wählen Sie das Tree-Pattern anhand Ihrer häufigsten Abfrage: Parent References – einfach und gut für die Navigation mit Rekursion auf Anwendungsseite; Child References – bettet ein Array direkter Kinder ein und ist schnell beim Lesen einer Ebene; Array of Ancestors – schnell bei der Suche nach Vorgängern und bei Teilbaumabfragen, aber aufwendig beim Verschieben; Materialised Paths – schnell bei Teilbaumabfragen mit regulären Ausdrücken, aber fehleranfällig beim Umbenennen. Hybride Ansätze (Speichern von Parent und Ancestors) tauschen höhere Komplexität beim Schreiben gegen höhere Lesegeschwindigkeit.

Child References: Direkte Kinder einbetten

Das Child-References-Pattern bettet in jedes Knotendokument ein Array der _id-Werte der direkten Kinder ein. Dadurch lassen sich alle Kinder eines Knotens mit einem einzigen Lesevorgang schnell abrufen, ohne dass eine separate Abfrage erforderlich ist. Es eignet sich ideal für Bäume, die häufig von oben nach unten gelesen werden (z. B. wenn ein Menü sofort seine Untereinträge rendert). Der Nachteil besteht darin, dass das Kinder-Array bei Knoten mit vielen Kindern sehr groß werden kann und sich der übergeordnete Knoten ohne zusätzlichen Index oder zusätzliches Feld nicht effizient ermitteln lässt.

// Child References pattern
db.categories.insertMany([
  { _id: 1, name: 'Electronics', children: [2, 3] },
  { _id: 2, name: 'Phones',      children: [4, 5] },
  { _id: 3, name: 'Laptops',     children: [] },
  { _id: 4, name: 'Smartphones', children: [] },
  { _id: 5, name: 'Feature Phones', children: [] }
])

// Get direct children of Electronics in one read
const parent = db.categories.findOne({ _id: 1 })
const children = db.categories.find({ _id: { $in: parent.children } }).toArray()

$graphLookup für die Baumdurchquerung verwenden

Die $graphLookup-Aggregationsstufe von MongoDB folgt rekursiv Referenzfeldern, um einen Baum oder Graphen zu durchlaufen, der mit einem beliebigen Pattern gespeichert wurde. Sie gibt alle erreichbaren Knoten bis zu einer angegebenen Tiefe zurück. Verwenden Sie sie mit Parent References oder Child References, um Hierarchien zu durchlaufen, ohne rekursiven Anwendungscode schreiben zu müssen. Geben Sie maxDepth an, um Endlosschleifen in zyklischen Graphen zu verhindern.

// Traverse all descendants of Electronics using $graphLookup
db.categories.aggregate([
  { $match: { _id: 1 } },  // start from Electronics
  {
    $graphLookup: {
      from: 'categories',
      startWith: '$_id',
      connectFromField: '_id',
      connectToField: 'parent',
      as: 'descendants',
      maxDepth: 10
    }
  }
])

Schnelltest

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

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Das Outlier Pattern hält normale Dokumente schlank, indem Arrays bis zu einem Schwellenwert eingebettet werden und ein hasOverflow-Flag außergewöhnliche Dokumente an eine Overflow-Collection weiterleitet; Tree-Structure-Patterns (Parent References, Array of Ancestors, Materialised Paths) sind jeweils für unterschiedliche Abfragemuster bei hierarchischen Daten optimiert; und $graphLookup durchläuft Referenzen rekursiv innerhalb der Pipeline, ohne Rekursion auf Anwendungsseite. Als Nächstes vergleichen wir MongoDB und Redis für Dokument- beziehungsweise Key-Value-Workloads.

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 „Outlier- und Tree-Structure-Patterns“ kostenlos?

Ja — der vollständige Text von „Outlier- und Tree-Structure-Patterns“ 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 „Outlier- und Tree-Structure-Patterns“?

Lernende verarbeiten Dokumente mit ungewöhnlich großen Arrays mithilfe des Outlier-Patterns und modellieren hierarchische Baumdaten mit Parent-Referenzen oder materialisierten Pfaden. 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 4 von 4.

Wie lange dauert die Lektion „Outlier- und Tree-Structure-Patterns“?

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. Bucket- und Computed-Patterns
  2. Extended-Reference- und Subset-Patterns
  3. Polymorphe Patterns und Schema-Versionierung
  4. Outlier- und Tree-Structure-Patterns
← Zurück zu MongoDB Academy