Ich bin neu in MongoDB und komme aus einer relationalen Datenbank. Ich möchte eine Fragenstruktur mit einigen Kommentaren entwerfen, weiß aber nicht, welche Beziehung für Kommentare verwendet werden soll: embed
oder reference
?
Eine Frage mit einigen Kommentaren, wie z. B. Stackoverflow , hätte eine folgende Struktur:
Question
title = 'aaa'
content = bbb'
comments = ???
Zuerst möchte ich eingebettete Kommentare verwenden (ich denke, dies embed
wird in MongoDB empfohlen), wie folgt:
Question
title = 'aaa'
content = 'bbb'
comments = [ { content = 'xxx', createdAt = 'yyy'},
{ content = 'xxx', createdAt = 'yyy'},
{ content = 'xxx', createdAt = 'yyy'} ]
Es ist klar, aber ich mache mir Sorgen um diesen Fall: Wenn ich einen bestimmten Kommentar bearbeiten möchte, wie erhalte ich seinen Inhalt und seine Frage? Es gibt keine _id
Möglichkeit, mich einen finden question_ref
zu lassen oder seine Frage zu finden. (Ich bin so ein Neuling, dass ich nicht weiß, ob es eine Möglichkeit gibt, dies ohne _id
und zu tun question_ref
.)
Muss ich ref
nicht verwenden embed
? Dann muss ich eine neue Sammlung für Kommentare erstellen?
Antworten:
Dies ist mehr eine Kunst als eine Wissenschaft. Die Mongo-Dokumentation zu Schemata ist eine gute Referenz, aber hier sind einige Dinge zu beachten:
Gib so viel wie möglich ein
Die Freude an einer Dokumentendatenbank besteht darin, dass viele Verknüpfungen eliminiert werden. Ihr erster Instinkt sollte darin bestehen, so viel wie möglich in einem einzigen Dokument zu platzieren. Da MongoDB-Dokumente strukturiert sind und Sie innerhalb dieser Struktur effizient abfragen können (dies bedeutet, dass Sie den Teil des Dokuments übernehmen können, den Sie benötigen, sodass die Dokumentgröße Sie nicht sonderlich beunruhigen sollte), besteht keine unmittelbare Notwendigkeit, Daten wie zu normalisieren Sie würden in SQL. Insbesondere sollten alle Daten, die außer dem übergeordneten Dokument nicht nützlich sind, Teil desselben Dokuments sein.
Trennen Sie Daten, auf die von mehreren Stellen aus verwiesen werden kann, in eine eigene Sammlung.
Dies ist weniger ein "Speicherplatz" -Problem als vielmehr ein "Datenkonsistenz" -Problem. Wenn sich viele Datensätze auf dieselben Daten beziehen, ist es effizienter und weniger fehleranfällig, einen einzelnen Datensatz zu aktualisieren und an anderen Stellen Verweise darauf zu behalten.
Überlegungen zur Dokumentgröße
MongoDB legt eine Größenbeschränkung von 4 MB (16 MB mit 1,8 MB) für ein einzelnes Dokument fest. In einer Welt mit GB Daten klingt dies klein, aber es sind auch 30.000 Tweets oder 250 typische Stapelüberlaufantworten oder 20 Flimmerfotos. Auf der anderen Seite sind dies weit mehr Informationen, als man auf einer typischen Webseite gleichzeitig präsentieren möchte. Überlegen Sie zunächst, was Ihre Anfragen einfacher macht. In vielen Fällen besteht die Sorge um die Dokumentgröße in einer vorzeitigen Optimierung.
Komplexe Datenstrukturen:
MongoDB kann beliebige tief verschachtelte Datenstrukturen speichern, diese jedoch nicht effizient durchsuchen. Wenn Ihre Daten einen Baum, eine Gesamtstruktur oder ein Diagramm bilden, müssen Sie jeden Knoten und seine Kanten effektiv in einem separaten Dokument speichern. (Beachten Sie, dass es Datenspeicher gibt, die speziell für diese Art von Daten entwickelt wurden und die Sie ebenfalls berücksichtigen sollten.)
Es wurde auch darauf hingewiesen, dass es unmöglich ist, eine Teilmenge von Elementen in einem Dokument zurückzugeben. Wenn Sie einige Teile jedes Dokuments auswählen müssen, ist es einfacher, sie voneinander zu trennen.
Datenkonsistenz
MongoDB macht einen Kompromiss zwischen Effizienz und Konsistenz. Die Regel lautet, dass Änderungen an einem einzelnen Dokument immer atomar sind, während Aktualisierungen an mehreren Dokumenten niemals als atomar angenommen werden sollten. Es gibt auch keine Möglichkeit, einen Datensatz auf dem Server zu "sperren" (Sie können dies in die Logik des Clients einbauen, indem Sie beispielsweise ein Feld "sperren" verwenden). Überlegen Sie beim Entwerfen Ihres Schemas, wie Sie Ihre Daten konsistent halten. Im Allgemeinen ist es umso besser, je mehr Sie in einem Dokument aufbewahren.
Für das, was Sie beschreiben, würde ich die Kommentare einbetten und jedem Kommentar ein ID-Feld mit einer ObjectID geben. In die ObjectID ist ein Zeitstempel eingebettet, sodass Sie diesen verwenden können, anstatt ihn zu erstellen, wenn Sie möchten.
quelle
Im Allgemeinen ist die Einbettung gut, wenn Sie Eins-zu-Eins- oder Eins-zu-Viele-Beziehungen zwischen Entitäten haben, und die Referenz ist gut, wenn Sie Viele-zu-Viele-Beziehungen haben.
quelle
Sie können nach Unterdokument abfragen :
db.question.find({'comments.content' : 'xxx'})
.Dadurch wird das gesamte Fragendokument zurückgegeben. Um den angegebenen Kommentar zu bearbeiten, müssen Sie den Kommentar auf dem Client suchen, bearbeiten und in der Datenbank speichern.
Wenn Ihr Dokument ein Array von Objekten enthält, müssen diese Unterobjekte im Allgemeinen clientseitig geändert werden.
quelle
Nun, ich bin etwas spät dran, möchte aber trotzdem meine Art der Schemaerstellung teilen.
Ich habe Schemata für alles, was durch ein Wort beschrieben werden kann, wie Sie es in der klassischen OOP tun würden.
Z.B
Jedes Schema kann als Dokument oder Unterdokument gespeichert werden, daher erkläre ich dies für jedes Schema.
Dokumentieren:
Unterdokument:
quelle
Ich bin auf diese kleine Präsentation gestoßen, als ich diese Frage selbst recherchiert habe. Ich war überrascht, wie gut es angelegt war, sowohl die Informationen als auch die Präsentation.
http://openmymind.net/Multiple-Collections-Versus-Embedded-Documents
Es fasste zusammen:
quelle
a lot
? 3? 10? 100? Was istlarge
? 1kb? 1 MB? 3 Felder? 20 Felder? Was istsmaller
/fewer
?Ich weiß, dass dies ziemlich alt ist, aber wenn Sie nach einer Antwort auf die Frage des OP suchen, wie nur ein bestimmter Kommentar zurückgegeben werden kann, können Sie den Operator $ (Abfrage) wie folgt verwenden:
quelle
Ja, wir können die Referenz im Dokument verwenden. Um das andere Dokument genau wie SQL zu füllen, füge ich hinzu. In Mongo DB haben sie keine Verknüpfungen, um ein Dokument mit mehreren Beziehungen zuzuordnen. Stattdessen können wir das Auffüllen verwenden , um unser Szenario zu erfüllen.
Beim Auffüllen werden die angegebenen Pfade im Dokument automatisch durch Dokumente aus anderen Sammlungen ersetzt. Wir können ein einzelnes Dokument, mehrere Dokumente, ein einfaches Objekt, mehrere einfache Objekte oder alle von einer Abfrage zurückgegebenen Objekte füllen. Schauen wir uns einige Beispiele an.
Weitere Informationen erhalten Sie unter: http://mongoosejs.com/docs/populate.html
quelle
Eigentlich bin ich ziemlich neugierig, warum niemand über die UML-Spezifikationen gesprochen hat. Als Faustregel gilt: Wenn Sie eine Aggregation haben, sollten Sie Referenzen verwenden. Wenn es sich jedoch um eine Komposition handelt, ist die Kopplung stärker und Sie sollten eingebettete Dokumente verwenden.
Und Sie werden schnell verstehen, warum es logisch ist. Wenn ein Objekt unabhängig vom übergeordneten Objekt vorhanden sein kann, möchten Sie auch dann darauf zugreifen, wenn das übergeordnete Objekt nicht vorhanden ist. Da Sie es einfach nicht in ein nicht vorhandenes übergeordnetes Element einbetten können, müssen Sie es in seiner eigenen Datenstruktur live schalten. Wenn ein übergeordnetes Element vorhanden ist, verknüpfen Sie es einfach miteinander, indem Sie dem übergeordneten Objekt eine Referenz des Objekts hinzufügen.
Sie wissen nicht wirklich, was der Unterschied zwischen den beiden Beziehungen ist? Hier ist ein Link, der sie erklärt: Aggregation vs Komposition in UML
quelle
Ich habe dieses Quiz als Referenz erstellt, um zu wissen, ob Sie das eine oder andere verwenden sollten
http://indie-rok.github.io/embedded-vs-reference-mongo-db
quelle
Wenn Sie die Anzahl der Kommentare und den Index des Kommentars, den Sie ändern möchten, nachverfolgt haben, können Sie den Punktoperator verwenden ( SO-Beispiel) ).
Sie könnten f.ex.
(als eine andere Möglichkeit, die Kommentare in der Frage zu bearbeiten)
quelle