2014-09-07 8 views
9

Ich lerne über Datenmodellierung in DocumentDb. Hier ist, wo ich einen Rat braucheSollte ich Denialize oder mehrere Abfragen in DocumentDb ausführen?

Bitte sehen Sie, wie meine Dokumente unten aussehen.

Ich kann hier zwei Ansätze sowohl mit Vor-und Nachteile.

Szenario 1:

Wenn ich die Daten halten denormalized (meine Dokumente weiter unten) durch Projektmitarbeiter Informationen zu halten, dh zuerst, Nachname, E-Mail usw. im selben Dokument wie das Projekt, ich kann die Informationen bekommen, die ich in einer Frage benötige ABER, wenn Jane Doe heiratet und ihr Nachname sich ändert, würde ich viele Dokumente in der Projektansammlung aktualisieren müssen. Ich muss auch sehr vorsichtig sein, um sicherzustellen, dass alle Sammlungen mit Dokumenten aktualisiert werden, die Mitarbeiterinformationen enthalten. Wenn ich zum Beispiel Jane Does Namen in der Projects-Sammlung aktualisiere, aber vergessen würde, die TimeSheets-Sammlung zu aktualisieren, wäre ich in Schwierigkeiten!

Szenario 2:

Wenn ich Daten halten etwas normalisiert und nur EmployeeId in den Projektunterlagen halten, dann kann ich drei Abfragen ausführen, wenn ich eine Projektliste erhalten möchten:

  • Abfrage 1 return projects list
  • Abfrage 2 würde mir EmployeeId aller Projektteammitglieder geben, die in der ersten Abfrage
  • Abfrage 3 für Mitarbeiterinformationen dh zuerst, zuletzt angezeigt werden Name, E-Mail, etc. Ich würde das Ergebnis von Abfrage 2 verwenden, um dieses

auszuführen Ich kann dann alle Daten in meiner Anwendung kombinieren.

Das Problem hier ist, dass DocumentDb jetzt eine Menge Einschränkungen zu haben scheint. Ich lese vielleicht Hunderte von Projekten mit Hunderten von Mitarbeitern in Projektteams. Sieht so aus, als gäbe es keine effiziente Möglichkeit, alle Mitarbeiterinformationen abzurufen, deren IDs in meiner zweiten Abfrage angezeigt werden. Bitte beachten Sie, dass ich hier möglicherweise Hunderte von Mitarbeiterinformationen abrufen muss. Wenn die folgende SQL-Abfrage für Mitarbeiterdaten verwendet wird, muss ich möglicherweise dieselbe Abfrage einige Male ausführen, um alle benötigten Informationen zu erhalten, da ich nicht glaube, dass ich Hunderte von OR-Anweisungen haben kann:

SELECT e.Id, e.firstName, e.lastName, e.emailAddress 
FROM Employees e 
WHERE e.Id = 1111 OR e.Id = 2222 

Ich verstehe, dass DocumentDb immer noch in der Vorschau ist und einige dieser Einschränkungen behoben werden. Wie soll ich dieses Problem angehen? Wie kann ich alle benötigten Projektdaten effizient speichern und verwalten - einschließlich der Projektteam-Informationen? Ist Szenario 1 eine bessere Lösung oder Szenario 2 oder gibt es eine bessere dritte Option?

So sehen meine Dokumente aus. Zunächst wird das Projektdokument:

{ 
    id: 789, 
    projectName: "My first project", 
    startDate: "9/6/2014", 
    projectTeam: [ 
     { id: 1111, firstName: "John", lastName: "Smith", position: "Sr. Engineer" }, 
     { id: 2222, firstName: "Jane", lastName: "Doe", position: "Project Manager" } 
    ] 
} 

Und hier sind zwei Mitarbeiter Dokumente, die in der Employees-Sammlung befinden:

{ 
    id: 1111, 
    firstName: "John", 
    lastName: "Smith", 
    dateOfBirth: "1/1/1967', 
    emailAddresses: [ 
     { email: "[email protected]", isPrimary: "true" }, 
     { email: "[email protected]", isPrimary: "false" } 
    ] 
}, 
{ 
    id: 2222, 
    firstName: "Jane", 
    lastName: "Doe", 
    dateOfBirth: "3/8/1975', 
    emailAddresses: [ 
     { email: "[email protected]", isPrimary: "true" } 
    ] 
} 
+0

Warum haben Sie mongodb hier hinzugefügt? –

+0

Weil sich die Frage letztendlich auf die Datenmodellierung in Dokumentendatenbanken bezieht, und ich möchte sehen, ob es einen Ansatz gibt, den ich noch nicht sehe. – Sam

+0

Ich denke über genau das gleiche nach, hast du irgendeinen Kommentar/Einblick auf deine Erfahrung seitdem? Ich wundere mich, entweder die Benutzer im Kontext zu normalisieren und zu lesen (zB: assoziiert mit einem Projekt in Ihrem Fall) und referenzieren die flüchtigen Informationen dort (mehr als 1 Abfrage) oder de-nornalise und möglicherweise ein "Aktualisieren/Aktualisieren von Benutzerdaten "Funktion für Admins, um die Namen bei Bedarf zu aktualisieren? (Ich versuche, mich von der gespeicherten Prozedur fernzuhalten, wenn ich kann) –

Antwort

12

Ich glaube, Sie auf dem richtigen Weg sind in den Kompromissen zwischen Normalisierungs Berücksichtigung oder Entnormalisierung Ihrer Projekt- und Mitarbeiterdaten.Wie Sie erwähnt haben:

Szenario 1) Wenn Sie de-normalisieren Ihr Datenmodell (Paar Projekte und Mitarbeiterdaten zusammen) - Sie können sich finden, zu Update mit viele Projekte, wenn Sie Update Mitarbeiter .

Szenario 2) Wenn Sie normalisieren Ihr Datenmodell (entkoppeln Projekte und Mitarbeiterdaten) - Sie würden abfragen müssen, um für Projekte employeeIds abzurufen und dann für die Mitarbeiter abfragen, wenn Sie die Liste der Mitarbeiter, die bekommen wollte ein Projekt.

Ich würde die entsprechende Abwägung für den Anwendungsfall Ihrer Anwendung wählen. Im Allgemeinen bevorzuge ich eine De-Normalisierung, wenn Sie eine rechenintensive Anwendung haben, und eine Normalisierung, wenn Sie eine schreibintensive Anwendung haben.

Beachten Sie, dass Sie vermeiden können, mehrere Roundtrips zwischen Ihrer Anwendung und der Datenbank durchzuführen, indem Sie die Speichervorgänge von DocumentDB nutzen (Abfragen werden auf DocumentDB-Server-Seite ausgeführt).

Hier ist ein Beispiel Speichervorgang für die Mitarbeiter, die zu einem bestimmten projectId Abrufen:

function(projectId) { 
    /* the context method can be accessed inside stored procedures and triggers*/ 
    var context = getContext(); 
    /* access all database operations - CRUD, query against documents in the current collection */ 
    var collection = context.getCollection(); 
    /* access HTTP response body and headers from the procedure */ 
    var response = context.getResponse(); 

    /* Callback for processing query on projectId */ 
    var projectHandler = function(documents) { 
    var i; 
    for (i = 0; i < documents[0].projectTeam.length; i++) { 
     // Query for the Employees 
     queryOnId(documents[0].projectTeam[i].id, employeeHandler); 
    } 
    }; 

    /* Callback for processing query on employeeId */ 
    var employeeHandler = function(documents) { 
    response.setBody(response.getBody() + JSON.stringify(documents[0])); 
    }; 

    /* Query on a single id and call back */ 
    var queryOnId = function(id, callbackHandler) { 
    collection.queryDocuments(collection.getSelfLink(), 
     'SELECT * FROM c WHERE c.id = \"' + id + '\"', {}, 
     function(err, documents) { 
     if (err) { 
      throw new Error('Error' + err.message); 
     } 
     if (documents.length < 1) { 
      throw 'Unable to find id'; 
     } 
     callbackHandler(documents); 
     } 
    ); 
    }; 

    // Query on the projectId 
    queryOnId(projectId, projectHandler); 
} 

Obwohl DocumentDB unterstützt begrenzt OR-Anweisungen während der Vorschau - Sie können immer noch relativ gute Leistung erhalten, indem die employeeId-Lookups Aufteilung in eine Reihe von asynchronen serverseitigen Abfragen.

+0

Vielen Dank für Ihre Antwort. Ich denke, der letztere Ansatz ist auch besser. Ich muss nur JS gespeicherte Prozeduren in DocumentDB zu meistern. Danke noch einmal. Ich schätze das Codebeispiel auch. – Sam