MongoDB: questo è un buon schema di progettazione?

3

Sto lavorando a un'app Meteor che consente agli utenti di creare eventi e assegnare loro membri dell'equipaggio. Ho suonato in giro con MongoDB prima e ho fatto alcune esperienze lungo la strada, dove ad esempio il mio primo tentativo è andato fuori bordo con oggetti incorporati e rapidamente diventato lento e difficile da mantenere. Diverse persone hanno quindi suggerito di provare un approccio di design più tradizionale ed è quello che ho fatto questa volta.

Ho suddiviso le mie raccolte con i riferimenti manuali in mente,

Eventi

_id : ObjectID,
propA: "Some prop",
propB: "Some other prop",
employees: [
    {employee_id: ObjectID, crew_id: ObjectID},
    {employee_id: ObjectID, crew_id: ObjectID},
]

I dipendenti

_id : ObjectID,
propA: "Some prop",
crew_id: ObjectID

Crews

_id : ObjectID,
propA: "Some prop"

Il ragionamento è che la raccolta di eventi diventerà piuttosto sostanziale durante il ciclo di vita delle applicazioni e quindi ritengo che la duplicazione sia una cosa negativa. Un'altra caratteristica degna di nota è che un dipendente deve appartenere a un certo equipaggio, ma su un evento reale può lavorare in qualsiasi equipaggio.

Inizialmente ero abbastanza contento di questo progetto, ma ho comunque riscontrato alcuni problemi che mi hanno portato qui.

1) Quando elenco un evento devo unire manualmente i ref per mostrare le proprietà effettive dei dipendenti e degli equipaggi (come il nome), è un po 'noioso, ma ciò che mi preoccupa di più sono le prestazioni: piuttosto che eseguire una query Devo eseguire tre (prima ottenere l'evento, quindi passare attraverso l'array di dipendenti e poi unire il dipendente con la collezione Employee e infine unirmi all'equipaggio con la collezione Crew).

2) Il mio problema più grande finora è quello che credo sia noto come deep querying. Prima di aggiungere un dipendente a un evento, devo sapere se è già stato assegnato, quindi è necessario interrogare la raccolta Eventi per un evento con un determinato ID e trovare anche la verifica se l'ID dipendente impiegato esiste nell'array dei dipendenti. Finora non sono stato in grado di farlo in una singola query.

Quindi la mia domanda si riduce a questo. Il mio design è bello così com'è o dovrei cambiarlo dato i miei casi d'uso? O in alternativa, se mantengo il mio attuale design, come dovrei affrontare il problema 1 e 2 (vale a dire, i join manuali e i ref vanno bene, ma le prestazioni sono un vero e proprio stop-stop possibile?).

    
posta KG Christensen 16.12.2013 - 14:07
fonte

2 risposte

10

Perché stai utilizzando un database non relazionale in questo caso?

Hai detto:

When listing an event I have to manually join refs in order to show the actual properties of the employees and crews (such as name), it's a bit tedious but what worries me most is performance:

e

My biggest problem so far though is what I believe is known as deep querying

[ enfasi aggiunta ]

Hai già alcuni indicatori forti che un database non relazionale non è adatto alle tue esigenze. Utilizzare invece un database relazionale. Cambiando lo schema in questo caso, non verranno compensati i problemi all'interno del toolset.

Prova il tuo progetto con un database relazionale e verifica se i problemi scompaiono. Ciò fornirà la prova che ti serve che tu non abbia scelto lo strumento giusto da usare in questo caso.

In un commento, hai aggiunto che sei bloccato con questo particolare ambiente e stai cercando schemi di schemi alternativi.

Da quello che ho visto, il modo migliore per compensare in questo caso è denormalizzare tutte le tue tabelle. Invece di 3 tavoli, avrai 1 tavolo dove disponi l'equipaggio e i dipendenti per evento.

Questo solleva alcune sfide assicurandoti di non assegnare due dipendenti, ma avere un flag di stato per l'evento dovrebbe aiutarti a controllarlo. In sostanza, esegui una query per verificare se l'ABC dipendente è già assegnato a un evento (o equipaggio) ancora attivo.

    
risposta data 16.12.2013 - 16:47
fonte
-1

Sono d'accordo con la risposta di GlenH7 - probabilmente vuoi un DB relazionale.

Detto questo:

1) When listing an event I have to manually join refs in order to show the actual properties of the employees and crews (such as name) [...] what worries me most is performance: [...]

Considera la possibilità di memorizzare nella cache i dipendenti e gli equipaggi: non ne avrai molti attivi e questo dovrebbe risolvere il problema delle prestazioni.

2) Before adding an employee to an event I have to know if he/she is already assigned, thus requiring to query the Events collection for an Event with a given ID and also find check if the given Employee ID exists in the employee array.

Potresti effettivamente usare un po 'di normalizzazione qui:

Eventi:

_id : ObjectID,
propA: "Some prop",
propB: "Some other prop",

Eventi-Dipendenti:

_id : ObjectID,
eventId: "_id of event",
employeeId: "_id of employee",
event_start: "denormalized event data for querying employee availability",

Queste sono due query per recuperare le informazioni complete sull'evento (presupponendo la cache dei dipendenti / membri dell'equipaggio), ma una singola query per vedere chi è disponibile in un dato momento. Puoi persino fare in modo che una query coperta come un indice con due ID e date rimangano piccoli (ish).

    
risposta data 16.12.2013 - 19:55
fonte

Leggi altre domande sui tag