Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
MongoDBchevron-right

7 coisas que aprendi ao modelar dados para as estatísticas do YouTube

Lauren Schaefer13 min read • Published Jan 10, 2022 • Updated Oct 01, 2024
MongoDBEsquema
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Mark Smith, Maxime Beugnet e eu recentemente embarcamos em um projeto para recuperar automaticamente estatísticas diárias sobre vídeos no canal do MongoDB no YouTube. Nossa equipe de gerenciamento extraía essas estatísticas todos os meses em uma planilha complicada. Em um esforço para ganhar pontos com nossa equipe de gerenciamento e ter um pouco de tempo de programação, trabalhamos juntos como uma equipe de três pessoas durante duas semanas para desenvolver rapidamente um aplicativo que extrai estatísticas diárias da API do Youtube e as armazena em um MongoDB Atlas database e os exibe em um dashboard do MongoDB Charts.
Captura de tela do dashbaord do MongoDB Charts que contém gráficos sobre os vídeos que nossa equipe publicou no YouTube
Captura de tela do dashbaord do MongoDB Charts que contém gráficos sobre os vídeos que nossa equipe publicou no YouTube
Mark, Max e eu temos uma parte do projeto. Mark cuidou da autenticação OAuth, Max criou os gráficos no dashboard e eu fui responsável por descobrir como recuperar e armazenar as estatísticas do YouTube.
Nesta publicação, vou compartilhar sete coisas que aprendi ao modelar os dados para este aplicativo. Mas, antes de entrar no que aprendi, vou compartilhar um pouco de contexto sobre como modelei os dados.

Sumário

Vídeos relacionados

Se você preferir assistir a um vídeo em vez de ler um texto, sem problemas.
Para saber mais sobre o que construímos e por que construímos dessa maneira, confira a gravação do stream do Twitch abaixo, onde Mark, Max e eu compartilhamos sobre nosso aplicativo.
Se você quiser a versão em vídeo deste artigo, confira a transmissão ao vivo que eu fiz com Mark e Max. Recebemos perguntas fantásticas do público, então você descobrirá alguns tópicos interessantes na gravação.
Se você preferir um vídeo mais conciso que abranja apenas o conteúdo deste artigo, confira a gravação abaixo.

Nosso modelo de dados

Nosso projeto tinha um prazo apertado de duas semanas, então tomamos decisões rápidas em nosso esforço para desenvolver rapidamente um produto mínimo viável. Quando começamos, nem sabíamos como queríamos exibir os dados, o que tornou a modelagem dos dados ainda mais desafiadora.
Acabei criando duas coleções:
  • youtube_videos: armazena metadados sobre cada um dos vídeos no canal do MongoDB no YouTube.
  • youtube_stats: armazena estatísticas diárias do YouTube (distribuídas por mês) sobre todos os vídeos da coleção youtube_videos.
Todos os dias, um programado trigger chama uma função sem servidor responsável por chamar a Youtube PlaylistItems do API. Essa API retorna metadados sobre todos os vídeos no MongoDB Youtube canal do no . Os metadados são armazenados na youtube_videos coleção . Abaixo está um documento da youtube_videos collection (algumas das informações foram editadas):
1{
2 "_id":"8CZs-0it9r4",
3 "kind": "youtube#playlistItem",
4 "isDA": true,
5 ...
6 "snippet": {
7 "publishedAt": 2020-09-30T15:05:30.000+00:00,
8 "channelId": "UCK_m2976Yvbx-TyDLw7n1WA",
9 "title": "Schema Design Anti-Patterns - Part 1",
10 "description": "When modeling your data in MongoDB...",
11 "thumbnails": {
12 ...
13 },
14 "channelTitle": "MongoDB",
15 ...
16 }
17}
Todos os dias, outro trigger chama uma função sem servidor responsável por chamar a de Youtube relatórios do API. As estatísticas que essa API retorna são armazenadas na youtube_stats coleção . Abaixo está um documento da coleção (algumas das estatísticas são removidas para manter o documento curto):
1{
2 "_id": "8CZs-0it9r4_2020_12",
3 "month": 12,
4 "year": 2020,
5 "videoId": "8CZs-0it9r4",
6 "stats": [
7 {
8 "date": 2020-12-01T00:00:00.000+00:00,
9 "views": 21,
10 "likes": 1
11 ...
12 },
13 {
14 "date": 2020-12-02T00:00:00.000+00:00,
15 "views": 29,
16 "likes": 1
17 ...
18 },
19 ...
20 {
21 "date": 2020-12-31T00:00:00.000+00:00,
22 "views": 17,
23 "likes": 0
24 ...
25 },
26 ]
27}
Para ser claro, não estou dizendo que esta foi a melhor maneira de modelar nossos dados; este é o modelo de dados que temos após duas semanas de rápido desenvolvimento. Discutirei alguns dos prós e contras do nosso modelo de dados no restante desta publicação.
Se quiser dar uma olhada em nosso código e saber mais sobre nosso aplicativo, visite https://github.com/mongodb-developer/dream.

O que aprendi

Sem mais demora, vamos para as sete coisas que eu aprendi modelando rapidamente os dados do YouTube.

1. Duplicar dados é assustador, mesmo para quem está treinando outras pessoas a fazer isso

Uma das regras de ouro ao modelar dados para o MongoDB é que os dados que são acessados juntos devem ser armazenados juntos. Ensinamos aos desenvolvedores que não há problema em duplicar dados, especialmente se você não os atualiza com frequência.
Duplicar dados pode parecer difícil no início
Duplicar dados pode parecer difícil no início
Quando comecei a entender como usar a API do YouTube e quais dados poderia recuperar, me dei conta de que precisaria fazer duas chamadas de API: uma para recuperar uma lista de vídeos com todos os metadados e outra para recuperar as estatísticas desses vídeos. Para facilitar o desenvolvimento, decidi armazenar as informações dessas duas chamadas de API em coleções separadas.
Eu não tinha certeza de quais dados precisariam ser exibidos junto com as estatísticas (em outras palavras, eu não tinha certeza de quais dados seriam acessados juntos), então não dupliquei nenhum dos dados. Eu sabia que, se fosse duplicar os dados, precisaria manter a consistência desses dados duplicados. E, para ser sincero, a manutenção de dados duplicados era um pouco assustadora devido à escassez de tempo e à falta de um processo de desenvolvimento de software que estávamos seguindo.
No modelo de dados atual, posso coletar estatísticas facilmente sobre curtidas, descurtidas, visualizações etc. para um determinado ID de vídeo, mas terei que usar $lookup para unir os dados com a coleção youtube_videos para lhe dizer qualquer coisa mais. Mesmo algo que parece relativamente simples, como listar o nome do vídeo junto com as estatísticas, requer o uso de $lookup. A operação $lookup necessária para unir os dados nas duas coleções não é tão complicada, mas as práticas recomendadas sugerem limitar $lookup, pois essas operações podem afetar negativamente o desempenho.
Enquanto desenvolvíamos nosso produto mínimo viável, avaliei a facilidade de desenvolvimento ao evitar a duplicação de dados em relação ao impacto potencial de dividir nossos dados no desempenho. A facilidade de desenvolvimento venceu.
Agora que sei que preciso de informações como o nome do vídeo e a data de publicação com as estatísticas, posso implementar o Padrão de referência estendida. Posso duplicar algumas das informações da coleção youtube_videos na coleçãoyoutube_stats. Em seguida, posso criar um trigger do Atlas que observará as alterações na coleçãoyoutube_videos e enviará automaticamente essas alterações para a coleção youtube_stats. (Observe que se eu estivesse usando um banco de dados auto-hospedado em vez de um banco de dados hospedado no Atlas, eu poderia usar um fluxo de alterações em vez de um trigger do Atlas para garantir que os dados permanecessem consistentes.)
Duplicar dados não é tão perigoso quando (1) você tem certeza de quais dados precisam ser duplicados e (2) usa Atlas triggers ou change streams para garantir que os dados permaneçam consistentes.

2. Use o Padrão de Bucket somente quando você se beneficiará dos buckets

Adoro padrões de projetos de esquemas (confira esta série de blogs ou este curso gratuito da MongoDB University para saber mais) e antipadrões de projeto de esquema (confira esta série de blogs ou esta série de vídeos do YouTube para saber mais).
Quando estava decidindo como armazenar as estatísticas diárias do Youtube, percebi que tinha dados de série temporal. Eu sabia que o padrão bucket era útil para dados de série temporal, então decidi implementá-lo. Decidi criar um bucket de estatísticas para um determinado período de tempo e armazenar todas as estatísticas desse período para um único vídeo em um documento.
Eu não tinha certeza do tamanho que meus buckets deveriam ter. Eu sabia que não queria cair na armadilha do Antipadrão de arrays massivos, então não queria que meus buckets fossem muito grandes. Para avançar rapidamente, decidi que um mês seria um bom tamanho de bucket e imaginei que poderia ajustar conforme necessário.
Qual deve ser o tamanho do seu bucket? Grande o suficiente para surpreender sua mãe.
Qual deve ser o tamanho do seu bucket? Grande o suficiente para surpreender sua mãe.
Os buckets acabaram sendo muito úteis durante o desenvolvimento, pois eu podia ver facilmente todas as estatísticas de um vídeo para um determinado mês para garantir que elas estavam sendo extraídas corretamente.
No entanto, os buckets não ajudaram muito os membros da minha e equipe e eu em nosso aplicativo. Não tínhamos muitos dados a ponto de nos preocupar em reduzir o tamanho dos nossos índices. Não implementamos o padrão computado para pré-computar estatísticas mensais. E não executamos queries que se beneficiaram de ter os dados agrupados por mês.
Olhando para trás, criar um documento para cada vídeo todos os dias não teria problema. Não nos beneficiamos de nenhuma das vantagens do padrão bucket. Se nossos requisitos mudassem, certamente poderíamos nos beneficiar do padrão bucket. No entanto, neste caso, eu adicionei a complexidade de agrupar as estatísticas em buckets, mas não obtive os benefícios, então não valeu a pena.

3. Use um campo de data para rotular buckets baseados em datas

Conforme descrito na seção anterior, decidi agrupar minhas estatísticas de vídeo do YouTube por mês. Eu precisava de uma maneira de indicar o intervalo de datas para cada grupo, portanto, cada documento contém um campo chamado year e um campo chamado month. Ambos os campos armazenam valores do tipo long. Por exemplo, um documento para o mês de janeiro 2021 teria "year": 2021 e "month": 1.
Não, eu não estava armazenando informações de data como uma data. Mas talvez eu devesse ter feito isso.
Não, eu não estava armazenando informações de data como uma data. Mas talvez eu devesse ter feito isso.
Poderíamos comparar meses de vários anos (por exemplo, poderíamos comparar estatísticas em janeiro de 2019, 2020 e 2021), e esse modelo de dados nos permitiria fazer isso.
Outra opção teria sido usar um único campo do tipo date para indicar o intervalo de datas. Por exemplo, para o mês de janeiro, eu poderia ter definido "date": new Date("2021-01"). Isso me permitiria realizar cálculos baseados em datas em minhas queries.
Tal como acontece com todas as considerações de modelagem de dados no MongoDB, a melhor opção depende do seu caso de uso e de como você fará a query dos dados. Use um campo do tipo date para buckets baseados em datas se desejar fazer uma query usando datas.

4. Limpar os dados que você recebe das APIs facilitará o trabalho com os dados

Como mencionei no início desta publicação, eu era responsável por recuperar e armazenar os dados do YouTube. Meu colega de equipe Max era responsável por criar os gráficos para ver os dados.
Não prestei muita atenção em como os dados que estava obtendo da API foram formatados — apenas os coloquei no banco de dados. (Já mencionei que estamos trabalhando o mais rápido possível?)
Desde que os dados estejam sendo inseridos no banco de dados, quem se importa com o formato em que estão?
Desde que os dados estejam sendo inseridos no banco de dados, quem se importa com o formato em que estão?
Quando Max começou a criar os gráficos, ele levantou algumas preocupações sobre a maneira como os dados foram formatados. A data em que o vídeo foi publicado estava sendo armazenada como string em vez de date. Além disso, o mês e o ano estavam sendo armazenados como string em vez de long.
Max era capaz de fazer conversões de tipo em MongoDB Charts, mas, no final das contas, queríamos armazenar os dados de uma forma que fosse fácil de usar, seja ao ver os dados em Charts ou consultando os dados usando a linguagem de query do MongoDB (MQL).
As correções foram simples. Depois de recuperar os dados da API, eu os converti para o tipo ideal antes de enviá-los ao banco de dados. Dê uma olhada na linha 37 da minha função se quiser ver um exemplo de como fiz isso.
Se você estiver extraindo dados de uma API, considere se vale a pena remodelar ou reformatar os dados antes de armazená-los. É uma coisa pequena que pode tornar o seu trabalho e o de seus colegas de equipe muito mais fácil no futuro.

5. Otimizar para o seu caso de uso é realmente difícil quando você não sabe totalmente qual será o seu caso de uso

Sim, isso é meio obvio.
Vou explicar melhor.
Quando começamos a trabalhar em nosso aplicativo, sabíamos que queríamos exibir visualmente as estatísticas do YouTube em um dashboard. Mas não sabíamos quais estatísticas poderíamos extrair da API ou como queríamos visualizar os dados. Nossa abordagem foi colocar os dados no banco de dados e depois descobrir.
Ao modelar nossos dados, não fazia ideia de qual seria nosso caso de uso final – não tinha certeza de como os dados seriam acessados. Então, em vez de seguir a regra prática de que os dados acessados juntos devem ser armazenados juntos, modelei os dados da maneira que fosse mais fácil para eu trabalhar ao recuperar e armazenar os dados.
Uma das vantagens de usar o MongoDB é que você tem muita flexibilidade em seu esquema, para que possa fazer alterações à medida que os requisitos mudam. (O padrão de versionamento de esquema fornece um padrão de como fazer isso com sucesso.)
Como Max estava se exibindo na criação dos nossos charts, vi que ele criou um pipeline de agregação dentro dos Charts que calcula o trimestre do ano fiscal (por exemplo, janeiro de 2021 está em Q4 do ano fiscal 2021) e o adiciona a cada documento na coleção youtube_stats. Vários de nossos charts agrupam os dados por trimestre, portanto, precisamos deste campo.
Eu estava muito satisfeito com a pipeline de agregação que Max criou para calcular o ano fiscal. No entanto, se eu soubesse que calcular o trimestre seria um de nossos requisitos quando eu estivesse modelando os dados, poderia ter calculado o trimestre do ano fiscal e armazenado dentro da coleção youtube_stats para que qualquer gráfico ou query pudesse usá-lo. Se eu tivesse seguido esse caminho, teria usado o Padrão Computado.
Agora que sei que temos um requisito para exibir o trimestre do ano fiscal, posso escrever um script para adicionar o campo fiscal_year_quarter aos documentos existentes. Também poderia atualizar a função que cria novos documentos na coleção youtube_stats para calcular o trimestre do ano fiscal e armazená-lo em novos documentos.
A modelagem de dados no MongoDB tem tudo a ver com seu caso de uso. Quando você não sabe qual é o seu caso de uso, a modelagem de dados se torna um jogo de adivinhação. Lembre-se de que tudo bem se seus requisitos mudarem; o esquema flexível do MongoDB permite que você atualize seu modelo de dados conforme necessário.

6. Não existe uma "maneira correta" de modelar seus dados

Confesso que já disse aos desenvolvedores que são novos no uso do MongoDB exatamente isso: não há uma "maneira certa" de modelar seus dados. Dois aplicativos que utilizam os mesmos dados podem ter modelos de dados ideais diferentes com base em como os aplicativos usam os dados.
No entanto, o perfeccionista em mim ficou um pouco perturbado ao modelar os dados para este aplicativo. Em mais de uma reunião de nossa equipe, eu disse a Mark e Max que não estava gostando do modelo de dados que havia criado. Eu não sentia que estava "acertando a mão".
Só quero que meu modelo de dados seja perfeito. É pedir demais?
Só quero que meu modelo de dados seja perfeito. É pedir demais?
Como mencionei acima, o problema era que eu não sabia o caso de uso para o qual estava otimizando enquanto desenvolvia o modelo de dados. Eu estava fazendo suposições e me sentindo desconfortável. Como eu estava usando um banco de dados relacional, não podia simplesmente normalizar os dados sistematicamente e afirmar que os havia modelado corretamente.
A flexibilidade do MongoDB lhe dá muito poder, mas também pode fazer você se perguntar se chegou ao modelo de dados ideal. Você pode descobrir, como eu fiz, que talvez precise revisitar seu modelo de dados à medida que seus requisitos se tornam mais claros ou mudam. E tudo bem.
(Não deixe a flexibilidade do esquema do MongoDB te assustar. Você pode usar a validação de esquema do MongoDB quando estiver pronto para bloquear parte ou todo o seu esquema.)

7. Determine o quanto você deseja ajustar seu modelo de dados com base na facilidade de trabalhar com os dados e em seus requisitos de desempenho

Com base no que aprendi anteriormente, que não existe "da maneira correta" para modelar seus dados, os modelos de dados provavelmente sempre podem ser aprimorados. Ao identificar quais serão suas queries ou se elas mudarem, você provavelmente encontrará novas maneiras de otimizar seu modelo de dados.
A questão é: quando seu modelo de dados é bom o suficiente? O perfeccionista em mim lutou com essa questão. Devo continuar otimizando? Ou o modelo de dados que temos é bom o suficiente para nossos requisitos?
Para responder a essa pergunta, me vi fazendo mais duas perguntas:
  • Meus colegas e eu conseguimos trabalhar facilmente com os dados?
  • O desempenho do nosso aplicativo é bom o suficiente?
As respostas para as perguntas podem ser um pouco subjetivas, especialmente se você não tiver requisitos de desempenho rígidos, como uma página da web deve carregar em X milissegundos.
No nosso caso, não definimos nenhum requisito de desempenho. Atualmente, nosso front-end é um dashboard Charts. Então, eu me perguntava: nosso Charts está carregando rápido o suficiente? E a resposta é sim, nosso Charts carrega muito rapidamente. O Charts utiliza cache com uma atualização padrão de uma hora para garantir que os gráficos carreguem rapidamente. Depois que um usuário carrega o dashboard em seu navegador, os gráficos permanecem exibidos, mesmo enquanto se espera que eles obtenham os dados mais recentes quando o cache for atualizado.
Se seus desenvolvedores são capazes de trabalhar facilmente com os dados e o desempenho do seu aplicativo é bom o suficiente, seu modelo de dados provavelmente é bom o suficiente.

Resumo

Toda vez que trabalho com o MongoDB, aprendo algo novo. No processo de trabalhar com uma equipe para criar rapidamente um aplicativo, aprendi muito sobre modelagem de dados no MongoDB:
Se você tiver interesse em aprender mais sobre modelagem de dados, recomendo os seguintes recursos:
Lembre-se de que cada caso de uso é diferente, portanto, cada modelo de dados será diferente. Concentre-se em como você usará os dados.
Se você tiver alguma dúvida sobre modelagem de dados, recomendamos que você faça parte da MongoDB Community. É um ótimo lugar para tirar dúvidas. Os funcionários e membros da comunidade do MongoDB estão lá todos os dias para responder a perguntas e compartilhar suas experiências. Espero ver você lá!

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Início rápido

Pipelines de agregação complexos com Baunilha PHP e MongoDB


Sep 05, 2024 | 10 min read
Artigo

Queries que não diferenciam maiúsculas de minúsculas sem índices que não diferenciam maiúsculas de minúsculas


Oct 01, 2024 | 8 min read
Início rápido

Aggregation Framework com Node.js 3.3.2 Tutorial


Oct 01, 2024 | 9 min read
Tutorial

Habilite a IA generativa e os cursos de pesquisa semântica em seu banco de dados com o MongoDB Atlas e o OpenAI


Sep 09, 2024 | 8 min read
Sumário
  • Sumário
  • Vídeos relacionados
  • Nosso modelo de dados
  • O que aprendi
  • Resumo