Esta é uma boa pergunta que ilustra os problemas com o overemebed e como lidar com isso.
Exemplo:curtidas de postagem
Vamos ficar com o exemplo de usuários que gostam de postagens, que é um exemplo simples. As outras relações teriam de ser tratadas em conformidade.
Você está absolutamente certo de que armazenar os gostos dentro do post, mais cedo ou mais tarde, levaria ao problema de que posts muito populares atingiriam o limite de tamanho.
Então você corretamente voltou para criar um
post_likes
coleção. Por que eu chamo isso de correto? Uma vez que se adapta aos seus casos de uso e requisitos funcionais e não funcionais! - Ele escala indefinidamente (bem, há um limite teórico, mas é enorme)
- É fácil de manter (crie um índice exclusivo sobre
post_id
eliked_user_id
) e use (tanto o usuário quanto o post são conhecidos, então adicionar um like é uma simples inserção ou mais provavelmente um upsert) - Você pode descobrir facilmente quais usuários gostam de qual postagem e qual postagem é curtida por quais usuários
No entanto, eu expandiria um pouco a coleção para evitar consultas desnecessárias para certos casos de uso que são frequentes.
Vamos supor, por enquanto, que os títulos das postagens e os nomes de usuário não podem ser alterados. Nesse caso, o seguinte modelo de dados pode fazer mais sentido
{
_id: new ObjectId(),
"post_id": someValue,
"post_title": "Cool thing",
"liked_user_id": someUserId,
"user_name": "JoeCool"
}
Agora vamos supor que você queira exibir o nome de usuário de todos os usuários que curtiram uma postagem. Com o modelo acima, isso seria uma consulta única e bastante rápida:
db.post_likes.find(
{"postId":someValue},
{_id:0,user_name:1}
)
Com apenas os IDs armazenados, essa tarefa bastante comum precisaria de pelo menos duas consultas e - dada a restrição de que pode haver um número infinito de curtidores para uma postagem - potencialmente enorme consumo de memória (você precisa armazenar os IDs de usuário na RAM).
É verdade que isso leva a alguma redundância, mas mesmo quando milhões de pessoas curtem uma postagem, estamos falando apenas de alguns megabytes de espaço em disco relativamente barato (e fácil de dimensionar) enquanto ganhamos muito desempenho em termos de experiência do usuário.
Agora vem a coisa:mesmo que os nomes de usuário e os títulos das postagens estejam sujeitos a alterações, você só precisava fazer uma atualização múltipla:
db.post_likes.update(
{"post_id":someId},
{ $set:{ "post_title":newTitle} },
{ multi: true}
)
Você está negociando que demora um pouco para fazer algumas coisas bastante raras, como alterar um nome de usuário ou uma postagem para velocidade extrema para casos de uso que acontecem com muita frequência.
Resumo
Tenha em mente que o MongoDB é um banco de dados orientado a documentos. Portanto, documente os eventos nos quais você está interessado com os valores necessários para consultas futuras e modele seus dados de acordo.