Mungo-Unterdokumente gegen verschachteltes Schema

122

Ich bin gespannt auf die Vor- und Nachteile der Verwendung von Unterdokumenten gegenüber einer tieferen Ebene in meinem Hauptschema:

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});

oder

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

Ich verwende derzeit überall Subdocs, wundere mich aber hauptsächlich über die Leistung oder das Abfragen von Problemen, auf die ich stoßen könnte.

Cyberwombat
quelle
Ich habe versucht, Ihnen eine Antwort zu geben, aber ich konnte nicht finden, wie. Aber geben Sie einen Blick auf hier: mongoosejs.com/docs/subdocs.html
gustavohenke
Hier ist eine gute Antwort zu MongoDB-Überlegungen, die Sie sich beim Erstellen Ihres Datenbankschemas stellen sollten: stackoverflow.com/questions/5373198/…
anthonylawson
Sie meinten, dass es erforderlich ist, auch das _idFeld zu beschreiben ? Ich meine, es ist nicht automatisch, wenn es aktiviert ist?
Vadorequest
weiß jemand, ob das _idFeld der Unterdokumente einzigartig ist? (erstellt mit dem 2. Weg in OPs Frage)
Saitama

Antworten:

71

Laut den Dokumenten ist es genau das gleiche. Die Verwendung eines Schemas würde jedoch auch ein _idFeld hinzufügen (sofern Sie dieses nicht deaktiviert haben) und vermutlich weitere Ressourcen zum Verfolgen von Subdocs verwenden.

Alternative Deklarationssyntax

Neu in Version 3 Wenn Sie keinen Zugriff auf die Instanz des Unterdokumentschemas benötigen, können Sie Unterdokumente auch deklarieren, indem Sie einfach ein Objektliteral übergeben [...]

AndyL
quelle
1
Aber ich habe es versucht. Warum die Unterdokumentdaten nicht in einer separaten Sammlung gespeichert werden. Es wird immer in der mainDoc-Sammlung gespeichert.
Fizer Khan
17
So funktionieren Unterdokumente. Sie werden in ein Dokument eingebettet. Stellen Sie vor dem Spielen mit Mungo sicher, dass Sie die zugrunde liegende MongoDB verstehen.
AndyL
1
In Bezug auf das Schema, das _id hinzufügt, ist dies sinnvoll, aber ich habe ein Schema mit einem Array von Unterdokumenten und einem Array von Objektliteralen erstellt, und beiden wurde eine _id hinzugefügt. Hat sich das Verhalten geändert?
Drew Goodwin
@DrewGoodwin scheint es für eine Weile so gewesen zu sein: stackoverflow.com/questions/17254008/…
cheesemacfly
37

Wenn Sie Schemas haben, die in verschiedenen Teilen Ihres Modells wiederverwendet werden, kann es hilfreich sein, einzelne Schemas für die untergeordneten Dokumente zu definieren, damit Sie sich nicht duplizieren müssen.

sonstone
quelle
4
Dies ist eine großartige Antwort. Manchmal verwende ich Unterdokumente in mehr als einem Modell, oder ich habe zwei Felder in einem Modell, die unterschieden werden müssen, aber immer noch dieselbe Unterdokumentstruktur haben.
Martin Hallén
2
Sie sollten auch die Vor- und Nachteile des Speicherns redundanter Informationen berücksichtigen.
Sam Vloeberghs
25

Sie sollten eingebettete Dokumente verwenden, wenn es sich um statische Dokumente handelt oder aufgrund von Leistungseinbußen nicht mehr als einige Hundert. Ich habe mich vor einiger Zeit mit diesem Thema befasst. Neu war, dass Asya Kamsky, die als Lösungsarchitektin für MongoDB arbeitet, einen Artikel über "Verwenden von Unterdokumenten" geschrieben hat.

Ich hoffe, das hilft, wer nach Lösungen oder Best Practices sucht.

Ursprünglicher Beitrag auf http://askasya.com/post/largeembeddedarrays . Sie erreichen ihr Stackoverflow-Profil unter https://stackoverflow.com/users/431012/asya-kamsky

Zunächst müssen wir uns überlegen, warum wir so etwas tun wollen. Normalerweise würde ich Leuten raten, Dinge einzubetten, die sie immer wieder haben möchten, wenn sie dieses Dokument abrufen. Die Kehrseite davon ist, dass Sie keine Dinge in das Dokument einbetten möchten, die Sie nicht zurückbekommen möchten.

Wenn Sie die von mir ausgeführten Aktivitäten in das Dokument einbetten, funktioniert dies zunächst hervorragend, da alle meine Aktivitäten genau dort sind und Sie mit einem einzigen Lesevorgang alles zurückerhalten können, was Sie mir möglicherweise zeigen möchten: "Sie haben kürzlich auf dieses und hier geklickt sind deine letzten beiden Kommentare "aber was passiert nach sechs Monaten und ich kümmere mich nicht um Dinge, die ich vor langer Zeit getan habe und du willst sie mir nicht zeigen, es sei denn, ich suche speziell nach einer alten Aktivität?

Erstens werden Sie immer größere Dokumente zurückgeben und sich um immer kleinere Teile kümmern. Sie können die Projektion jedoch verwenden, um nur einen Teil des Arrays zurückzugeben. Der eigentliche Schmerz besteht darin, dass das Dokument auf der Festplatte größer wird und immer noch alles gelesen wird, auch wenn Sie nur einen Teil davon an den Endbenutzer zurückgeben, aber Da meine Aktivität nicht aufhört, solange ich aktiv bin, wächst das Dokument weiter und weiter.

Das offensichtlichste Problem dabei ist, dass Sie möglicherweise das Dokumentlimit von 16 MB erreichen, aber darüber sollten Sie sich überhaupt keine Sorgen machen. Ein Dokument, das kontinuierlich wächst, verursacht jedes Mal höhere Kosten, wenn es auf die Festplatte verschoben werden muss. Selbst wenn Sie Maßnahmen ergreifen, um die Auswirkungen der Fragmentierung zu verringern, sind Ihre Schreibvorgänge insgesamt unnötig lang und beeinträchtigen die Gesamtleistung Ihrer gesamten Anwendung.

Sie können noch etwas tun, das die Leistung Ihrer Anwendung vollständig beeinträchtigt, und zwar die Indizierung dieses ständig wachsenden Arrays. Dies bedeutet, dass jedes Mal, wenn das Dokument mit diesem Array verschoben wird, die Anzahl der Indexeinträge, die aktualisiert werden müssen, direkt proportional zur Anzahl der indizierten Werte in diesem Dokument ist. Je größer das Array, desto größer wird diese Anzahl Sein.

Ich möchte nicht, dass Sie davon abgehalten werden, Arrays zu verwenden, wenn sie gut zum Datenmodell passen - sie sind eine leistungsstarke Funktion des Datenmodells der Dokumentendatenbank, aber wie alle leistungsstarken Tools muss es unter den richtigen Umständen verwendet werden und es sollte mit Vorsicht verwendet werden.

efkan
quelle
3
Dies sollte die beste Antwort sein. Es ist ein Knaller auf das Geld. MongoDBs eigene White Papers sagen so ziemlich dasselbe.
Jay Edwards
Dieser Artikel über das Bucket Pattern ergänzt das, worüber Asya gut spricht. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern Ich denke, das SubDoc-Schema in OPs Frage würde gut mit dem Bucket-Muster funktionieren.
plong0
13

Erstellen Sie grundsätzlich eine Variable nestedDovund fügen Sie sie hier einname: [nestedDov]

Einfache Version:

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});

JSON-Beispiel

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}

Beispiel:

Geben Sie hier die Bildbeschreibung ein

Wayne Chiu
quelle
1
Damit wird die Frage nach der Leistung überhaupt nicht beantwortet.
Cyberwombat
Ich habe ein bisschen bearbeitet, um mehr Sinn zu machen. Was denken Sie?
Wayne Chiu
3
Die Frage ist nicht, wie verschachtelte Schemas erstellt werden sollen. Es ist eine Diskussion darüber, ob Mongoose mit verschachtelten Schemas oder eingebetteten Unterdokumenten leistungsfähiger ist. Grundsätzlich sprechen wir von Benchmarks oder Sorten oder Randfällen, in denen Mungo einander vorzieht. Und wie in der ausgewählten Antwort erwähnt, scheint es zumindest ab V3 keinen Unterschied zu machen.
Cyberwombat
17
Vielleicht funktioniert es nicht für das OP, aber ich fand das sehr hilfreich. Vielen Dank.
Gene Higgins
Dies ist gut, wenn alle 3 Schemas in einer .js-Datei deklariert sind. Wie können wir damit umgehen, wenn wir in 3 verschiedenen .js-Dateien deklariert sind?
Satyam
9

Ich denke, dies wird an anderer Stelle durch mehrere Posts auf SO behandelt.

Nur ein paar:

Der große Schlüssel ist, dass es hier keine einzige Antwort gibt, sondern nur eine Reihe ziemlich komplexer Kompromisse.

Gates VP
quelle
3
Vielleicht formuliere ich meine Frage nicht richtig - Dies ist keine Frage, wie ich meine Datenbank strukturieren soll, sondern die Interna der Verwendung eines Teilschemas, anstatt nur das Array in eine tiefere Ebene zu schreiben. Meine Hauptursache für die Verwendung eines Teilschemas ist, dass ich benutzerdefinierte Schematypen verwenden und validieren lassen kann - etwas, das mit verschachtelten Arrays nicht funktioniert (aus einer früheren Frage, die ich zu SO hatte). Soweit ich das beurteilen kann, ist ein Subdoc so ziemlich dasselbe wie ein verschachteltes Array - ich kenne die Interna davon einfach nicht -, wenn seine Verwendung zu Leistungsproblemen oder Ähnlichem führen würde.
Cyberwombat
0

Es gibt einen Unterschied zwischen den beiden:

  • Die Verwendung eines verschachtelten Schemas ist hilfreich für die Validierung.

  • Verschachteltes Schema kann in anderen Schemas wiederverwendet werden.

  • Verschachteltes Schema Fügen Sie dem Unterdokument das Feld '_id' hinzu, es sei denn, Sie haben "_id: false" verwendet.
Ahmad Zahabi
quelle