Para criar um relacionamento no MongoDB, incorpore um documento BSON em outro ou faça referência a ele de outro.
Os bancos de dados MongoDB funcionam de maneira diferente dos bancos de dados relacionais. Isso também vale para os relacionamentos.
No MongoDB, você pode criar um relacionamento usando um dos dois métodos a seguir:
- Documentos incorporados.
- Documentos referenciados.
O método usado dependerá dos dados e de como você pretende consultar esses dados.
Relações incorporadas
Com o MongoDB, você pode incorporar documentos dentro de documentos. Portanto, um único documento pode conter seus próprios relacionamentos.
Na verdade, já criamos um relacionamento usando esse método quando criamos um documento pela primeira vez.
Relação individual
Um relacionamento de um para um é onde o documento pai tem um filho e o filho tem um pai.
Por exemplo, uma regra de negócios pode dizer que um artista só pode ter um endereço e que o endereço só pode pertencer a um artista.
O código a seguir cria um relacionamento um para um, incorporado ao documento.
db.artists.insert( { _id : 2, artistname : "Prince", address : { street : "Audubon Road", city : "Chanhassen", state : "Minnesota", country : "United States" } } )
Resultado:
WriteResult({ "nInserted" : 1 })
Relação um-para-muitos
Um um para muitos relacionamento é onde o documento pai pode ter muitos documentos filho, mas os documentos filho só podem ter um documento pai.
Então, outra regra de negócios pode dizer que um artista pode ter muitos álbuns, mas um álbum só pode pertencer a um artista.
A execução do código a seguir criará um relacionamento um para muitos:
db.artists.insert( { _id : 3, artistname : "Moby", albums : [ { album : "Play", year : 1999, genre : "Electronica" }, { album : "Long Ambients 1: Calm. Sleep.", year : 2016, genre : "Ambient" } ] } )
Resultado:
WriteResult({ "nInserted" : 1 })
Relações referenciadas a documentos
Você pode usar uma referência de documento para criar um relacionamento. Em vez de incorporar o documento filho no documento pai (como fizemos acima), você separa o documento filho em seu próprio documento autônomo.
Então poderíamos fazer isso:
Documento principal
db.artists.insert( { _id : 4, artistname : "Rush" } )
Documentos secundários
Vamos inserir 3 documentos filho — um para cada membro da banda:
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 } )
Consultando o relacionamento
Depois de inserir os dois documentos acima, você pode usar
$lookup
para executar uma junção externa esquerda nas duas coleções. Isso, em conjunto com o
aggregate()
método e $match
para especificar o artista específico em que você está interessado, retornará os documentos pai e filho em um. db.artists.aggregate([ { $lookup: { from: "musicians", localField: "_id", foreignField: "artist_id", as: "band_members" } }, { $match : { artistname : "Rush" } } ]).pretty()
Resultado:
{ "_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 } ] }
Você pode ver que os dois primeiros campos são da coleção de artistas, e o restante é da coleção de músicos.
Portanto, se você consultar apenas a coleção de artistas:
db.artists.find( { artistname : "Rush" } )
Você só obteria isso:
{ "_id" : 4, "artistname" : "Rush" }
Nenhum dado relacionado é retornado.
Quando usar documentos incorporados versus documentos referenciados
Ambos os métodos de criação de relacionamentos têm seus prós e contras. Há momentos em que você pode usar documentos incorporados e outras vezes você usará documentos referenciados.
Quando usar relacionamentos incorporados
Um dos principais benefícios do uso do método de relacionamento embutido é o desempenho. Quando o relacionamento é incorporado ao documento, as consultas serão executadas mais rapidamente do que se estivessem espalhadas por vários documentos. O MongoDB só precisa retornar um documento, em vez de juntar vários documentos para recuperar os relacionamentos. Isso pode fornecer um grande aumento de desempenho – especialmente ao trabalhar com muitos dados.
As relações incorporadas também tornam as consultas mais fáceis de escrever. Em vez de escrever consultas complexas que unem muitos documentos por meio de seu identificador exclusivo, você pode retornar todos os dados relacionados em uma única consulta.
Outra consideração a ter em mente é que o MongoDB só pode garantir a atomicidade no nível do documento. As atualizações de documentos para um único documento são sempre atômicas, mas não para vários documentos.
Quando vários usuários estão acessando os dados, sempre há uma chance de que dois ou mais usuários tentem atualizar o mesmo documento com dados diferentes. Nesse caso, o MongoDB garantirá que nenhum conflito ocorra e apenas um conjunto de dados seja atualizado por vez. O MongoDB não pode garantir isso em vários documentos.
Portanto, em geral, relacionamentos incorporados podem ser usados na maioria dos casos, desde que o documento permaneça dentro do limite de tamanho (16 megabytes no momento da gravação) e/ou seu limite de aninhamento (100 níveis de profundidade no momento da gravação).
No entanto, os relacionamentos incorporados não são apropriados para todos ocasiões. Pode haver situações em que faça mais sentido criar um relacionamento referenciado a um documento.
Quando usar relacionamentos referenciados
Para dados que precisam ser repetidos em muitos documentos, pode ser útil tê-los em seu próprio documento separado. Isso pode reduzir erros e ajudar a manter os dados consistentes (tendo em mente que as atualizações de vários documentos não são atômicas).
Usando o exemplo acima, um músico pode ser membro (ou ex-membro) de muitas bandas. Alguns também podem produzir álbuns para outros artistas, ensinar alunos, administrar clínicas, etc. Além disso, muitos dados podem ser armazenados em relação a cada músico. Portanto, ter um documento separado para cada músico faz sentido neste caso.
Além disso, se você acha que seus documentos incorporados podem exceder o limite de tamanho de arquivo imposto pelo MongoDB, você precisará armazenar alguns dados em documentos separados.