Commit efba527a authored by Marcel Huber's avatar Marcel Huber
Browse files

Merge branch 'release_20.9.0'

parents dfe7636f c17e4357
Pipeline #40387 passed with stages
in 4 minutes and 33 seconds
= {myexerciseprefix}Abschluss{solutions-text}{mysubtitle}
:description: final exercise, finish all
:keywords: database, sql, MongoDB, sharding, postgresql
:keywords: database, sql, postgresql
:ex_number: 0
:current_dir_prefix: Abschluss/
//:exercise_solution:
......@@ -14,7 +14,6 @@ include::../ADocGitlabVars.asc[]
== Zielsetzung
* Sie kennen die Grundlagen der Datenbank-Migration mit Schema und Daten.
* Sie kennen, wie MongoDB Sharding implementiert und auf was geachtet werden muss.
Sie erhalten zudem Zeit, nicht-gelöste Aufgaben vorgängiger Übungen zu lösen und können Fragen klären, die beim Lösen der Aufgaben aufgetreten sind.
......@@ -166,153 +165,6 @@ COMMIT;
endif::exercise_solution[]
{blank}
=== Aufgabe {counter:ex_number}: Sharding mit MongoDB
[discrete]
===== Vorbereitung
Ihnen ist die link:{ci_project_fileref}MongoDBIntro/README.adoc[Übung MongoDB Einführung] (link:{ci_project_artifacts_download}MongoDBIntro/MongoDBIntro.pdf?job=ArtifactsCollection[PDF Datei]) bekannt.
Schauen Sie bei der Bearbeitung der untenstehenden Aufgaben jeweils diese Dokumentation zu https://docs.mongodb.com/manual/sharding/[Sharding mit MongoDB] an.
Lesen Sie zuerst folgenden http://vargas-solar.com/big-data-analytics/hands-on/sharding/[Blog-Post "Sharding data collections with MongoDB"] durch.
Beachten Sie dabei vorher folgende Themen bzw. beantworten Sie danach folgende Fragen.
. Was ist Sharding?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Sharding ist die horizontale Partitionierung auf Nodes die eigenständige Prozesse, Memory und Disks haben (_Horizontal Scaling Out_ mit _Shared nothing_-Architektur).
Vgl. dazu die Vorlesung.
[quote, 'Learn MongoDB The Hard Way', http://learnmongodbthehardway.com/schema/sharding/#sharding]
____
Sharding is a mechanism for scaling writes by distributing them across multiple shards.
____
=====
endif::exercise_solution[]
. Welche Strategien (Arten) von Sharding kennt MongoDB?
ifdef::exercise_solution[]
+
[example,title=""]
=====
MongoDB kennt die beiden Sharding-Stratgien _Range-based_ und _Hash-based_ (horizontal) Partitioning.
=====
endif::exercise_solution[]
. Was ist ein Shard Key?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Shard Key:: Ein Shard Key besteht aus einem oder mehreren unveränderlichen (_immutable_) Feldern, die in jedem Dokument einer Collection vorhanden sein müssen.
Um die Dokumente in einer Collection zu verteilen (_sharden_), partitioniert MongoDB die Collection mit dem Shard Key (_Splitterschlüssel_).
Der Datenbank-Administrator wählt den Shard Key beim Erstellen einer Collection.
Die Shard Key-Konfiguration kann danach nicht mehr verändert werden.
=====
endif::exercise_solution[]
. Was sind die Vorteile des Sharding?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Lastverteilung:: Verteilt den Lese- und Schreib-Workload auf die Shards im Sharded-Cluster, sodass jeder Shard eine Teilmenge der Cluster-Vorgänge verarbeiten kann.
Effizienz:: Bei Abfragen, die den Shard-Schlüssel oder das Präfix eines zusammengesetzten Shard-Schlüssels enthalten, können Mongos die Abfrage auf einen bestimmten Shard oder eine Gruppe von Shards ausrichten.
Diese gezielten Vorgänge sind in der Regel effizienter als das Senden an alle Splitter im Cluster.
Verfügbarkeit:: Ein sharded Cluster kann weiterhin partielle Lese- / Schreibvorgänge ausführen, selbst wenn ein oder mehrere Shards nicht verfügbar sind.
=> https://docs.mongodb.com/manual/sharding/#advantages-of-sharding[Vorteile des Sharding]
=====
endif::exercise_solution[]
. Was ist bei der Wahl eines Range-based Shard Keys zu beachten?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Kardinalität:: Die Kardinalität eines Shard Keys bestimmt die maximale Anzahl von Partitionen, die der MongoDB-Balancer erzeugen kann.
Ein guter Shard Key ist einer mit hoher Kardinalität (Cardinality) und niedriger Häufigkeit (Frequency).
Dies erleichtert die horizontale Skalierung bzw. gleichmässige Verteilung der Daten.
Man berücksichtige jeden dieser Faktoren bei der Auswahl eines Shard Keys.
Wenn ein Datenmodell ein Sharding auf einen Schlüssel mit niedriger Kardinalität erfordert, kann man auch einen zusammengesetzten Index mit einem Feld mit höherer Kardinalität verwenden.
Häufigkeit:: Die Häufigkeit des Shard Keys gibt an, wie oft ein bestimmter Wert in den Daten vorkommt.
Gute Kandidaten sind Felder mit kleiner Häufigkeit.
Ein monoton aufsteigender Schlüsselwert - wie namentlich der Identifikator (Id) - ist zu vermeiden, denn damit würde nur der erste Shard/Partition verwendet, was die Verteilung verunmöglicht oder aber ggf. zu aufwändigen Datenbank-internen Reorganisationen führt (vgl. https://docs.mongodb.com/manual/core/sharding-shard-key/#choosing-a-shard-key[choosing a shard key]).
Zum Vergleich: Beim Hash-based Sharding genügt es, das Feld der Collection anzugeben (z.B. Identifikator).
Der Hash wird dann vom System berechnet.
Mit dem Hash-based Sharding können auch monoton aufsteigende Schlüsselwerte (Ids) verwendet werden.
Man beachte die Ähnlichkeit eines Hash-based Shard Keys von MongoDB mit dem https://aws.amazon.com/de/blogs/database/choosing-the-right-dynamodb-partition-key/[Partition Key von Amazons DynamoDB] (Quelle: AWS Database Blog zu _Choosing the Right DynamoDB Partition Key_).
=====
endif::exercise_solution[]
. Was sind nun bei der Tabelle *angstellter* aus dem AngProj-Schema die verschiedenen Shard Key-Varianten (mind. 2)?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Wie erwähnt hat ein guter Shard Key folgende Eigenschaften: High cardinality, Low frequency, Non-monotonically changing in value.
Als Range-based Shard kommt Attribut *abt* in Frage. Dazu nehmen wir an, dass Bereichsabfragen ("Range Queries") vorkommen.
Ein möglicher Nachteil von Range-based Shards ist die Wahrscheinlichkeit einer unausgeglichenen Verteilung.
Als Hash-based Shard Key kann das Attribut *persnr* verwendet werden.
Hash-based Shards haben den Nachteil, dass nur genaue Match-Abfragen an einen bestimmten Shard weitergeleitet werden, d.h. Bereichsabfragen müssen Daten von allen Shards abrufen.
Als dritte Möglichkeit könnte in MongoDB noch der *_id* als Hash-based Shard Key verwendet werden.
Theoretisch könnte man noch einen zusammenengesetzten Range-based Shard Key in Betracht ziehen, doch das gibt die Tabelle *angestellter* nicht her.
=====
endif::exercise_solution[]
{blank}
////
=== Aufgabe {ex_number}{counter:subtopic}: Erweiterte Queries
:query_number: 0
Gegeben seien folgende Daten aus der xref:{ci_project_fileref}MongoDBIntro/README.adoc#mongodb-manual-joins[MongoDB Einführung (Manuelle Joins)].
.Daten
[source,js]
----
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d730"), name: 'Leto'})
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d731"), name: 'Duncan', manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d732"), name: 'Moneo', manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Siona', manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")] })
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name: 'Ghanima', family: {mother: 'Chani', father: 'Paul', brother: ObjectId("4d85c7039ab0fd70a117d730")}})
----
:query_name: employees-managed-by-leto
.[#{query_name}]#Q{counter:query_number} {query_name}#
Finde alle Angestellten mit Manager *Leto*.
ifdef::exercise_solution[]
[example,title=""]
=====
.Abfrage
[source,js]
----
db.employees.find({manager:{$in:[db.employees.findOne({name:'Leto'},{_id:1})._id]}},{_id:0})
----
.Untergebene von *Leto*
[source,js]
----
{ "name" : "Duncan", "manager" : ObjectId("4d85c7039ab0fd70a117d730") }
{ "name" : "Moneo", "manager" : ObjectId("4d85c7039ab0fd70a117d730") }
{ "name" : "Siona", "manager" : [ ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732") ] }
----
=====
endif::exercise_solution[]
////
[appendix,id='solutions']
== Musterlösung
......
= {myexerciseprefix}Abschluss{solutions-text}{mysubtitle}
:description: final exercise, finish all
:keywords: database, sql, MongoDB, sharding, postgresql
:keywords: database, sql, postgresql
:ex_number: 0
:current_dir_prefix: Abschluss/
:exercise_solution:
......@@ -14,7 +14,6 @@ include::../ADocGitlabVars.asc[]
== Zielsetzung
* Sie kennen die Grundlagen der Datenbank-Migration mit Schema und Daten.
* Sie kennen, wie MongoDB Sharding implementiert und auf was geachtet werden muss.
Sie erhalten zudem Zeit, nicht-gelöste Aufgaben vorgängiger Übungen zu lösen und können Fragen klären, die beim Lösen der Aufgaben aufgetreten sind.
......@@ -166,153 +165,6 @@ COMMIT;
endif::exercise_solution[]
{blank}
=== Aufgabe {counter:ex_number}: Sharding mit MongoDB
[discrete]
===== Vorbereitung
Ihnen ist die link:{ci_project_fileref}MongoDBIntro/README.adoc[Übung MongoDB Einführung] (link:{ci_project_artifacts_download}MongoDBIntro/MongoDBIntro.pdf?job=ArtifactsCollection[PDF Datei]) bekannt.
Schauen Sie bei der Bearbeitung der untenstehenden Aufgaben jeweils diese Dokumentation zu https://docs.mongodb.com/manual/sharding/[Sharding mit MongoDB] an.
Lesen Sie zuerst folgenden http://vargas-solar.com/big-data-analytics/hands-on/sharding/[Blog-Post "Sharding data collections with MongoDB"] durch.
Beachten Sie dabei vorher folgende Themen bzw. beantworten Sie danach folgende Fragen.
. Was ist Sharding?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Sharding ist die horizontale Partitionierung auf Nodes die eigenständige Prozesse, Memory und Disks haben (_Horizontal Scaling Out_ mit _Shared nothing_-Architektur).
Vgl. dazu die Vorlesung.
[quote, 'Learn MongoDB The Hard Way', http://learnmongodbthehardway.com/schema/sharding/#sharding]
____
Sharding is a mechanism for scaling writes by distributing them across multiple shards.
____
=====
endif::exercise_solution[]
. Welche Strategien (Arten) von Sharding kennt MongoDB?
ifdef::exercise_solution[]
+
[example,title=""]
=====
MongoDB kennt die beiden Sharding-Stratgien _Range-based_ und _Hash-based_ (horizontal) Partitioning.
=====
endif::exercise_solution[]
. Was ist ein Shard Key?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Shard Key:: Ein Shard Key besteht aus einem oder mehreren unveränderlichen (_immutable_) Feldern, die in jedem Dokument einer Collection vorhanden sein müssen.
Um die Dokumente in einer Collection zu verteilen (_sharden_), partitioniert MongoDB die Collection mit dem Shard Key (_Splitterschlüssel_).
Der Datenbank-Administrator wählt den Shard Key beim Erstellen einer Collection.
Die Shard Key-Konfiguration kann danach nicht mehr verändert werden.
=====
endif::exercise_solution[]
. Was sind die Vorteile des Sharding?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Lastverteilung:: Verteilt den Lese- und Schreib-Workload auf die Shards im Sharded-Cluster, sodass jeder Shard eine Teilmenge der Cluster-Vorgänge verarbeiten kann.
Effizienz:: Bei Abfragen, die den Shard-Schlüssel oder das Präfix eines zusammengesetzten Shard-Schlüssels enthalten, können Mongos die Abfrage auf einen bestimmten Shard oder eine Gruppe von Shards ausrichten.
Diese gezielten Vorgänge sind in der Regel effizienter als das Senden an alle Splitter im Cluster.
Verfügbarkeit:: Ein sharded Cluster kann weiterhin partielle Lese- / Schreibvorgänge ausführen, selbst wenn ein oder mehrere Shards nicht verfügbar sind.
=> https://docs.mongodb.com/manual/sharding/#advantages-of-sharding[Vorteile des Sharding]
=====
endif::exercise_solution[]
. Was ist bei der Wahl eines Range-based Shard Keys zu beachten?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Kardinalität:: Die Kardinalität eines Shard Keys bestimmt die maximale Anzahl von Partitionen, die der MongoDB-Balancer erzeugen kann.
Ein guter Shard Key ist einer mit hoher Kardinalität (Cardinality) und niedriger Häufigkeit (Frequency).
Dies erleichtert die horizontale Skalierung bzw. gleichmässige Verteilung der Daten.
Man berücksichtige jeden dieser Faktoren bei der Auswahl eines Shard Keys.
Wenn ein Datenmodell ein Sharding auf einen Schlüssel mit niedriger Kardinalität erfordert, kann man auch einen zusammengesetzten Index mit einem Feld mit höherer Kardinalität verwenden.
Häufigkeit:: Die Häufigkeit des Shard Keys gibt an, wie oft ein bestimmter Wert in den Daten vorkommt.
Gute Kandidaten sind Felder mit kleiner Häufigkeit.
Ein monoton aufsteigender Schlüsselwert - wie namentlich der Identifikator (Id) - ist zu vermeiden, denn damit würde nur der erste Shard/Partition verwendet, was die Verteilung verunmöglicht oder aber ggf. zu aufwändigen Datenbank-internen Reorganisationen führt (vgl. https://docs.mongodb.com/manual/core/sharding-shard-key/#choosing-a-shard-key[choosing a shard key]).
Zum Vergleich: Beim Hash-based Sharding genügt es, das Feld der Collection anzugeben (z.B. Identifikator).
Der Hash wird dann vom System berechnet.
Mit dem Hash-based Sharding können auch monoton aufsteigende Schlüsselwerte (Ids) verwendet werden.
Man beachte die Ähnlichkeit eines Hash-based Shard Keys von MongoDB mit dem https://aws.amazon.com/de/blogs/database/choosing-the-right-dynamodb-partition-key/[Partition Key von Amazons DynamoDB] (Quelle: AWS Database Blog zu _Choosing the Right DynamoDB Partition Key_).
=====
endif::exercise_solution[]
. Was sind nun bei der Tabelle *angstellter* aus dem AngProj-Schema die verschiedenen Shard Key-Varianten (mind. 2)?
ifdef::exercise_solution[]
+
[example,title=""]
=====
Wie erwähnt hat ein guter Shard Key folgende Eigenschaften: High cardinality, Low frequency, Non-monotonically changing in value.
Als Range-based Shard kommt Attribut *abt* in Frage. Dazu nehmen wir an, dass Bereichsabfragen ("Range Queries") vorkommen.
Ein möglicher Nachteil von Range-based Shards ist die Wahrscheinlichkeit einer unausgeglichenen Verteilung.
Als Hash-based Shard Key kann das Attribut *persnr* verwendet werden.
Hash-based Shards haben den Nachteil, dass nur genaue Match-Abfragen an einen bestimmten Shard weitergeleitet werden, d.h. Bereichsabfragen müssen Daten von allen Shards abrufen.
Als dritte Möglichkeit könnte in MongoDB noch der *_id* als Hash-based Shard Key verwendet werden.
Theoretisch könnte man noch einen zusammenengesetzten Range-based Shard Key in Betracht ziehen, doch das gibt die Tabelle *angestellter* nicht her.
=====
endif::exercise_solution[]
{blank}
////
=== Aufgabe {ex_number}{counter:subtopic}: Erweiterte Queries
:query_number: 0
Gegeben seien folgende Daten aus der xref:{ci_project_fileref}MongoDBIntro/README.adoc#mongodb-manual-joins[MongoDB Einführung (Manuelle Joins)].
.Daten
[source,js]
----
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d730"), name: 'Leto'})
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d731"), name: 'Duncan', manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d732"), name: 'Moneo', manager: ObjectId("4d85c7039ab0fd70a117d730")});
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Siona', manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")] })
db.employees.insert({_id: ObjectId("4d85c7039ab0fd70a117d734"), name: 'Ghanima', family: {mother: 'Chani', father: 'Paul', brother: ObjectId("4d85c7039ab0fd70a117d730")}})
----
:query_name: employees-managed-by-leto
.[#{query_name}]#Q{counter:query_number} {query_name}#
Finde alle Angestellten mit Manager *Leto*.
ifdef::exercise_solution[]
[example,title=""]
=====
.Abfrage
[source,js]
----
db.employees.find({manager:{$in:[db.employees.findOne({name:'Leto'},{_id:1})._id]}},{_id:0})
----
.Untergebene von *Leto*
[source,js]
----
{ "name" : "Duncan", "manager" : ObjectId("4d85c7039ab0fd70a117d730") }
{ "name" : "Moneo", "manager" : ObjectId("4d85c7039ab0fd70a117d730") }
{ "name" : "Siona", "manager" : [ ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732") ] }
----
=====
endif::exercise_solution[]
////
[appendix,id='solutions']
== Musterlösung
......
......@@ -297,7 +297,7 @@ Weiterführende Informationen zu diesen Aufgaben finden Sie in https://github.co
Verwenden Sie für diese Übung eine neue Datenbank `uebung2`.
.Basisdaten
.Basisdaten der Collection `unicorns`
[source,javascript]
----
{_id: ObjectId("5cc6e5d94249f49a59ac4000"), name: "Horny", dob: new Date(1992,2,13,7,47), loves: ["carrot","papaya"], weight: 600, gender: "m", vampires: 63},
......@@ -735,15 +735,14 @@ In dieser Aufgabe sollen Sie die verschiedenen Varianten kennenlernen.
Weiterführende Informationen zu dieser Aufgabe finden Sie auch in https://github.com/karlseguin/the-little-mongodb-book/blob/master/en/mongodb.markdown#chapter-4---data-modeling[Data Modeling] von The Little MongoDB Book.
.Daten
.Daten der Collection `employees`
[source,javascript]
----
db.employees.insertMany([
{_id: ObjectId("4d85c7039ab0fd70a117d730"), name: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d731"), name: "Duncan", manager: ObjectId("4d85c7039ab0fd70a117d730")},
{_id: ObjectId("4d85c7039ab0fd70a117d732"), name: "Moneo", manager: ObjectId("4d85c7039ab0fd70a117d730")},
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: "Siona", manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")]},
{_id: ObjectId("4d85c7039ab0fd70a117d734"), name: "Ghanima", family: {mother: "Chani", father: "Paul", brother: ObjectId("4d85c7039ab0fd70a117d730")}}
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: "Siona", manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")]}
])
----
......@@ -771,27 +770,13 @@ db.employees.findOne({_id: db.employees.find({name:"Moneo"})[0].manager})
----
=====
endif::exercise_solution[]
ifdef::blubby[]
. Finden Sie die Kinder von *Chani*.
// aus einer früheren Aufgabe?!
ifdef::exercise_solution[]
+
[example,title=""]
=====
.Kinder von *Chani*
[source, javascript]
----
db.employees.find({'family.mother': "Chani"})
=====
endif::exercise_solution[]
endif::blubby[]
[id='mongodb-joins-graphlookup']
==== Aufgabe {ex_number}{counter:subtopic}: Joins mit `$graphLookup` Operator
In dieser Aufgabe verwenden wir die https://docs.mongodb.com/manual/aggregation/[Aggregation Pipeline] und den https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/[`$graphLookup`] Operator.
.Daten
.Daten der Collection `employees`
[source,javascript]
----
{_id: ObjectId("4d85c7039ab0fd70a117d730"), name: "Leto"},
......@@ -830,7 +815,10 @@ db.employees.aggregate([
{ $match: { "name":"Moneo"} },
{ $project: { _id:0, name:1, manager:1, managerDocs:1 } }
])
----
.Resultat der Abfrage
[source, javascript]
----
{ "name" : "Moneo", "manager" : "Leto", "managerDocs" : [ { "_id" : ObjectId("4d85c7039ab0fd70a117d730"), "name" : "Leto" } ] }
----
=====
......@@ -841,30 +829,160 @@ endif::exercise_solution[]
Finden Sie eine Möglichkeit einen Join mittels https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/[`$lookup`] Operator durchzuführen?
Welche Daten passen dazu besser, die von <<mongodb-joins-manual>> oder von <<mongodb-joins-graphlookup>>
.[#lookup-manager-moneo]#Q{counter:query_number} Manager von *Moneo*#
Erstellen Sie eine Abfrage um den Manager von *Moneo* anzuzeigen.
.[#lookup-manager-moneo-which-data]#Q{counter:query_number} Passendes DataSet#
Welche Daten passen besser zu einer einfachen `$lookup` Abfrage, die von <<mongodb-joins-manual>> oder von <<mongodb-joins-graphlookup>>?
ifndef::exercise_solution[]
[example,title=""]
=====
{nbsp}
{nbsp}
=====
endif::exercise_solution[]
ifdef::exercise_solution[]
[example,title=""]
=====
Die Daten der Aufgabe <<mongodb-joins-graphlookup>> passen gut für diese einfache Join Abfrage über verschiedene Collections.
=====
endif::exercise_solution[]
{nbsp}
.[#lookup-manager-moneo]#Q{counter:query_number} Manager von *Moneo* ermitteln#
Erstellen Sie eine Abfrage um den Manager von *Moneo* anzuzeigen unter Verwendung von `localField` und `foreignField`.
.Daten der Collection `employees`
[source,javascript]
----
{_id: ObjectId("4d85c7039ab0fd70a117d730"), name: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d731"), name: "Duncan", manager: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d732"), name: "Moneo", manager: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: "Siona", manager: ["Leto", "Moneo"] }
----
[example,title=""]
=====
.Manager von *Moneo* mit einfachem `$lookup` Aggregat
ifdef::exercise_solution[]
[source,javascript]
----
db.employees.aggregate({
$lookup: {
from: "employees",
localField: "manager",
foreignField: "name",
as: "managers"
}
}, {
$match: {
"name": "Moneo"
}
}, {
$project: {
_id: 0,
manager: 0,
managers: {
_id: 0,
manager: 0
}
}
})
----
endif::exercise_solution[]
ifndef::exercise_solution[]
{nbsp}
{nbsp}
{nbsp}
{nbsp}
endif::exercise_solution[]
.Resultat der Abfrage
ifdef::exercise_solution[]
[source, javascript]
----
{ "name" : "Moneo", "managers" : [ { "name" : "Leto" } ] }
----
endif::exercise_solution[]
ifndef::exercise_solution[]
{nbsp}
{nbsp}
endif::exercise_solution[]
=====
.[#lookup-manager-moneo]#Q{counter:query_number} Manager von *Moneo* über verschiedene Collections ermitteln#
Erstellen Sie eine Abfrage um den Manager von *Moneo* anzuzeigen wenn die Daten in zwei unterschiedlichen Collections abgelegt sind.
.Daten der beiden Collections
[source,javascript]
----
db.employees.insertMany([
{_id: ObjectId("4d85c7039ab0fd70a117d731"), name: "Duncan", manager: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d732"), name: "Moneo", manager: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: "Siona", manager: ["Leto", "Moneo"]}
])
db.managers.insertMany([
{_id: ObjectId("4d85c7039ab0fd70a117d740"), name: "Leto", department: "Sales"},
{_id: ObjectId("4d85c7039ab0fd70a117d741"), name: "Moneo", department: "Research"}
])
----
[example,title=""]
=====
.Manager von *Moneo* mit `$lookup`
[source, subs="attributes", javascript]
ifdef::exercise_solution[]
[source, javascript]
----
tbd.
db.employees.aggregate({
$lookup: {
from: "managers",
localField: "manager",
foreignField: "name",
as: "managers"
}
}, {
$match: {
"name": "Moneo"
}
}, {
$project: {
_id: 0,
manager: 0,
managers: {
_id: 0
}
}
})
----
=====
endif::exercise_solution[]
ifndef::exercise_solution[]
{nbsp}
{nbsp}
{nbsp}
{nbsp}
endif::exercise_solution[]
.Resultat der Abfrage
ifdef::exercise_solution[]
[source, javascript]
----
{ "name" : "Duncan", "managers" : [ { "name" : "Leto", "department" : "Sales" } ] }
{ "name" : "Moneo", "managers" : [ { "name" : "Leto", "department" : "Sales" } ] }
{ "name" : "Siona", "managers" : [ { "name" : "Leto", "department" : "Sales" }, { "name" : "Moneo", "department" : "Research" } ] }
----
endif::exercise_solution[]
ifndef::exercise_solution[]
{nbsp}
{nbsp}
{nbsp}
endif::exercise_solution[]
=====
include::{exercises_dir}MongodbShardingScalingOut.asc[]
......
......@@ -297,7 +297,7 @@ Weiterführende Informationen zu diesen Aufgaben finden Sie in https://github.co
Verwenden Sie für diese Übung eine neue Datenbank `uebung2`.
.Basisdaten
.Basisdaten der Collection `unicorns`
[source,javascript]
----
{_id: ObjectId("5cc6e5d94249f49a59ac4000"), name: "Horny", dob: new Date(1992,2,13,7,47), loves: ["carrot","papaya"], weight: 600, gender: "m", vampires: 63},
......@@ -735,15 +735,14 @@ In dieser Aufgabe sollen Sie die verschiedenen Varianten kennenlernen.
Weiterführende Informationen zu dieser Aufgabe finden Sie auch in https://github.com/karlseguin/the-little-mongodb-book/blob/master/en/mongodb.markdown#chapter-4---data-modeling[Data Modeling] von The Little MongoDB Book.
.Daten
.Daten der Collection `employees`
[source,javascript]
----
db.employees.insertMany([
{_id: ObjectId("4d85c7039ab0fd70a117d730"), name: "Leto"},
{_id: ObjectId("4d85c7039ab0fd70a117d731"), name: "Duncan", manager: ObjectId("4d85c7039ab0fd70a117d730")},
{_id: ObjectId("4d85c7039ab0fd70a117d732"), name: "Moneo", manager: ObjectId("4d85c7039ab0fd70a117d730")},
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: "Siona", manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")]},
{_id: ObjectId("4d85c7039ab0fd70a117d734"), name: "Ghanima", family: {mother: "Chani", father: "Paul", brother: ObjectId("4d85c7039ab0fd70a117d730")}}
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: "Siona", manager: [ObjectId("4d85c7039ab0fd70a117d730"), ObjectId("4d85c7039ab0fd70a117d732")]}
])
----
......@@ -771,27 +770,13 @@ db.employees.findOne({_id: db.employees.find({name:"Moneo"})[0].manager})
----
=====
endif::exercise_solution[]
ifdef::blubby[]
. Finden Sie die Kinder von *Chani*.
// aus einer früheren Aufgabe?!
ifdef::exercise_solution[]
+
[example,title=""]
=====
.Kinder von *Chani*
[source, javascript]
----
db.employees.find({'family.mother': "Chani"})
=====
endif::exercise_solution[]
endif::blubby[]
[id='mongodb-joins-graphlookup']
==== Aufgabe {ex_number}{counter:subtopic}: Joins mit `$graphLookup` Operator
In dieser Aufgabe verwenden wir die https://docs.mongodb.com/manual/aggregation/[Aggregation Pipeline] und den https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/[`$graphLookup`] Operator.
.Daten
.Daten der Collection `employees`
[source,javascript]
----
{_id: ObjectId("4d85c7039ab0fd70a117d730"), name: "Leto"},
......@@ -830,7 +815,10 @@ db.employees.aggregate([
{ $match: { "name":"Moneo"} },
{ $project: { _id:0, name:1, manager:1, managerDocs:1 } }
])
----
.Resultat der Abfrage
[source, javascript]
----
{ "name" : "Moneo", "manager" : "Leto", "managerDocs" : [ { "_id" : ObjectId("4d85c7039ab0fd70a117d730"), "name" : "Leto" } ] }
----
=====
......@@ -841,30 +829,160 @@ endif::exercise_solution[]
Finden Sie eine Möglichkeit einen Join mittels https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/[`$lookup`] Operator durchzuführen?
Welche Daten passen dazu besser, die von <<mongodb-joins-manual>> oder von <<mongodb-joins-graphlookup>>
.[#lookup-manager-moneo]#Q{counter:query_number} Manager von *Moneo*#
Erstellen Sie eine Abfrage um den Manager von *Moneo* anzuzeigen.