MongoDB-Felder projizieren

MongoDBBeginner
Jetzt üben

Einführung

In diesem Lab lernen Sie, wie Sie MongoDB-Projektionen verwenden, um zu steuern, welche Felder in Ihren Abfrageergebnissen angezeigt werden. Projektion ist ein leistungsstarkes Feature, das es Ihnen ermöglicht, bestimmte Felder für die Rückgabe auszuwählen. Dies kann die über das Netzwerk übertragene Datenmenge reduzieren und die Abfrageleistung verbessern. Sie werden das Ein- und Ausschließen von Feldern, das Projizieren von Feldern innerhalb verschachtelter Dokumente und die Verwendung des Aggregations-Frameworks zur Umgestaltung der Ausgabe üben. Am Ende dieses Labs werden Sie ein solides Verständnis dafür haben, wie Sie Projektionen effektiv in Ihren MongoDB-Abfragen einsetzen.

Spezifische Felder mit Projektion auswählen

In diesem ersten Schritt lernen Sie die Grundlagen der Projektion, indem Sie nur die spezifischen Felder auswählen, die Sie in Ihren Abfrageergebnissen sehen möchten. Dies wird als "inklusive" Projektion bezeichnet.

Öffnen Sie zuerst die MongoDB Shell. Diese interaktive Befehlszeilenschnittstelle ist der Ort, an dem Sie alle Ihre Datenbankbefehle für dieses Lab ausführen werden.

mongosh

Sie befinden sich nun in der MongoDB Shell. Ihre Terminal-Eingabeaufforderung ändert sich, um anzuzeigen, dass Sie verbunden sind. Wechseln wir zu einer neuen Datenbank namens projectlab_database und fügen einige Beispieldaten ein. Wenn die Datenbank nicht existiert, erstellt MongoDB sie für Sie, sobald Sie Daten speichern.

use projectlab_database

Fügen Sie als Nächstes drei Dokumente in eine Sammlung namens users ein.

db.users.insertMany([
  {
    name: "John Doe",
    age: 30,
    email: "john.doe@example.com",
    city: "New York",
    job: "Software Engineer"
  },
  {
    name: "Jane Smith",
    age: 28,
    email: "jane.smith@example.com",
    city: "San Francisco",
    job: "Data Scientist"
  },
  {
    name: "Mike Johnson",
    age: 35,
    email: "mike.johnson@example.com",
    city: "Chicago",
    job: "Product Manager"
  }
]);

Nun fragen wir diese Sammlung ab. Um nur die Felder name und age für alle Dokumente zurückzugeben, fügen Sie ein Projektionsdokument als zweites Argument zur find()-Methode hinzu. Im Projektionsdokument geben Sie die einzuschließenden Felder mit einer 1 an. Standardmäßig wird das Feld _id immer zurückgegeben. Sie können es explizit ausschließen, indem Sie seinen Wert auf 0 setzen.

db.users.find({}, { name: 1, age: 1, _id: 0 });

Sie sollten die folgende Ausgabe sehen, die nur die Felder name und age für jeden Benutzer enthält:

[
  { "name": "John Doe", "age": 30 },
  { "name": "Jane Smith", "age": 28 },
  { "name": "Mike Johnson", "age": 35 }
]

Diese Technik ist sehr nützlich, um nur die notwendigen Daten abzurufen, was besonders wichtig ist, wenn Sie mit großen Dokumenten arbeiten.

Spezifische Felder von Ergebnissen ausschließen

Zusätzlich zur Auswahl der einzuschließenden Felder können Sie auch angeben, welche Felder ausgeschlossen werden sollen. Dies wird als "exklusive" Projektion bezeichnet und ist nützlich, wenn Sie die meisten Felder sehen möchten, aber einige, wie sensible oder große, ausblenden wollen.

Sie sollten sich immer noch in der mongosh-Shell befinden und projectlab_database ausgewählt haben.

Um Felder auszuschließen, setzen Sie ihren Wert im Projektionsdokument auf 0. Führen wir eine Abfrage aus, um alle Benutzerdaten abzurufen, aber die Felder email und city auszuschließen.

db.users.find({}, { email: 0, city: 0 });

Die Ausgabe enthält alle Felder außer email und city. Beachten Sie, dass das Feld _id standardmäßig immer noch enthalten ist.

[
  {
    _id: ObjectId("..."),
    name: 'John Doe',
    age: 30,
    job: 'Software Engineer'
  },
  {
    _id: ObjectId("..."),
    name: 'Jane Smith',
    age: 28,
    job: 'Data Scientist'
  },
  {
    _id: ObjectId("..."),
    name: 'Mike Johnson',
    age: 35,
    job: 'Product Manager'
  }
]

Eine wichtige Regel bei der Projektion ist, dass Sie in demselben Projektionsdokument keine Inklusion (1) und keinen Ausschluss (0) mischen können. Die einzige Ausnahme von dieser Regel ist das Feld _id. Sie können das Feld _id explizit ausschließen (_id: 0), auch wenn Sie andere Felder einschließen, wie Sie es im vorherigen Schritt getan haben. Sie können es auch in einer exklusiven Projektion ausschließen.

Um beispielsweise email, city und _id auszuschließen, würden Sie Folgendes ausführen:

db.users.find({}, { email: 0, city: 0, _id: 0 });

Diese Abfrage gibt Dokumente zurück, die nur die Felder name, age und job enthalten.

Felder in verschachtelten Dokumenten projizieren

Reale Daten sind oft mit verschachtelten Dokumenten und Arrays strukturiert. Die Projektionsfähigkeiten von MongoDB ermöglichen es Ihnen, Felder präzise auszuwählen, selbst wenn sie tief in der Dokumentenstruktur eingebettet sind.

Löschen wir zunächst die vorhandene users-Sammlung und fügen neue Dokumente ein, die ein verschachteltes contact-Objekt und ein skills-Array enthalten.

db.users.deleteMany({});

Fügen Sie nun die neuen Daten ein.

db.users.insertMany([
  {
    name: "John Doe",
    contact: {
      email: "john.doe@example.com",
      phone: {
        mobile: "123-456-7890",
        work: "987-654-3210"
      }
    },
    skills: ["JavaScript", "MongoDB", "React"]
  },
  {
    name: "Jane Smith",
    contact: {
      email: "jane.smith@example.com",
      phone: {
        mobile: "234-567-8901",
        work: "876-543-2109"
      }
    },
    skills: ["Python", "Data Science", "Machine Learning"]
  }
]);

Um ein Feld innerhalb eines verschachtelten Dokuments zu projizieren, verwenden Sie die "Punktnotation" (dot notation). Um beispielsweise den name des Benutzers und seine Handynummer auszuwählen, würden Sie "contact.phone.mobile": 1 angeben. Versuchen wir, den name, die email und die Handynummer (mobile) zu projizieren.

db.users.find(
  {},
  {
    name: 1,
    "contact.email": 1,
    "contact.phone.mobile": 1,
    _id: 0
  }
);

Das Ergebnis behält die verschachtelte Struktur für die ausgewählten Felder bei:

[
  {
    "name": "John Doe",
    "contact": {
      "email": "john.doe@example.com",
      "phone": { "mobile": "123-456-7890" }
    }
  },
  {
    "name": "Jane Smith",
    "contact": {
      "email": "jane.smith@example.com",
      "phone": { "mobile": "234-567-8901" }
    }
  }
]

Sie können auch einen Teil eines Arrays mit dem $slice-Operator projizieren. Um den name und nur die ersten beiden Fähigkeiten für jeden Benutzer zu erhalten, führen Sie den folgenden Befehl aus:

db.users.find({}, { name: 1, skills: { $slice: 2 }, _id: 0 });

Die Ausgabe zeigt jeden Benutzer mit einem skills-Array, das nur zwei Elemente enthält:

[
  { "name": "John Doe", "skills": ["JavaScript", "MongoDB"] },
  { "name": "Jane Smith", "skills": ["Python", "Data Science"] }
]

Ausgabefelder mit Aggregation umformen

Für fortgeschrittenere Transformationen, wie das Umbenennen von Feldern oder das Erstellen neuer berechneter Felder, reicht die Projektion der find()-Methode nicht aus. Stattdessen können Sie das Aggregations-Framework verwenden, insbesondere die $project-Phase.

Bereiten wir unsere Daten für diesen Schritt vor. Löschen Sie die Sammlung und fügen Sie Benutzer mit Gehaltsinformationen ein.

db.users.deleteMany({});
db.users.insertMany([
  {
    name: "John Doe",
    age: 30,
    salary: 75000,
    department: "Engineering"
  },
  {
    name: "Jane Smith",
    age: 28,
    salary: 85000,
    department: "Data Science"
  },
  {
    name: "Mike Johnson",
    age: 35,
    salary: 95000,
    department: "Management"
  }
]);

Die $project-Phase in einer Aggregations-Pipeline kann Dokumente neu gestalten, indem neue Felder hinzugefügt, vorhandene Felder umbenannt oder Felder entfernt werden. Um sie zu verwenden, übergeben Sie ein Array von Phasen an die aggregate()-Methode.

Um ein Feld umzubenennen, definieren Sie einen neuen Feldnamen und weisen ihm den Wert eines vorhandenen Feldes zu, dem ein Dollarzeichen ($) vorangestellt ist. Benennen wir name in fullName und age in yearsOld um.

db.users.aggregate([
  {
    $project: {
      fullName: "$name",
      yearsOld: "$age",
      _id: 0
    }
  }
]);

Sie können auch neue Felder basierend auf Berechnungen erstellen. Erstellen wir ein Feld monthlySalary, indem wir das Jahresgehalt (salary) durch 12 teilen, und ein Feld salaryTier basierend auf bedingter Logik mit dem $switch-Operator.

db.users.aggregate([
  {
    $project: {
      name: 1,
      monthlySalary: { $divide: ["$salary", 12] },
      salaryTier: {
        $switch: {
          branches: [
            { case: { $lt: ["$salary", 80000] }, then: "Junior" },
            { case: { $gte: ["$salary", 80000] }, then: "Senior" }
          ],
          default: "Unknown"
        }
      },
      _id: 0
    }
  }
]);

Die Ausgabe ist eine komplett neue Dokumentenstruktur, die Sie in der $project-Phase definiert haben:

[
  { "name": "John Doe", "monthlySalary": 6250, "salaryTier": "Junior" },
  {
    "name": "Jane Smith",
    "monthlySalary": 7083.333333333333,
    "salaryTier": "Senior"
  },
  {
    "name": "Mike Johnson",
    "monthlySalary": 7916.666666666667,
    "salaryTier": "Senior"
  }
]

Die $project-Phase gibt Ihnen die vollständige Kontrolle über die endgültige Form Ihrer Abfrageergebnisse und ermöglicht leistungsstarke Datentransformationen direkt in der Datenbank.

Zusammenfassung

In diesem Lab haben Sie gelernt, wie Sie die Ausgabe Ihrer MongoDB-Abfragen effektiv mithilfe von Projektionen steuern. Sie haben mit den Grundlagen des Ein- und Ausschließens von Feldern mit der find()-Methode begonnen. Anschließend haben Sie sich fortgeschritteneren Themen zugewandt, wie der Verwendung der Punktnotation (dot notation) zur Projektion von Feldern in verschachtelten Dokumenten und der Verwendung des $slice-Operators, um eine Teilmenge eines Arrays zurückzugeben. Schließlich haben Sie die Leistungsfähigkeit der $project-Phase des Aggregations-Frameworks erkundet, um Dokumente vollständig neu zu gestalten, indem Sie Felder umbenannt, neue berechnete Felder erstellt und bedingte Logik angewendet haben. Diese Fähigkeiten sind grundlegend für das Schreiben effizienter und präziser Abfragen in MongoDB.