2014-09-07 11 views
9

Sto imparando sulla modellazione dei dati in DocumentDb. Ecco dove ho bisogno di qualche consiglioDevo denormalizzare o eseguire più query in DocumentDb?

Si prega di vedere ciò che i miei documenti sembrano come di seguito.

Qui posso seguire due approcci sia con pro che contro.

Scenario 1:

Se continuo i dati denormalizzati (vedere i miei documenti sottostanti), mantenendo le informazioni membro del team di progetto, corrispondente alla prima, cognome, e-mail, ecc nello stesso documento come il progetto, ho posso ottenere le informazioni di cui ho bisogno in una query, MA quando Jane Doe si sposa e il suo cognome cambia, dovrei aggiornare molti documenti nella collezione Progetti. Dovrei anche essere estremamente attento nel fare in modo che tutte le raccolte con documenti che contengono informazioni sui dipendenti vengano aggiornate pure. Se, ad esempio, aggiorno il nome di Jane Doe nella raccolta Progetti, ma dimentico di aggiornare la collezione TimeSheets, sarei nei guai!

Scenario 2:

Se continuo di dati in qualche modo normalizzati e mantenere solo EmployeeId nei documenti di progetto, posso quindi eseguire tre query ogni volta che voglio ottenere una lista di progetti:

  • Query 1 restituisce la lista di progetti
  • Query 2 mi fornisce EmployeeId di tutti i membri del team di progetto che compaiono nella prima query
  • Query 3 per informazioni sui dipendenti, ad esempio prima, ultima nome, email, ecc. Userei il risultato di Query 2 per eseguire questo

Posso quindi combinare tutti i dati nella mia applicazione.

Il problema qui è che DocumentDb sembra avere molte limitazioni ora. Potrei leggere centinaia di progetti con centinaia di dipendenti nei team di progetto. Sembra che non ci sia un modo efficace per ottenere tutte le informazioni sui dipendenti le cui ID appaiono nella mia seconda query. Ancora una volta, tieni presente che potrebbe essere necessario richiamare qui centinaia di informazioni sui dipendenti. Se la seguente query SQL è quella che utilizzerei per i dati dei dipendenti, potrei dover eseguire la stessa query alcune volte per ottenere tutte le informazioni di cui ho bisogno perché non penso di poter avere centinaia di istruzioni OR:

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

Capisco che DocumentDb è ancora in anteprima e alcune di queste limitazioni verranno corrette. Detto questo, come dovrei affrontare questo problema? In che modo posso archiviare/gestire in modo efficiente e recuperare tutti i dati di progetto di cui ho bisogno, incluse le informazioni sul team di progetto? Scenario 1 è una soluzione migliore o Scenario 2 o c'è una terza opzione migliore?

Ecco come sono i miei documenti. In primo luogo, il documento di progetto:

{ 
    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" } 
    ] 
} 

E qui ci sono due documenti dei dipendenti che si trovano nella collezione Dipendenti:

{ 
    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

Perché hai aggiunto mongodb qui? –

+0

Perché alla fine la domanda riguarda la modellazione dei dati nei database di documenti e voglio vedere se c'è un approccio là fuori che non vedo ancora. – Sam

+0

Sto riflettendo la stessa identica cosa, hai qualche commento/intuizione sulla tua esperienza da allora? Mi sto chiedendo di normalizzare e leggere gli utenti nel contesto (ad esempio: associato a un progetto nel tuo caso) e fare riferimento alle informazioni volatili (più di 1 query) o de-nornalizzare e possibile avere un "Aggiorna/Aggiorna dati utente" "funzione per gli amministratori di aggiornare i nomi se necessario? (Sto cercando di evitare la stored procedure se posso) –

risposta

12

credo che sei sulla strada giusta nel considerare il trade-off tra normalizzante o de-normalizzare i dati del progetto e dei dipendenti.Come si è accennato:

Scenario 1) Se si de-normalizzare il vostro modello di dati (progetti di coppia e dati dei dipendenti insieme) - si può trovare a dover aggiornamento molti progetti quando si aggiornamento un dipendente .

Scenario 2) Se si normalizzare il vostro modello di dati (disaccoppiare progetti e dei dati dei dipendenti) - dovreste interrogare per i progetti per recuperare employeeIds e poi interrogare per i dipendenti se si voleva ottenere l'elenco dei lavoratori appartenenti a un progetto.

Vorrei scegliere il trade-off appropriato in base al caso d'uso della vostra applicazione. In generale, preferisco de-normalizzare quando si ha un'applicazione di lettura intensa e si normalizza quando si ha un'applicazione di scrittura intensa.

Si noti che è possibile evitare di dover effettuare più roundtrip tra l'applicazione e il database sfruttando le procedure di archiviazione di DocumentDB (le query verranno eseguite su DocumentDB-server-side).

Ecco un esempio di procedimento serbo per il recupero di lavoratori appartenenti a una specifica ProjectID:

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); 
} 

Anche se DocumentDB supporta Limited o dichiarazioni durante l'anteprima - è ancora possibile ottenere relativamente buone prestazioni suddividendo i EmployeeID-ricerche in un sacco di query lato server asincrone.

+0

Grazie per la risposta. Ritengo che quest'ultimo approccio sia anche migliore. Ho solo bisogno di padroneggiare le stored procedure JS in DocumentDB. Grazie ancora. Apprezzo anche il codice di esempio. – Sam

Problemi correlati