Come Progettare uno Schema di Documento in MongoDB

L’autore ha selezionato il Fondo per Internet Aperto/Libertà di Parola per ricevere una donazione nell’ambito del programma Scrivi per Donazioni.

Introduzione

Se hai molta esperienza nel lavoro con database relazionali, può essere difficile superare i principi del modello relazionale, come pensare in termini di tabelle e relazioni. Database orientati ai documenti come MongoDB rendono possibile liberarsi dalla rigidità e dalle limitazioni del modello relazionale. Tuttavia, la flessibilità e la libertà che derivano dalla possibilità di memorizzare documenti autodescrittivi nel database possono portare ad altri tranelli e difficoltà.

Questo articolo concettuale descrive cinque linee guida comuni relative alla progettazione dello schema in un database orientato ai documenti e sottolinea varie considerazioni che si dovrebbero fare quando si modellano le relazioni tra i dati. Esploreremo anche diverse strategie che si possono adottare per modellare tali relazioni, inclusa l’integrazione di documenti all’interno di array e l’uso di riferimenti tra figli e genitori, nonché quando queste strategie sarebbero più appropriate da utilizzare.

Linea guida 1 — Conservare insieme ciò che deve essere accessibile insieme

In un tipico database relazionale, i dati sono conservati in tabelle, e ogni tabella è costruita con un elenco fisso di colonne che rappresentano vari attributi che compongono un’entità, oggetto o evento. Ad esempio, in una tabella che rappresenta gli studenti di un’università, potresti trovare colonne che contengono il nome, il cognome, la data di nascita e un numero di identificazione univoco di ciascuno studente.

Tipicamente, ogni tabella rappresenta un singolo soggetto. Se volessi memorizzare informazioni sulle attuali studi di uno studente, sulle borse di studio o sull’educazione precedente, potrebbe avere senso conservare quei dati in una tabella separata da quella che contiene le sue informazioni personali. Potresti quindi collegare queste tabelle per indicare che esiste una relazione tra i dati in ciascuna di esse, indicando che le informazioni che contengono hanno una connessione significativa.

Ad esempio, una tabella che descrive lo stato di borsa di studio di ogni studente potrebbe fare riferimento agli studenti tramite il loro numero di ID studente, ma non memorizzerebbe direttamente il nome o l’indirizzo dello studente, evitando così la duplicazione dei dati. In un caso del genere, per recuperare informazioni su uno studente con tutti i dettagli relativi ai suoi account sui social media, alla sua educazione precedente e alle borse di studio, una query dovrebbe accedere a più di una tabella alla volta e poi compilare i risultati provenienti da diverse tabelle in uno.

Questo metodo di descrizione delle relazioni attraverso riferimenti è noto come modello di dati normalizzato. Memorizzare i dati in questo modo – utilizzando oggetti separati e concisi collegati tra loro – è anche possibile nei database orientati ai documenti. Tuttavia, la flessibilità del modello di documento e la libertà che offre di memorizzare documenti incorporati e array all’interno di un singolo documento significa che è possibile modellare i dati in modo diverso rispetto a quanto si potrebbe fare in un database relazionale.

Il concetto sottostante per modellare i dati in un database orientato ai documenti è di “memorizzare insieme ciò che verrà acceduto insieme”.” Approfondendo ulteriormente l’esempio dello studente, supponiamo che la maggior parte degli studenti di questa scuola abbia più di un indirizzo email. A causa di ciò, l’università desidera avere la possibilità di memorizzare più indirizzi email con le informazioni di contatto di ogni studente.

In un caso come questo, un documento di esempio potrebbe avere una struttura simile a questa:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ]
}

Si noti che questo documento di esempio contiene un elenco incorporato di indirizzi email.

La rappresentazione di più di un singolo soggetto all’interno di un unico documento caratterizza un modello di dati denormalizzato. Permette alle applicazioni di recuperare e manipolare tutti i dati rilevanti per un dato oggetto (qui, uno studente) in una sola volta senza la necessità di accedere a più oggetti e collezioni separate. Ciò garantisce anche l’atomicità delle operazioni su tale documento senza dover utilizzare transazioni multi-documento per garantire l’integrità.

L’archiviazione insieme di ciò che deve essere accessibile insieme utilizzando documenti incorporati è spesso il modo ottimale per rappresentare i dati in un database orientato ai documenti. Nelle seguenti linee guida, imparerai come diverse relazioni tra oggetti, come relazioni uno-a-uno o uno-a-molti, possono essere modellate al meglio in un database orientato ai documenti.

Linea guida 2 — Modellare Relazioni Uno-a-Uno con Documenti Incorporati

Una relazione uno-a-uno rappresenta un’associazione tra due oggetti distinti in cui un oggetto è connesso esattamente con uno di un altro tipo.

Continuando con l’esempio dello studente della sezione precedente, ogni studente ha solo una tessera ID valida in un dato momento. Una carta non appartiene mai a più studenti e nessuno studente può avere più carte d’identità. Se dovessi memorizzare tutti questi dati in un database relazionale, sarebbe probabile che abbia senso modellare la relazione tra studenti e le loro carte ID memorizzando i record degli studenti e i record delle carte ID in tabelle separate che sono collegate attraverso riferimenti.

Un metodo comune per rappresentare tali relazioni in un database di documenti è utilizzare documenti incorporati. Ad esempio, il seguente documento descrive uno studente di nome Sammy e la sua tessera ID:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "id_card": {
        "number": "123-1234-123",
        "issued_on": ISODate("2020-01-23"),
        "expires_on": ISODate("2020-01-23")
    }
}

Nota che invece di un singolo valore, il campo id_card di questo documento di esempio contiene un documento incorporato che rappresenta la carta d’identità dello studente, descritta da un numero ID, la data di emissione della carta e la data di scadenza della carta. La carta d’identità diventa essenzialmente parte del documento che descrive lo studente Sammy, anche se è un oggetto separato nella realtà. Solitamente, strutturare lo schema del documento in questo modo in modo da poter recuperare tutte le informazioni correlate attraverso una singola query è una scelta solida.

Le cose diventano meno intuitive se si incontrano relazioni che collegano un oggetto di un tipo con molti oggetti di un altro tipo, come gli indirizzi email di uno studente, i corsi che frequenta o i messaggi che pubblica sul forum del consiglio studentesco. Nei prossimi consigli, utilizzerai questi esempi di dati per imparare diversi approcci per lavorare con relazioni uno-a-molti e molti-a-molti.

Linee guida 3 — Modellare relazioni uno-a-pochi con documenti incorporati

Quando un oggetto di un tipo è correlato a più oggetti di un altro tipo, può essere descritto come una relazione uno-a-molti. Uno studente può avere più indirizzi email, un’auto può avere numerose parti o un ordine di acquisto può consistere di più articoli. Ognuno di questi esempi rappresenta una relazione uno-a-molti.

Sebbene il modo più comune per rappresentare una relazione uno-a-uno in un database di documenti sia attraverso un documento incorporato, ci sono diversi modi per modellare relazioni uno-a-molti in uno schema di documenti. Tuttavia, quando si considerano le opzioni per modellare al meglio queste relazioni, ci sono tre proprietà della relazione data che si dovrebbero considerare:

  • Cardinalità: Cardinalità è la misura del numero di elementi individuali in un dato insieme. Ad esempio, se una classe ha 30 studenti, si potrebbe dire che quella classe ha una cardinalità di 30. In una relazione uno-a-molti, la cardinalità può essere diversa in ogni caso. Uno studente potrebbe avere un solo indirizzo email o più. Potrebbero essere iscritti a poche classi o potrebbero avere un orario completamente pieno. In una relazione uno-a-molti, la dimensione di “molti” influenzerà come potresti modellare i dati.
  • Accesso indipendente: Alcuni dati correlati saranno raramente, se non mai, accessibili separatamente dall’oggetto principale. Ad esempio, potrebbe essere insolito recuperare l’indirizzo email di uno studente senza altri dettagli dello studente. D’altra parte, i corsi di un’università potrebbero dover essere accessibili e aggiornati individualmente, indipendentemente dallo studente o dagli studenti che sono iscritti a parteciparvi. Se mai accederete a un documento correlato da solo influenzerà anche come potreste modellare i dati.
  • Se la relazione tra i dati è rigorosamente una relazione uno-a-molti: Considerate i corsi che uno studente partecipa in un’università. Dal punto di vista dello studente, può partecipare a più corsi. In superficie, questo potrebbe sembrare una relazione uno-a-molti. Tuttavia, i corsi universitari sono raramente frequentati da un solo studente; più spesso, più studenti frequentano la stessa classe. In casi come questo, la relazione in questione non è realmente una relazione uno-a-molti, ma una relazione molti-a-molti, e quindi adottereste un approccio diverso per modellare questa relazione rispetto a una relazione uno-a-molti.

Immaginate di decidere come memorizzare gli indirizzi email degli studenti. Ogni studente può avere più indirizzi email, come uno per il lavoro, uno per uso personale e uno fornito dall’università. Un documento che rappresenta un singolo indirizzo email potrebbe assumere una forma simile a questa:

{
    "email": "[email protected]",
    "type": "work"
}

In termini di cardinalità, ci saranno solo alcuni indirizzi email per ogni studente, poiché è improbabile che uno studente abbia dozzine — per non parlare di centinaia — di indirizzi email. Pertanto, questa relazione può essere caratterizzata come una relazione uno-a-pochi, che è una ragione convincente per incorporare gli indirizzi email direttamente nel documento dello studente e memorizzarli insieme. Non si corre il rischio che l’elenco degli indirizzi email cresca indefinitamente, il che renderebbe il documento grande e poco efficiente da utilizzare.

Nota: È importante essere consapevoli di alcuni inconvenienti associati all’archiviazione dei dati in array. Ad esempio, un singolo documento MongoDB non può superare i 16MB di dimensione. Sebbene sia possibile e comune incorporare più documenti utilizzando campi array, se l’elenco degli oggetti cresce incontrollabilmente, il documento potrebbe raggiungere rapidamente questo limite di dimensione. Inoltre, l’archiviazione di una grande quantità di dati all’interno di array incorporati ha un grande impatto sulle prestazioni delle query.

L’incorporazione di più documenti in un campo array sarà probabilmente adatta in molte situazioni, ma è bene sapere che potrebbe non essere sempre la soluzione migliore.

Per quanto riguarda l’accesso indipendente, è probabile che gli indirizzi email non vengano acceduti separatamente dallo studente. Di conseguenza, non c’è un chiaro incentivo per memorizzarli come documenti separati in una collezione separata. Questa è un’altra ragione convincente per incorporarli all’interno del documento dello studente.

L’ultima cosa da considerare è se questa relazione è davvero una relazione uno-a-molti anziché una relazione molti-a-molti. Poiché un indirizzo email appartiene a una singola persona, è ragionevole descrivere questa relazione come una relazione uno-a-molti (o, forse più accuratamente, una relazione uno-a-pochi) anziché una relazione molti-a-molti.

Queste tre ipotesi suggeriscono che incorporare i vari indirizzi email degli studenti all’interno degli stessi documenti che descrivono gli studenti stessi sarebbe una buona scelta per archiviare questo tipo di dati. Un documento di esempio di uno studente con indirizzi email incorporati potrebbe avere questa forma:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ]
}

Utilizzando questa struttura, ogni volta che recuperi un documento di uno studente, recupererai anche gli indirizzi email incorporati nella stessa operazione di lettura.

Se modelli una relazione di tipo uno-a-pochi, dove i documenti correlati non devono essere accessibili in modo indipendente, incorporare i documenti direttamente in questo modo è solitamente auspicabile, poiché può ridurre la complessità dello schema.

Come accennato in precedenza, tuttavia, incorporare i documenti in questo modo non è sempre la soluzione ottimale. La prossima sezione fornisce maggiori dettagli sui motivi per cui questo potrebbe essere il caso in alcuni scenari e illustra come utilizzare i riferimenti ai figli come alternativa per rappresentare le relazioni in un database di documenti.

Linea guida 4 — Modellazione delle relazioni uno-a-molti e molti-a-molti con riferimenti figlio

La natura della relazione tra gli studenti e i loro indirizzi email ha influenzato come tale relazione potesse essere modellata al meglio in un database di documenti. Ci sono alcune differenze tra questa e la relazione tra gli studenti e i corsi a cui partecipano, quindi il modo in cui modelli le relazioni tra gli studenti e i loro corsi sarà diverso anche lui.

Un documento che descrive un singolo corso a cui uno studente partecipa potrebbe seguire una struttura come questa:

{
    "name": "Physics 101",
    "department": "Department of Physics",
    "points": 7
}

Supponiamo che tu abbia deciso fin dall’inizio di utilizzare documenti incorporati per memorizzare informazioni sui corsi di ciascuno studente, come in questo esempio:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ],
    "courses": [
        {
            "name": "Physics 101",
            "department": "Department of Physics",
            "points": 7
        },
        {
            "name": "Introduction to Cloud Computing",
            "department": "Department of Computer Science",
            "points": 4
        }
    ]
}

Questo sarebbe un documento MongoDB perfettamente valido e potrebbe benissimo servire lo scopo, ma considera le tre proprietà delle relazioni che hai imparato nella linea guida precedente.

La prima è la cardinalità. Uno studente probabilmente manterrà solo alcuni indirizzi email, ma può frequentare più corsi durante i suoi studi. Dopo diversi anni di frequenza, potrebbero esserci dozzine di corsi a cui lo studente ha partecipato. Inoltre, seguiranno questi corsi insieme a molti altri studenti che a loro volta frequentano il loro insieme di corsi nel corso degli anni di frequenza.

Se hai deciso di incorporare ogni corso come nell’esempio precedente, il documento dello studente diventerebbe rapidamente ingestibile. Con una cardinalità più alta, l’approccio del documento incorporato diventa meno persuasivo.

La seconda considerazione è l’accesso indipendente. A differenza degli indirizzi email, è ragionevole presumere che ci saranno casi in cui sarà necessario recuperare informazioni sui corsi universitari in modo autonomo. Ad esempio, supponiamo che qualcuno abbia bisogno di informazioni sui corsi disponibili per preparare una brochure di marketing. Inoltre, è probabile che i corsi debbano essere aggiornati nel tempo: il professore che insegna il corso potrebbe cambiare, il suo orario potrebbe fluttuare o i suoi prerequisiti potrebbero dover essere aggiornati.

Se dovessi archiviare i corsi come documenti incorporati all’interno dei documenti degli studenti, recuperare l’elenco di tutti i corsi offerti dall’università diventerebbe problematico. Inoltre, ogni volta che un corso necessita di un aggiornamento, dovresti passare attraverso tutti i record degli studenti e aggiornare le informazioni del corso ovunque. Entrambi sono buoni motivi per archiviare i corsi separatamente e non incorporarli completamente.

La terza cosa da considerare è se la relazione tra studente e un corso universitario è effettivamente uno-a-molti o invece molti-a-molti. In questo caso, è quest’ultimo, poiché più di uno studente può frequentare ogni corso. La cardinalità di questa relazione e gli aspetti di accesso indipendente suggeriscono contro l’incorporazione di ogni documento del corso, principalmente per ragioni pratiche come facilità di accesso e aggiornamento. Considerando la natura molti-a-molti della relazione tra corsi e studenti, potrebbe avere senso archiviare i documenti dei corsi in una collezione separata con identificatori unici propri.

I documenti che rappresentano le classi in questa collezione separata potrebbero avere una struttura simile a questi esempi:

{
    "_id": ObjectId("61741c9cbc9ec583c836170a"),
    "name": "Physics 101",
    "department": "Department of Physics",
    "points": 7
},
{
    "_id": ObjectId("61741c9cbc9ec583c836170b"),
    "name": "Introduction to Cloud Computing",
    "department": "Department of Computer Science",
    "points": 4
}

Se decidi di memorizzare informazioni sul corso in questo modo, dovrai trovare un modo per collegare gli studenti a questi corsi in modo da sapere quali studenti frequentano quali corsi. Nei casi come questo, dove il numero di oggetti correlati non è eccessivamente grande, soprattutto con relazioni molti-a-molti, un modo comune di procedere è utilizzare riferimenti figlio.

Con i riferimenti figlio, il documento di uno studente farà riferimento agli identificatori degli oggetti dei corsi che lo studente frequenta in un array incorporato, come in questo esempio:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ],
    "courses": [
        ObjectId("61741c9cbc9ec583c836170a"),
        ObjectId("61741c9cbc9ec583c836170b")
    ]
}

Nota che questo documento di esempio ha ancora un campo courses che è anche un array, ma invece di incorporare documenti di corso completi come nell’esempio precedente, vengono incorporati solo gli identificatori che fanno riferimento ai documenti di corso nella collezione separata. Ora, quando si recupera un documento di studente, i corsi non saranno immediatamente disponibili e dovranno essere interrogati separatamente. D’altra parte, è immediatamente noto quali corsi recuperare. Inoltre, nel caso in cui i dettagli di un corso debbano essere aggiornati, è necessario modificare solo il documento del corso stesso. Tutti i riferimenti tra studenti e i loro corsi rimarranno validi.

Nota: Non esiste una regola ferma per quando la cardinalità di una relazione è troppo grande per incorporare riferimenti figlio in questo modo. Potresti scegliere un approccio diverso a seconda della cardinalità più bassa o più alta, se è ciò che meglio si adatta all’applicazione in questione. Dopotutto, vorrai sempre strutturare i tuoi dati in modo da adattarli al modo in cui la tua applicazione li interroga e li aggiorna.

Se modelli una relazione uno-a-molti dove la quantità di documenti correlati è entro limiti ragionevoli e i documenti correlati devono essere accessibili in modo indipendente, favorisci l’archiviazione dei documenti correlati separatamente e l’incorporazione di riferimenti ai figli per collegarli.

Ora che hai imparato come utilizzare i riferimenti ai figli per indicare relazioni tra diversi tipi di dati, questa guida esporrà un concetto inverso: i riferimenti ai genitori.

Linea guida 5 — Modellare Relazioni Uno-a-Molti Illimitate con Riferimenti ai Genitori

L’uso dei riferimenti ai figli funziona bene quando ci sono troppi oggetti correlati per incorporarli direttamente all’interno del documento padre, ma la quantità è ancora entro limiti noti. Tuttavia, ci sono casi in cui il numero di documenti associati potrebbe essere illimitato e continuare a crescere nel tempo.

Ad esempio, immagina che il consiglio studentesco dell’università abbia un bacheca messaggi dove qualsiasi studente può pubblicare qualunque messaggio voglia, incluse domande sui corsi, storie di viaggio, annunci di lavoro, materiale di studio o semplicemente una chiacchierata libera. Un messaggio di esempio in questo contesto consiste in un oggetto e un corpo del messaggio:

{
    "_id": ObjectId("61741c9cbc9ec583c836174c"),
    "subject": "Books on kinematics and dynamics",
    "message": "Hello! Could you recommend good introductory books covering the topics of kinematics and dynamics? Thanks!",
    "posted_on": ISODate("2021-07-23T16:03:21Z")
}

Potresti utilizzare uno dei due approcci discussi in precedenza — incorporazione e riferimenti ai figli — per modellare questa relazione. Se decidessi di optare per l’incorporazione, il documento dello studente potrebbe assumere una forma simile a questa:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ],
    "courses": [
        ObjectId("61741c9cbc9ec583c836170a"),
        ObjectId("61741c9cbc9ec583c836170b")
    ],
    "message_board_messages": [
        {
            "subject": "Books on kinematics and dynamics",
            "message": "Hello! Could you recommend good introductory books covering the topics of kinematics and dynamics? Thanks!",
            "posted_on": ISODate("2021-07-23T16:03:21Z")
        },
        . . .
    ]
}

Tuttavia, se uno studente è prolifico nella scrittura di messaggi, il loro documento diventerà rapidamente incredibilmente lungo e potrebbe facilmente superare il limite di dimensione di 16MB, quindi la cardinalità di questa relazione suggerisce contro l’embedding. Inoltre, i messaggi potrebbero dover essere accessibili separatamente dallo studente, come potrebbe essere il caso se la pagina del forum è progettata per mostrare i messaggi più recenti pubblicati dagli studenti. Questo suggerisce anche che l’embedding non è la scelta migliore per questo scenario.

Nota: Dovresti anche considerare se i messaggi del forum sono frequentemente accessibili quando si recupera il documento dello studente. Se non lo sono, avere tutti incorporati all’interno di quel documento comporterebbe una penalità di prestazioni quando si recupera e si manipola questo documento, anche quando l’elenco dei messaggi non verrebbe utilizzato spesso. L’accesso infrequente dei dati correlati è spesso un altro indizio che non dovresti incorporare documenti.

Ora considera l’uso di riferimenti figlio invece di incorporare documenti completi come nell’esempio precedente. I singoli messaggi sarebbero memorizzati in una collezione separata e il documento dello studente potrebbe quindi avere la seguente struttura:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ],
    "courses": [
        ObjectId("61741c9cbc9ec583c836170a"),
        ObjectId("61741c9cbc9ec583c836170b")
    ],
    "message_board_messages": [
        ObjectId("61741c9cbc9ec583c836174c"),
        . . .
    ]
}

In questo esempio, il campo message_board_messages ora memorizza i riferimenti ai figli a tutti i messaggi scritti da Sammy. Tuttavia, cambiare l’approccio risolve solo uno dei problemi menzionati prima in quanto ora sarebbe possibile accedere ai messaggi in modo indipendente. Ma anche se la dimensione del documento dello studente crescerebbe più lentamente utilizzando l’approccio dei riferimenti ai figli, la raccolta degli identificatori degli oggetti potrebbe anche diventare ingestibile data la cardinalità illimitata di questa relazione. Dopotutto, uno studente potrebbe facilmente scrivere migliaia di messaggi durante i suoi quattro anni di studio.

In tali scenari, un modo comune per collegare un oggetto a un altro è attraverso riferimenti genitore. A differenza dei riferimenti ai figli descritti in precedenza, ora non è il documento dello studente a fare riferimento ai singoli messaggi, ma piuttosto un riferimento nel documento del messaggio che punta allo studente che l’ha scritto.

Per utilizzare i riferimenti genitore, è necessario modificare lo schema del documento del messaggio per contenere un riferimento allo studente che ha redatto il messaggio:

{
    "_id": ObjectId("61741c9cbc9ec583c836174c"),
    "subject": "Books on kinematics and dynamics",
    "message": "Hello! Could you recommend a good introductory books covering the topics of kinematics and dynamics? Thanks!",
    "posted_on": ISODate("2021-07-23T16:03:21Z"),
    "posted_by": ObjectId("612d1e835ebee16872a109a4")
}

Nota il nuovo campo posted_by che contiene l’identificatore dell’oggetto del documento dello studente. Ora, il documento dello studente non conterrà alcuna informazione sui messaggi che ha pubblicato:

{
    "_id": ObjectId("612d1e835ebee16872a109a4"),
    "first_name": "Sammy",
    "last_name": "Shark",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        },
        {
            "email": "[email protected]",
            "type": "home"
        }
    ],
    "courses": [
        ObjectId("61741c9cbc9ec583c836170a"),
        ObjectId("61741c9cbc9ec583c836170b")
    ]
}

Per recuperare l’elenco dei messaggi scritti da uno studente, si utilizzerebbe una query sulla collezione dei messaggi e si filtrerebbe contro il campo posted_by. Avere i messaggi in una collezione separata rende sicuro far crescere l’elenco dei messaggi senza influenzare nessuno dei documenti dello studente.

Nota: Quando si utilizzano riferimenti padre, creare un indice sul campo che fa riferimento al documento padre può migliorare significativamente le prestazioni delle query ogni volta che si filtra in base all’identificatore del documento padre.

Se si modella una relazione uno-a-molti dove la quantità di documenti correlati è illimitata, indipendentemente dal fatto che i documenti debbano essere accessibili in modo indipendente, generalmente si consiglia di memorizzare i documenti correlati separatamente e utilizzare riferimenti padre per collegarli al documento padre.

Conclusione

Grazie alla flessibilità dei database orientati ai documenti, determinare il modo migliore per modellare le relazioni in un database di documenti è meno una scienza rigorosa che in un database relazionale. Leggendo questo articolo, ti sei familiarizzato con l’incorporamento di documenti e l’uso di riferimenti figlio e padre per memorizzare dati correlati. Hai imparato a considerare la cardinalità delle relazioni e ad evitare array illimitati, oltre a tenere in considerazione se il documento sarà accessibile separatamente o frequentemente.

Questi sono solo alcuni suggerimenti che possono aiutarti a modellare relazioni tipiche in MongoDB, ma la progettazione dello schema del database non è una soluzione universale. Prendi sempre in considerazione la tua applicazione e il modo in cui utilizza e aggiorna i dati durante la progettazione dello schema.

Per saperne di più sul design degli schemi e sui modelli comuni per archiviare diversi tipi di dati in MongoDB, ti invitiamo a consultare la documentazione ufficiale di MongoDB su questo argomento.

Source:
https://www.digitalocean.com/community/tutorials/how-to-design-a-document-schema-in-mongodb