MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB - Crea una relazione

Per creare una relazione in MongoDB, incorpora un documento BSON all'interno di un altro o fai riferimento ad esso da un altro.

I database MongoDB funzionano in modo diverso rispetto ai database relazionali. Questo vale anche per le relazioni.

In MongoDB, puoi creare una relazione utilizzando uno dei due metodi seguenti:

  • Documenti incorporati.
  • Documenti referenziati.

Il metodo che utilizzi dipenderà dai dati e da come intendi interrogarli.

Relazioni integrate

Con MongoDB puoi incorporare documenti all'interno di documenti. Pertanto, un singolo documento può contenere le proprie relazioni.

In effetti, abbiamo già creato una relazione utilizzando questo metodo quando abbiamo creato un documento per la prima volta.

Relazione uno-a-uno

Una relazione uno-a-uno è dove il documento genitore ha un figlio e il figlio ha un genitore.

Ad esempio, una regola aziendale potrebbe dire che un artista può avere un solo indirizzo e che l'indirizzo può appartenere a un solo artista.

Il codice seguente crea una relazione uno-a-uno, incorporata nel documento.

db.artists.insert(
    {
        _id : 2,
        artistname : "Prince",
        address :   {
                        street : "Audubon Road",
                        city : "Chanhassen",
                        state : "Minnesota",
                        country : "United States"
                    }
    }
)

Risultato:

WriteResult({ "nInserted" : 1 })

Relazione uno-a-molti

Un uno-a-molti la relazione è dove il documento principale può avere molti documenti secondari, ma i documenti secondari possono avere solo un documento principale.

Quindi, un'altra regola aziendale potrebbe dire che un artista può avere molti album, ma un album può appartenere solo a un artista.

L'esecuzione del codice seguente creerà una relazione uno-a-molti:

db.artists.insert(
    {
        _id : 3,
        artistname : "Moby",
        albums : [
                    {
                        album : "Play",
                        year : 1999,
                        genre : "Electronica"
                    }, 
                    {
                        album : "Long Ambients 1: Calm. Sleep.",
                        year : 2016,
                        genre : "Ambient"
                    }
                ]
    }
)

Risultato:

WriteResult({ "nInserted" : 1 })

Relazioni con riferimento ai documenti

È possibile utilizzare un riferimento al documento per creare una relazione. Invece di incorporare il documento figlio nel documento padre (come abbiamo fatto sopra), separi il documento figlio nel suo documento autonomo.

Quindi potremmo farlo:

Documento genitore

db.artists.insert(
    {
        _id : 4,
        artistname : "Rush"
    }
)

Documenti figlio

Inseriamo 3 documenti figlio, uno per ogni membro della band:

db.musicians.insert(
    {
        _id : 9,
        name : "Geddy Lee",
        instrument : [ "Bass", "Vocals", "Keyboards" ],
        artist_id : 4
    }
)
db.musicians.insert(
    {
        _id : 10,
        name : "Alex Lifeson",
        instrument : [ "Guitar", "Backing Vocals" ],
        artist_id : 4
    }
)
db.musicians.insert(
    {
        _id : 11,
        name : "Neil Peart",
        instrument : "Drums",
        artist_id : 4
    }
)

Interrogazione della relazione

Dopo aver inserito i due documenti precedenti, puoi usare $lookup per eseguire un join esterno sinistro sulle due raccolte.

Questo, insieme a aggregate() metodo e $match per specificare l'artista specifico che ti interessa, restituirà i documenti genitore e figlio in uno.

db.artists.aggregate([
    {
      $lookup:
        {
          from: "musicians",
          localField: "_id",
          foreignField: "artist_id",
          as: "band_members"
        }
   },
   { $match : { artistname : "Rush" } }
]).pretty()

Risultato:

{
	"_id" : 4,
	"artistname" : "Rush",
	"band_members" : [
		{
			"_id" : 9,
			"name" : "Geddy Lee",
			"instrument" : [
				"Bass",
				"Vocals",
				"Keyboards"
			],
			"artist_id" : 4
		},
		{
			"_id" : 10,
			"name" : "Alex Lifeson",
			"instrument" : [
				"Guitar",
				"Backing Vocals"
			],
			"artist_id" : 4
		},
		{
			"_id" : 11,
			"name" : "Neil Peart",
			"instrument" : "Drums",
			"artist_id" : 4
		}
	]
}

Puoi vedere che i primi due campi provengono dalla raccolta degli artisti e il resto dalla raccolta dei musicisti.

Quindi, se interroghi solo la collezione di artisti da sola:

db.artists.find( { artistname : "Rush" } )

Otterresti solo questo:

{ "_id" : 4, "artistname" : "Rush" }

Non vengono restituiti dati correlati.

Quando utilizzare i documenti incorporati rispetto ai documenti di riferimento

Entrambi i metodi per creare relazioni hanno i loro pro e contro. A volte potresti utilizzare documenti incorporati e altre volte utilizzerai documenti referenziati.

Quando utilizzare le relazioni incorporate

Uno dei principali vantaggi dell'utilizzo del metodo della relazione incorporata è rappresentato dalle prestazioni. Quando la relazione è incorporata nel documento, le query verranno eseguite più velocemente che se fossero distribuite su più documenti. MongoDB deve restituire solo un documento, invece di unire più documenti per recuperare le relazioni. Ciò può fornire un notevole aumento delle prestazioni, soprattutto quando si lavora con molti dati.

Le relazioni incorporate semplificano anche la scrittura delle query. Invece di scrivere query complesse che uniscono molti documenti tramite il loro identificatore univoco, puoi restituire tutti i dati correlati all'interno di una singola query.

Un'altra considerazione da tenere a mente è che MongoDB può garantire l'atomicità solo a livello di documento. Gli aggiornamenti dei documenti in un singolo documento sono sempre atomici, ma non per più documenti.

Quando più utenti accedono ai dati, c'è sempre la possibilità che due o più utenti tentino di aggiornare lo stesso documento con dati diversi. In questo caso, MongoDB assicurerà che non si verifichino conflitti e che venga aggiornato solo un insieme di dati alla volta. MongoDB non può garantire questo su più documenti.

Quindi, in generale, le relazioni incorporate possono essere utilizzate nella maggior parte dei casi, a condizione che il documento rimanga entro il limite di dimensione (16 megabyte al momento della scrittura) e/o il suo limite di annidamento (100 livelli di profondità al momento della scrittura).

Tuttavia, le relazioni incorporate non sono appropriate per tutti occasioni. Potrebbero esserci situazioni in cui ha più senso creare una relazione referenziata al documento.

Quando utilizzare le relazioni di riferimento

Per i dati che devono essere ripetuti su più documenti, può essere utile averli in un documento separato. Ciò può ridurre gli errori e aiutare a mantenere coerenti i dati (tenendo presente che gli aggiornamenti di più documenti non sono atomici).

Usando l'esempio sopra, un musicista potrebbe essere un membro (o ex membro) di molte band. Alcuni potrebbero anche produrre album per altri artisti, insegnare agli studenti, gestire cliniche, ecc. Inoltre, molti dati potrebbero essere archiviati su ciascun musicista. Quindi avere un documento separato per ogni musicista ha senso in questo caso.

Inoltre, se ritieni che i tuoi documenti incorporati possano superare il limite di dimensione del file imposto da MongoDB, dovrai archiviare alcuni dati in documenti separati.