Transcrições
1. Introdução do curso: Bem-vindo de volta ao Módulo oito, modelando relacionamentos
com o Mongoose Esta aula é uma continuação
da série de cursos Express JS Meu nome é Shawn
Ragunhi e eu serei seu guia enquanto mergulhamos avançadas de design de banco de dados Tive o
privilégio de trabalhar em vários aplicativos de produção
sem JS e estou animado para compartilhar
minhas ideias com você Alguns dos meus melhores trabalhos
incluem projetar sistemas
escaláveis de alto
desempenho que dependem de bancos de dados bem
estruturados, e hoje você
aprenderá a fazer o mesmo Neste módulo,
estamos nos concentrando na modelagem de relacionamentos
no Mongoose, que é essencial
para qualquer aplicativo que interconecte Veja o que você
aprenderá a modelar relacionamentos usando documentos de referência
e incorporação,
gerenciando matrizes de subdocumentos e trabalhando com transações do MongAV e trabalhando Você também aprenderá
sobre a validação IDs de
objetos para manter a
integridade do seu banco de Essa classe é perfeita para desenvolvedores de
back-end que já têm alguma experiência com Express Js e Mongo DB Se você concluiu
os módulos anteriores, está bem preparado para isso. Você não precisará instalar Js,
Express, Mongo DB
e mangos, além uma compreensão básica das operações
de multidões Entender como modelar relacionamentos de
dados é fundamental
para criar aplicativos escaláveis, sustentáveis e
eficientes Ao final deste módulo, você não apenas
saberá como estruturar relacionamentos
complexos
no Mongadib, mas também ganhará
experiência prática na criação de
APIs que funcionam perfeitamente
em cenários Neste módulo,
trabalharemos em dois projetos. Primeiro, você criará a API do carro para gerenciar
carros em nosso sistema, aprendendo a incorporar e referenciar
documentos de forma eficaz Em seguida, você desenvolverá
a API de aluguéis, que inclui criar
e recuperar aluguéis, validar
IDs de objetos e lidar com transações para garantir a confiabilidade
dos dados Esses projetos proporcionarão uma experiência prática implementação de técnicas avançadas
de banco de dados. Portanto, este módulo está
repleto aulas e projetos práticos que elevarão suas habilidades de
desenvolvimento de back-end Vamos começar e vemos na
primeira palestra.
2. Modelagem de relacionamento de dados com Mongoose: Em todos os exemplos
que analisamos até agora, trabalhamos com documentos únicos e
independentes. Mas no
mundo real, as entidades e conceitos com os quais trabalhamos têm algum tipo
de associação. Por exemplo, você pode ter um objeto do curso ou
um documento do curso. E, claro, esse
curso tem um autor, mas um autor é
mais do que apenas um nome. É mais do que
uma simples sequência de caracteres. Talvez tenhamos uma coleção de autores onde armazenamos documentos
criados
e, em cada documento criado,
podemos ter
propriedades como nome, site, imagem e assim site, imagem Então, nesta palestra,
vou falar sobre como trabalhar
com objetos relacionados Basicamente, temos
duas abordagens. Uma é usar referências, que chamamos de normalização, e a outra abordagem é
usar documentos incorporados, que chamamos de desnormalização Então, vamos ver como eles funcionam. Com a primeira abordagem,
devemos ter uma coleção separada
para armazenar nossos autores. Então, podemos ter um
objeto de autor como esse. Aqui temos todos os
tipos de propriedades
e, em seguida, teremos uma coleção
separada onde armazenamos
objetos do curso como esses. Então, aqui temos um objeto de curso. Definimos o autor como o ID de um documento
do autor na coleção do autor. Aqui estamos usando uma referência. Agora eu preciso esclarecer
algo aqui. Em bancos de dados relacionais,
temos esse conceito de relacionamento que
impõe a integridade dos dados Mas no Mongo DV ou em nenhum banco de
dados SEQL em geral, não
temos um relacionamento Portanto, embora eu esteja definindo
o ID de um autor aqui, na verdade
não
há associação ou relacionamento entre esses dois
documentos no banco de dados. Em outras palavras, posso definir
isso como um ID inválido, e o Mongo DV não se importa
com Agora, poderíamos levar esse
exemplo para o próximo nível. Digamos que um curso possa
ter vários autores. Então, em vez da propriedade
author, poderíamos ter autores, que definimos como uma
matriz de referências. Então, aqui vamos armazenar
vários IDs. Agora, para simplificar, vamos trabalhar com
um único autor. Então, vou
deletar essa parte. Portanto, essa é nossa primeira abordagem, que envolve o uso de referências. Existe outra abordagem. Então, em vez de ter uma
coleção separada de autores, podemos incorporar um documento do autor
dentro de um documento do curso Então, aqui podemos ter um
objeto do curso ou um documento do curso. Neste documento, temos a propriedade author e a
definimos como um objeto. Então, aqui, teremos todas as
propriedades de um autor. Então, estamos incorporando um documento
dentro de outro documento. Ok. E isso é o que
chamamos de desnormalização Agora, se nunca trabalhamos
com bancos de dados iguais antes e você vem de um
banco de dados relacional, você pode pensar que a
primeira abordagem é o Vu Mas esse não é necessariamente o caso quando se trabalha com bancos
de dados iguais. Cada abordagem tem seus
pontos fortes e fracos. abordagem escolhida
realmente depende do seu aplicativo e dos requisitos de
consulta Então, basicamente, você
precisa fazer uma troca entre desempenho
e consistência da consulta. Deixe-me explicar o que
quero dizer com isso. Com a primeira abordagem, temos um único local
para definir um autor. Se amanhã eu decidir mudar o nome desse autor
de talhado para talhado, há um único lugar
que preciso modificar, e todos os cursos que
fazem referência a esse autor
verão imediatamente o autor Então, com a primeira abordagem,
temos consistência. No entanto, toda vez
que quisermos consultar um curso, precisamos fazer uma consulta extra
para carregar o autor relacionado. Agora, às vezes, essa
consulta extra pode não ser um grande problema. Mas, em determinadas situações, você quer garantir que suas consultas sejam executadas o mais
rápido possível Se for esse o caso,
você precisa examinar
a segunda abordagem usando documentos
incorporados. Então, com essa
abordagem, podemos carregar um objeto do curso e seu
autor usando uma única consulta. Não precisamos fazer uma consulta
adicional para carregar o autor porque o
autor está dentro do objeto do curso ou
do documento do curso. No entanto, com essa abordagem, se amanhã eu
decidir mudar o nome desse autor
de
hewn para Shevin, provável que haja vários documentos do curso
que precisem ser atualizados E se nossa operação de atualização
não funcionar com sucesso, é possível que tenhamos alguns documentos do curso
que não estejam atualizados. Então, acabaremos com dados
inconsistentes. Portanto, a primeira abordagem nos
dá consistência. A segunda abordagem nos
dá desempenho. É por isso que eu disse que
você precisa fazer uma
troca entre consistência
e desempenho. Você não pode ter
os dois ao mesmo tempo. Portanto, em cada parte do
seu aplicativo, você precisa
pensar nas consultas que executará com
antecedência
e projetará seu
banco de dados com base nessas consultas Então, esses são os princípios
gerais. Agora temos uma terceira abordagem. O que chamamos de abordagem
híbrida. Por exemplo, imagine que cada
autor tenha 50 propriedades. Não queremos duplicar todas essas propriedades em
cada curso em nosso banco de dados, para que possamos ter uma
coleção separada de autores Mas, em vez de usar
uma referência aqui, podemos incorporar um documento
do autor dentro de um documento do curso, mas não a
representação completa desse autor Talvez queiramos apenas
o nome da propriedade. Então, com a abordagem híbrida, nosso banco de dados
ficará assim. Portanto, temos uma
coleção de autores. Nesta coleção, teremos objetos de
autor como esses. Temos o nome Chevan, e aqui teremos outras
50 propriedades Agora teremos uma
coleção separada de cursos. Nesta coleção,
teremos documentos de cursos como esses. Então, autor, definimos
isso como um documento
e, neste documento, teremos apenas duas propriedades. Um é ID. Essa é uma referência a
um documento do autor. Também temos pregos. Com essa abordagem,
podemos
ler rapidamente um objeto do curso
junto com esse autor, para que possamos otimizar nosso desempenho de
consulta, mas não precisamos armazenar todas essas propriedades de
um autor dentro de um documento do
curso. Agora, essa abordagem é
particularmente útil se você quiser ter um instantâneo dos seus dados em um determinado momento Por exemplo, imagine que você está criando um aplicativo de
comércio eletrônico. Lá teremos
coleções como pedidos,
produtos, carrinhos de compras e assim por diante Em cada pedido, precisamos
armazenar um instantâneo de um produto porque
queremos saber o preço desse produto
em um determinado momento Então é aí que
usaremos a abordagem híbrida. Então, mais uma vez
, a abordagem escolhida realmente depende do aplicativo
que você está criando. Não há certo ou errado. Cada abordagem tem
pontos fortes e fracos. Nas próximas palestras, mostrarei como
implementar cada uma
dessas abordagens
3. Referenciando documentos no Mongoose: Nesta palestra,
mostrarei como referenciar um documento
em outro documento Se você quiser trabalhar
comigo, baixe este arquivo. Eu me anexei a esta palestra. Nesse arquivo, preencha o
Js. Temos dois modelos. O primeiro é autor
com três propriedades, nome, biografia e site. O outro modelo é coors
com um nome de propriedade. Nesta palestra,
adicionaremos outro autor da propriedade
e, lá, referenciaremos um documento do autor
em nosso banco de dados Também temos algumas funções
auxiliares. Uma delas é criar autor. A outra é criar curso e a última
é listar cursos. Todas essas funções
são semelhantes às que vimos
anteriormente nesta seção. Portanto, não há nada de novo aqui. Agora, antes de começar, quero que você acesse o
Mongo DB Compass
e exclua o banco de dados do
playground Queremos começar com uma
tela limpa. Então digite playground aqui
para excluir esse banco de dados. Ok, agora na parte inferior
deste arquivo, você pode ver, temos uma chamada para
criar a função de autor, criar um autor chamado
Chewn com essas propriedades Então abra o terminal
e execute o node, opulate JS. Então criamos um autor, e aqui está a ideia
desse autor. Ok, agora copie isso de
volta para o código. Vamos confirmar essa linha, criar autor e
habilitar a criação de curso. Então, aqui queremos
criar um curso chamado node course
para esse novo autor. Então você passa o
ID do autor como uma string. Agora, se você observar a
implementação dessa função, aqui criamos um objeto de
curso com duas propriedades, nome e autor. Agora, salve o arquivo.
De volta ao terminal. Vamos executar esse programa mais
uma vez. Então, criamos esse objeto do
curso. Aqui está a ideia do curso, o nome do curso, mas não
temos o autor. A razão para isso é que, porque definimos esse modelo de curso, adicionamos apenas a propriedade name. Portanto, ao salvar um objeto do curso, somente as propriedades que
você definiu em seu modelo serão
mantidas no banco de dados Então, aqui precisamos adicionar
outra propriedade, autor. Dissemos isso para um objeto do tipo
esquema. O tipo dessa propriedade
deve ser o ID do objeto. Portanto, usamos o esquema mongoose, o ID do objeto
dottypes. Além disso, definimos uma propriedade chamada ref e aqui adicionamos o nome da coleção de destino,
portanto, nessa propriedade do autor, armazenaremos um ID de objeto que faz referência a um documento
do autor. Mas, mais uma vez, não temos realmente um
relacionamento adequado. Aqui, podemos armazenar um curso
com um autor inválido, e o MongoDB não
reclama Então, modificamos nosso modelo agora de volta
no nó terminal,
OpulateJS, então aqui está
nosso novo objeto de curso Você pode ver que temos
a propriedade do autor agora de volta no MongoDB Campus. Vamos dar uma olhada nesse banco de dados do
playground. Aqui está nossa coleção de cursos. Então você pode ver que
temos dois documentos. O primeiro não
tem autor, mas o segundo tem. Então, aqui temos um ID de objeto que faz
referência a um autor
4. Dominando a população em manguisa: Agora é hora de obter todos os cursos junto
com seus autores. Então, vamos desativar,
criar a função do curso e habilitar essa
função para listar os cursos. Então, nesta função, estamos
chamando o método find. Recebemos todos os cursos e selecionamos apenas o
nome da propriedade. Digamos que as mudanças, Bag no
nó terminal, OpulatetJS Olha, só temos ID e nome
sublinhados. Agora, aqui, se eu adicionar o autor e executar esse programa mais
uma vez, veja, nosso segundo documento
tem um autor, mas estamos apenas obtendo a
referência ou o ID do objeto. Em um aplicativo do mundo real, queremos carregar esse documento
do autor para que possamos exibir seu nome. É aí que usamos
o método populate. Então, aqui está uma multa, podemos chamar de populate
como o primeiro argumento, especificamos o caminho ao qual
foi dada a propriedade Então, neste caso, nossa
propriedade é o autor. E porque antes,
ao definir o modelo do curso, vamos
dar uma olhada aqui. Então, aqui está nosso modelo de curso. Ao definir isso, definimos o
autor como um ID de objeto e referenciamos a coleção do
autor. Então, quando carregamos um objeto do curso e preenchemos a propriedade do
autor, Mongoose sabe que
ele deve consultar a coleção do autor
no Para voltar à função de listas de cursos, simplesmente
chamamos populate e passamos author como o nome
da propriedade alvo Agora vamos ver o que acontece. Então, de volta ao terminal,
vamos executar isso mais uma vez. Ok, olha, nosso primeiro documento, nosso primeiro curso não tem um autor, então
não recebemos nada. Mas nosso segundo documento, nosso segundo curso tem um autor, e aqui temos uma representação completa
de um documento do autor. Agora, em um aplicativo do mundo real, um autor pode ter
várias propriedades. Talvez, ao mostrar
a lista de cursos, não
queiramos obter todas
essas propriedades adicionais. Só queremos obter
o nome da propriedade. Então, de volta ao quadro, ao
chamar o método populate, como segundo argumento,
você pode especificar as propriedades que
deseja incluir ou excluir Então, queremos incluir apenas o nome. Agora, de volta ao terminal, vamos executar esse aplicativo mais
uma vez. Portanto, desta vez, nossa propriedade de
autor é um objeto com apenas duas
propriedades: ID e nome. Agora também podemos excluir
essa propriedade de ID sublinhada. Então, aqui, adicionamos um traço
para excluir a propriedade, e o nome da
propriedade de destino é ID sublinhado Digamos, de volta ao terminal, vamos executar isso mais uma vez. E agora nossa propriedade de autor é um objeto com
apenas uma propriedade. Nome. Também é possível
preencher várias propriedades Por exemplo, vamos
imaginar que cada curso tenha uma categoria e uma categoria
faça referência a um documento de categoria. Então, aqui podemos chamar
preenche novamente na categoria
e, geralmente, escolher apenas a propriedade
do nome de cada documento da Agora,
deixe-me mostrar uma última coisa antes de terminarmos esta palestra. Anteriormente, eu disse
que, no Mongo DB, não
temos relacionamentos para integridade de
dados em nosso banco de dados Então, aqui em nossa coleção de
cursos, é possível definir esse
autor com documento inválido Então, vamos mudar esses dois
em vez de dois C um, C. Não temos um autor
com esse ID neste banco de dados. Veja, o MongoDB está perfeitamente
bem com essa operação. Agora, de volta ao terminal, vamos executar esse programa mais
uma vez. Veja agora que nosso autor é nulo porque não há nenhum autor com um determinado ID em nosso banco de dados
5. Incorporando documentos com o Mongoose: Na última palestra, você aprendeu a usar as
referências para relacionar documentos Nesta palestra,
veremos
outra técnica que
é a incorporação Então, se você quiser
citar junto comigo, baixe este arquivo, que
anexei a esta palestra, embaring dot js Então, aqui temos
esse esquema de autor exatamente igual ao que tivemos
na última palestra Tem três propriedades, nome, biografia e site. Temos esse modelo de autor. Abaixo disso, temos
o modelo do curso. Agora, aqui, não temos
a propriedade do autor, e é isso que vamos
adicionar nesta palestra Então, adicionamos a propriedade do autor. Agora, na última aula,
atribuímos ao autor uma ideia de objeto Então, vamos dar uma olhada. Aqui está nosso modelo
de curso da última palestra. Olha, aqui está a propriedade do
autor. Definimos o tipo
dessa propriedade como
um ID de objeto e referenciamos
a coleção do autor. Nesta palestra,
vamos incorporar um documento do autor diretamente
dentro de um documento do curso Então, definimos o tipo dessa
propriedade para o esquema do autor. Isso está definido aqui. Ok, essa é a única
mudança que precisamos fazer. Agora vamos dar uma olhada
na função criar curso. É preciso um
nome de curso e um autor, inicialize o curso e
salve-o exatamente como antes Então, na parte inferior desse arquivo, temos uma chamada para
essa função para criar um novo curso
com esse autor. Então, antes de prosseguir,
vamos abrir o Mongoi B Compass
e excluir esse vamos abrir o Mongoi B Compass
e excluir Queremos começar em uma tela
limpa para
ter certeza de que estamos na
mesma página. Tudo bem. Linda. Agora, no terminal, vamos executar node embedding dot js Então, aqui está nosso novo documento do
curso. Você pode ver que o autor é um objeto com duas propriedades,
ID e nome. Portanto, este é um documento incorporado
ou um subdocumento. Esses subdocumentos são
como documentos normais. Portanto, a
maioria dos recursos disponíveis em documentos
normais também estão
disponíveis em subdocumentos Por exemplo, podemos
implementar a validação aqui. Podemos impor isso. O
nome do autor pode ser necessário. No entanto, esses subdocumentos não podem ser salvos sozinhos. Eles só podem ser salvos
no contexto de seus pais. Então, digamos que eu queira mudar
o nome desse autor. Aqui está o ID do curso. Vamos copiar isso. Aqui, vou criar uma nova diversão **** Autor do LaunctuDate Ask
Bridges to Ecodblog. Aqui, primeiro precisamos encontrar
um curso com um determinado ID. Então, chamamos cours dot Fine BID, passamos este ID do curso Agora aguarde o resultado e
abjete esse curso. Está bem? Agora modificamos o autor. Suponha que o nome do autor do ponto seja o autor, dissemos isso a Yvan Rebounci E agora podemos chamar force dot C. Portanto, não temos o autor do
curso dot save. Isso não existe. Está bem? Então, vamos seguir em frente
e executar essa função. Atualize o autor, e
aqui está o ID da minha bolsa. Agora, de volta ao terminal, vamos executar node embedding dot js Nosso documento está atualizado. Então, vamos dar uma olhada no Compass. Atualize esta é nossa coleção de
cursos de playground. Aqui está o documento do nosso curso, outro objeto, e você pode ver as
propriedades do nome atualizadas. Também podemos atualizar um
subdocumento diretamente. Então, em vez de consultá-lo primeiro, podemos atualizá-lo diretamente
no banco de dados Então, aqui, vou
modificar esse código e substituir fine by ID
pela atualização 1. Aqui, como primeiro argumento, passamos um objeto de consulta. Estamos procurando um
curso com esse ID, ID
forçado , e o segundo
argumento é nosso objeto de atualização. Então, aqui usamos um operador de conjunto
que você já viu antes. Definimos isso para um objeto e aqui passamos um
ou mais pares de valores E. Então, aqui, para acessar
a propriedade aninhada, usamos a notação de pensamento Digamos que queremos atualizar o nome do
autor de um curso. Então, passamos o nome do ponto do autor. Definimos isso para
Peter Parker. OK. Com isso, não precisamos
modificar esse objeto na memória e salvá-lo explicitamente Nós o atualizamos diretamente
no banco de dados. Antes de executarmos este módulo, percebo que
cometi um erro aqui. Essa deve ser a
primeira atualização. Tudo bem. Vamos executar isso de
novo. Ok, vamos verificar o Compass, atualize Então, aqui está nosso objeto de autor. E olha, o nome
foi atualizado para Io parker. Se você quiser
remover um subdocumento, use o operador
Sunset Deixe-me mostrar como isso funciona. Usamos o operador unset. Agora podemos usar o nome de ponto
do autor não definido para remover essa propriedade aninhada Ou podemos remover esse
subdocumento como um todo. Precisamos definir isso
como uma string vazia. Está bem? Agora vamos executar isso novamente. Portanto,
os cães que incorporam nós de volta abrangem, atualizam e olham, não
temos mais Agora, como eu disse antes, esses subdocumentos são
semelhantes aos documentos normais Então, aqui podemos
impor a validação. Podemos impor isso. Todo
curso deve ter um autor. Mas aqui está a definição
do esquema do nosso curso. Se você quiser tornar essa propriedade de
autor obrigatória, aqui precisamos passar
um objeto do tipo esquema Portanto, definimos o tipo como esquema do
autor e, em seguida ,
exigimos que ele seja verdadeiro exatamente como
aprendemos anteriormente nesta seção Ou, se quiser tornar obrigatória
uma propriedade específica nesse documento de autor, aplique essa validação no
próprio subdocumento do
autor Então, aqui você passa um objeto do tipo esquema e define a
propriedade necessária como verdadeira Na próxima palestra,
mostrarei como trabalhar com uma
variedade de subdocumentos
6. Matrizes de subdocumentos no Mongoose: Então, na última aula, adicionamos o autor como um subdocumento
neste documento do curso Nesta palestra,
mostrarei como alterar isso
para uma
matriz de subdocumentos. Então, primeiro, renomeamos essa
propriedade para autores e, em seguida, alteramos seu valor para
um esquema de matriz de autores OK. Agora, aqui, ao
criar um curso, também
queremos passar
uma série de autores. Então, vou renomear
esse parâmetro para autores. OK. E, finalmente, é
aqui que estamos
criando um curso. Então, em vez de passar um objeto de autor,
passamos uma matriz. Aqui está o primeiro autor, e aqui está o segundo. Digamos que comedor. Agora, de volta à bússola, vou deletar
essa coleção, que possamos ver todos os novos dados
sem nenhuma confusão, ok? Agora, de volta ao
nó terminal, incorporando o ponto Gs. Ok, aqui está nosso novo documento do
curso. Você pode ver que os autores estão definidos
como uma matriz com dois objetos. Este é o primeiro autor e
aqui está o segundo autor. E se você olhar no Compass,
vamos atualizar aqui. Esta é a coleção do curso. Aqui está nosso documento cruzado com uma variedade de autores. Linda. Todo autor é um objeto. Ao expandir isso, você vê
duas propriedades: ID e nome. Linda. Agora, sempre podemos adicionar um autor a essa matriz
posteriormente. Deixe-me te mostrar. Então, de volta ao código, vamos
criar uma nova função, adicionar
constantemente o autor Async Então, passamos um ID do curso
aqui e um objeto de autor. Agora, aqui precisamos
encontrar uma pose primeiro. Então, força constante. Configuramos isso para aguardar o ID do
StFineBy. E aqui passamos esse argumento de
ID de curso . Nós temos o curso. Agora, forçar autores, como
você sabe, é uma matriz. Portanto, podemos chamar o método
push para inserir esse
objeto autor nessa matriz. Mas nossas mudanças estão
apenas na memória. Eles não são salvos
no banco de dados, então precisamos chamar force.ca. Agora, deixe-me deletar isso
e chamar Aqui, precisamos
passar o ID do curso. Então, vou voltar e copiar
esse ID do curso Então cole aqui e depois passe um novo objeto de autor com
o nome, digamos, flash. De volta ao terminal,
vamos executar isso novamente. Ok, nossas alterações são
salvas no banco de dados. Então, vamos verificá-los. Vou me refrescar
aqui. Aqui estão os autores. Olha, temos três
objetos nesta matriz. E aqui está nosso novo autor. Remover um autor
é muito parecido. Então, de volta ao código, vamos adicionar uma nova função, a
constante remove author. assíncrona, aqui precisamos de
dois parâmetros, bolsa e ID do autor Então, primeiro, carregamos o
curso exatamente como antes. Agora vamos aos autores do cours dot. Aqui temos um método chamado ID
e, com isso, podemos
pesquisar um objeto filho pelo ID. Então você passa esse ID de autor que nos dá o objeto autor. Agora podemos chamar o método Delete
one nesse objeto. E, finalmente, salve o curso. Ok, então vamos chamar essa nova
função, remover autor. Deixe-me duplicar essa linha, remover o segundo argumento e alterar o nome
para remover o autor Agora precisamos de um ID de autor. Então, de volta, aqui
está a ideia do flash. Então, vou colar isso aqui. Ok, vamos executar isso. Modo, o ponto de incorporação é. Linda. Vamos dar
uma olhada em nossos dados. Então, vou
atualizar esta página. Autores, olhem, temos
apenas dois autores agora. O Flash sumiu. Então é assim
que trabalhamos com subdocumentos
7. Configurando o MongoDB para transações: Bem vindo de volta. Neste vídeo, estamos configurando conjuntos
MangaiBrplica, que são essenciais para executar Essa configuração garantirá que o Mangaib
esteja no modo de conjunto de réplicas, permitindo que você trabalhe com transações com
vários documentos Na próxima palestra,
mergulharemos na realização de transações
usando mangusto. Então, vamos estabelecer as
bases hoje. Então, examinaremos duas opções. O número um é a réplica de nó
único definida no servidor Mangaib local Agora, essa abordagem é ótima
para testes e desenvolvimento. E o número dois são os
conjuntos de réplicas com o Mangaib atlas, que são ideais para produção pois são baseados em
nuvem e totalmente Vamos começar com
a configuração local. Portanto, configuraremos o Monger
I B para ser executado no modo de
conjunto de réplicas em sua
máquina local com um único Essa configuração nos permite
desenvolver e testar
transações localmente. Portanto, precisamos configurar o modo Manga
IB ou Replica set
e, para isso, precisamos editar a configuração do
Mongo DB Localize o arquivo de configuração. Por padrão, esse
arquivo está localizado nos arquivos
do programa de viagem, servidor
Mongo DB Em seguida, a pasta Virgin,
que é 8.0 no meu caso, e depois a pasta bin, e aqui está mongod dot Agora abra o mongod dot cfg com um editor de texto
como o bloco de notas ou código do
Visual Studio e
localize ou adicione uma seção de replicação Aqui está a replicação
RUPL desse nome. Definimos isso para RS
Zero. E economize. Você pode receber um erro porque não
está no modo de
administrador. Então, aqui está um aviso. Basta tentar como administrador
e nosso arquivo será salvo. Você pode usar qualquer nome
para o conjunto de réplicas, mas R zero é uma escolha comum Agora, reiniciaremos o Mongo DB com a configuração
atualizada Então, abra o Power Shell como
administrador e execute o lap service, ah, A Mongo DB. Agora
vamos reiniciá-lo. Então comece o serviço, h A Mongo DB. Com o Mongo I B agora
no modo de conjunto de réplicas, vamos inicializá-lo Para isso, precisamos
instalar o shell Mongo DB. Portanto, o Mongo B 6.0 e
versões posteriores fornecem o Mongo Asch
como Ele não está mais incluído do servidor
Mongo ib Se você
já o instalou, isso é bom. Caso contrário, visite a página de download do Mongo
Debe Shell. Selecione seu sistema operacional para baixar a versão mais recente. Eu preferiria o instalador MS para uma instalação mais limpa. Embora seja sua escolha, você também pode escolher o ZIP. Abra o MSI e instale-o. Clique em Avançar e observe que você precisa copiar
o caminho de instalação. Então, copie-o em seguida e instale. Depois de instalado, adicione o
diretório MonGash ao caminho do sistema. Então, vamos abrir as variáveis de
ambiente. Você precisa procurar as variáveis do
ambiente do sistema. Aqui, clique em variáveis de
ambiente. Na seção de variáveis do sistema,
curta caminho e clique em Editar. Adicione o caminho que você copiou e clique em OK
para salvar as alterações Então, mais uma vez.
OK. OK. Ótimo. Agora, reiniciaremos o
PowerShell para aplicar as alterações. Depois de adicionar o Mongo
SH ao caminho, vá para o PowerShell
e execute o Mongo Por padrão, o Mongo SH se conecta
à porta 27017 do host local. Se o seu servidor Mongo DV estiver sendo executado localmente
na porta padrão, ele se conectará Agora, inicialize
o conjunto de réplicas
inserindo o ponto Rs, Estou recebendo essa
mensagem de erro porque já
iniciei o conjunto de réplicas antes.
Então você pode ignorá-lo. Você receberá a mensagem correta. Por fim, verificaremos o status e garantiremos que o conjunto de
réplicas esteja em execução Então, status de pontos Rs. Linda. Tudo
está configurado corretamente, e o MongoDB agora estará
sendo executado no modo de conjunto de réplicas, e estamos prontos
para começar a trabalhar com Mas isso não é então. Para ambientes de produção, o
MongoDB Atlas é uma escolha incrível porque configura
automaticamente conjuntos
de réplicas de vários nós, que significa que o suporte a transações está pronto para ser usado imediatamente Então, primeiro de tudo,
acesse o site MongoDB
Atlas Se você ainda não tem
uma conta, cadastre-se, é rápido e gratuito. Se você já tem
um, basta fazer o login. Depois de fazer login, clique em Novo projeto no painel do
Atlas Agora dê um nome ao projeto. Vou escolher
Fair Wheels para fair Wheels e
depois clicar em Avançar. Aqui, crie o projeto. Então, nosso projeto foi criado. Temos que criar um cluster. Então clique em Criar e aqui, se você estiver testando, o nível zero gratuito é perfeito. Mas, para produção,
você deve escolher um nível mais alto para obter mais
potência e recursos. Feito isso,
nomeie seu cluster. Portanto, o padrão é cluster zero, mas vou
escolher pares de rodas. Agora, escolha um provedor de nuvem, AWS, Azure ou Google Cloud e selecione a região
mais próxima dos usuários. Isso ajuda a reduzir a latência
e melhora o desempenho. Vou escolher a
AWS e a região
como Mumbai e , em seguida,
criar a implantação E aqui nosso cluster é criado. Então, aqui temos que criar
um nome de usuário e uma senha, que usaremos
em nossa cadeia de conexão para garantir que você copie a
senha e o nome de usuário. E, em seguida, crie o usuário do banco de dados. Em seguida, você precisa escolher
um método de conexão. Então, aqui escolha os drivers. Verifique se o motorista está perto de Js. A versão é 6.7 ou posterior. E, como você pode ver, a Fair
Wheels é provisionamento. Portanto, nosso banco de dados está sendo provisionado e isso
levará algum tempo Enquanto isso, vamos
proteger nossa cadeia de conexão. Vá para Acesso à rede e
adicione seu endereço IP. Isso permite que seu aplicativo se
conecte ao cluster. Se você estiver em um IP dinâmico, poderá adicionar uma ampla faixa ou
permitir o acesso de qualquer lugar, mas tenha cuidado com isso
na produção. Não, é isso mesmo. Eu volto aos clusters. Isso levará alguns minutos. Eu vou
avançar rapidamente, e aqui está. Então, clique em Conectar
e, novamente, em
drivers, verifique se a opção Near Jasn
617 ou posterior está selecionada E aqui está nossa cadeia de
conexão. Será
algo parecido com isso. Manga V mais SRE Colen Slalsh e o nome de usuário e a senha Portanto, essa não é sua senha. Você precisa se certificar de substituir
o DvPassword por uma senha
para o seu nome de usuário Copie essa string e substitua a string de conexão em nosso aplicativo por esta. Portanto, certifique-se de nomear
o banco de dados com o nome da
rede de dardos, slash fair wheels Isso garantirá que
seu banco de dados esteja conectado
ou, se não houver um banco
de dados com o nome Fair Wheels
, ele será criado. Além disso, certifique-se de
substituir a senha do banco de uma senha que você
copiou gerou aleatoriamente,
e pronto Com o Mongerib atlas, os
conjuntos de réplicas são habilitados por padrão. Portanto, um cluster está pronto
para lidar com transações sem nenhuma etapa extra.
É simples assim. Na próxima palestra,
desenvolveremos
essa configuração mergulhando nas transações usando o mangusto.
8. Realizando transações usando o Mongoose: Em Mon Vov, temos o
conceito de transações, que basicamente significa um grupo de operações que devem
ser realizadas como uma unidade Então, ou todas
essas operações serão concluídas ou alterarão
o estado do banco de dados, ou se algo
falhar no meio, todas essas operações que
foram aplicadas
serão revertidas e nossos dados
voltarão ao estado inicial. As transações do MovaDB estão realmente além do escopo deste curso Mas se você quiser
saber mais sobre isso, deixe-me mostrar a
página certa na documentação. Portanto, pesquise as transações do Mongo
DB. Ok, então aqui está o manual de transações do
Mongo DB. Este documento
explica claramente como realizar transações
distribuídas
usando um exemplo real. Agora, nesta palestra,
vou
mostrar transações
usando mangusto. Mas internamente, ele implementa essa transação usando as transações
do Mongoiw Agora, de volta ao código aqui em
rentals, o ponto está na parte superior, primeiro precisamos carregar o Mongoose Um mangusto tão constante. Definimos isso para exigir o Mongoose. Agora, ele tem um método de início de
sessão que precisamos chamar aqui. Portanto, aguarde o início da sessão do Mongos
dot e guarde-a na Então ponha uma sessão. Em nosso método de postagem, é
aqui que criamos
um objeto de aluguel. Agora não
vamos mais criar esse aluguel e
atualizar o explícito Em vez disso, vamos
iniciar uma transação. Aqui, iniciamos uma
transação chamando session dot start transaction Todas as consultas de manga relacionadas
à transação pausam uma opção de sessão para
associá-las à Portanto, temos duas
operações na Mongóia aqui. Rental dot save e car dot CV. Então, você deseja salvar
esse novo aluguel na coleção de aluguéis. Então você liga para salvar e
passar a sessão. Ok, então esta é nossa
primeira operação, salvando o novo aluguel. Agora, como parte desta unidade, também
queremos atualizar
a coleção do carro. Então, passamos a sessão aqui e também
diminuímos essa operação. Então, essas são duas operações. Depois de encadear todas essas
operações e, finalmente, você precisa chamar await
session dot Comtransaction E sessão ponto sessão. Se você não codificar a transação de
confirmação, nenhuma dessas operações
será executada. Tudo bem. Agora é possível que algo falhe durante
essa transação. Portanto, precisamos agrupar isso
em um bloco try cache. Então, aqui vou
adicionar um bloco tribal. Vou mover todo esse
código para dentro do bloco tri. Então, isso é para o nosso cenário de
sucesso. Agora, se algo falhar, devemos capturar uma
exceção aqui e retornar um erro 500
com o clin Portanto, o status do ponto de resposta 500, o que significa
erro interno do servidor com uma mensagem de mentira seu veículo não está grampeado Algo deu errado.
Mas antes disso, precisamos abortar
a transação Portanto, aguarde a
transação ponto a bordo da sessão e, em seguida, a
sessão ponto da sessão Agora, em um aplicativo do mundo real, neste
momento, você
deseja registrar essa exceção. Então, mais tarde, você pode voltar
e ver o que deu errado. Teremos
uma seção separada no curso sobre
tratamento e registro de erros. Então, por enquanto, não vamos
nos preocupar com isso. Então, de volta ao Campus Mongo DB, vou excluir os
aluguéis da coleção de aluguéis Agora, de volta ao terminal, ele executa o
aplicativo. Não mais. Nosso aplicativo está
em execução. Linda. De volta ao nosso banco de dados, veja nossa coleção de carros. Então, aqui temos um carro e
um número em estoque é cinco. Vou criar
um novo aluguel. Então vamos
voltar aqui, e esse número deve ser f.
Então, vamos voltar para Postman Então, vou
enviar uma solicitação de postagem para nosso terminal de locação
e, aqui no corpo
da solicitação, tenho um ID de cliente
e um ID de carro válidos. Então, vamos nos enviar. Ok, aqui está nossa
resposta. Linda. Então esse é nosso novo objeto de
locatário. Você pode ver se você o alugou
no ID, no cliente e no carro. Agora, de volta ao banco de dados aqui
na coleção do carro, vou atualizar essa lista Olha, o número no
estoque agora é quatro. Portanto, isso verifica se nossa transação
foi concluída com sucesso Agora eu tenho uma pergunta para você. Então, aqui criamos
esse objeto de aluguel. Nós apenas definimos cliente e carro. Em seguida, passamos a sessão para o Mongo Di B Operations e enviamos esse
objeto de aluguel para o cliente Portanto, nesse código, não
definimos o ID nem o
alugamos em propriedades. Mas no corpo da resposta, você pode ver que essas duas
propriedades estão definidas. Então, como isso aconteceu? Em nenhum lugar desse código, depois de
executarmos essa transação, redefinimos o objeto de aluguel Então, como obtivemos as propriedades de
ID e data? Talvez você espere que o Mongo DB
defina esses valores para nós. Mas, na verdade, não. No Mongo B, não
temos esses valores
padrão Nós os definimos em
nosso esquema Mongoose. Então, quando criamos um
novo aluguel ou objeto, Mongoose conhece o
esquema desse Ele examina várias propriedades e define os valores padrão. O mesmo vale para
a propriedade do IE. Então, com mais precisão, o Mongo
DB não define isso. Essa propriedade é definida antes de salvarmos esse
documento no banco de dados. Eu não te contei isso
antes porque não
queria confundi-lo
com muitos detalhes Há mais coisas a serem
identificadas que abordaremos na próxima palestra.
9. ObjectID no MongoDB: Nesta palestra, veremos
os IDs de objetos
no Mongo Di Bi Então você notou que quando você armazena um documento
no Mongadib, Mongo Debi define o valor
da propriedade ID como uma
string longa como Então, aqui temos 24 caracteres, e cada dois caracteres
representam um byte. Então, essencialmente,
temos 12 bytes para identificar de
forma exclusiva um
documento no Mongo Agora, desses 12 bytes, os primeiros quatro bytes
representam um timestamp, e essa é a hora em que esse
documento foi criado Posteriormente, mostrarei
como
extrair esse timestamp desse ID
de objeto Portanto, com esses quatro bytes, você não precisa criar uma propriedade separada em seu
documento, como a criada em, porque esse carimbo de data/hora está
incluído na ID do objeto Da mesma forma,
se você quiser classificar seus documentos com base no
horário de criação, basta classificá-los
pela propriedade de ID. Os próximos três bytes representam
um identificador de máquina. Portanto, duas máquinas diferentes terão dois identificadores
diferentes Os próximos dois bytes representam
um identificador de processo. Portanto, se gerarmos dois
IDs de objetos na mesma máquina, mas em processos diferentes, esses dois bytes
serão diferentes. E, finalmente, os últimos três
bytes representam um contador. Se você estiver na
mesma máquina
no mesmo processo
no mesmo segundo, mas gerar dois documentos
diferentes, o Canter Bites
será Então, com esses 12 bytes, podemos identificar exclusivamente
um documento no Há uma chance muito, muito baixa de
gerarmos dois
IDs de objetos iguais. Deixe-me mostrar como
isso pode acontecer. Então você sabe que em um byte, temos oito bits Em cada bit, temos
um zero ou um. Então, quantos números podemos representar em um
byte ou oito bits Bem, isso é dois
elevado a oito, que é 256. Então, com um byte, podemos
armazenar 256 números diferentes. Agora eu lhe disse que
os últimos três bytes representam um contador. É como o
contador que você
provavelmente já viu no servidor SQL, no MySQL e em outros bancos Portanto, um
número de incremento automático, como um, dois, três, quatro e assim por diante Então, quantos números
você pode armazenar em três bytes? Isso é dois elevado a 24. Isso é 16 milhões. Então, se no mesmo segundo
na mesma máquina,
no mesmo processo, gerarmos mais de
16 milhões de documentos, esse contador transbordará E é aí que
podemos acabar com dois documentos com
o mesmo ID de objeto. Mas você pode ver que esse é um cenário muito improvável para a
maioria dos aplicativos existentes. Tudo o que eu quero que você saiba
é que esse
ID de objeto é quase único,
mas não 100%. Agora, você pode estar
curioso para saber por que não
temos um mecanismo no Mongo Dew
que garanta Por exemplo, em sistemas de
gerenciamento de banco como SQL server ou MySQL, na tabela E, temos um número de incremento automático
que garante Da próxima vez que quisermos armazenar um registro do curso em nosso banco de dados, a ideia desse curso será a ideia do último
curso mais um. Essa abordagem garante a exclusividade
desses identificadores, mas prejudica a escalabilidade no Mangaib. Esse ID que temos aqui não
é gerado pelo próprio
Mongo DB. Na verdade, é gerado
pelo driver Mongo DB. Então, temos esse
motorista do Mongo Dew que fala com o Mongo Div. Portanto, esse ID aqui é
gerado pelo motorista, e isso significa que
não precisamos esperar Mongo Dew gere um
novo identificador exclusivo E é por isso que
os aplicativos criados com base no Mongo DB são
altamente escaláveis Podemos ter várias
instâncias do Mongo DB e
não precisamos conversar com
um local central para obter um identificador exclusivo O próprio driver pode gerar um identificador quase exclusivo
usando esses 12 bytes. Então, quando construímos um
aplicativo com Node e o Express,
usamos o mongoose Como eu disse antes, o mongoose é uma abstração do driver Mongo
DB Então, quando criamos um novo ID de
objeto e um novo documento, Mongoose conversa com o
driver do Mongo DB para gerar um Agora, você também pode gerar
explicitamente um ID, se
quiser. Deixe-me te mostrar. Vou limpar
tudo isso na parte superior. Vamos carregar mongos que
precisam de mangas. Aqui podemos criar
um novo ID de objeto. Então, vamos definir isso para o novo IDE de objeto de
pontos de tipos de pontos Mongos. E então vamos registrar
isso no console. E aqui no terminal, vamos executar esse programa que
é node object ID dot js. Então, veja, temos um identificador
exclusivo e não armazenamos
nada no Mongoib Geramos esse ID de
objeto na memória. Agora eu disse que
os primeiros quatro bytes representam um timestamp Portanto, esse ID de objeto tem um
método chamado GTs Stamp, salvo novamente no terminal Vamos executar isso de novo. Olha, esta é a hora em que gerei
esse ID de objeto. Também temos um método estático
nessa classe de ID de objeto para
validar IDs de objetos. Então mangos dot types dot
Object ID dot é válido. Então eu posso passar uma string
aqui, 12, três, quatro. Obviamente, esse não é
um ID de objeto válido. Então, quando registramos isso no
console, devemos obter false. O registro de pontos do console é válido. Vamos executar isso de novo.
E aqui está o resultado. Então, agora que você entende os IDs de
objetos com mais detalhes,
na próxima palestra, voltaremos ao nosso
aplicativo Fair Wheels e faremos algumas alterações para torná-lo
melhor
10. Validando ObjectID usando Joi: Então, de volta ao nosso aplicativo Fair
Wheels, eu tenho o carteiro aberto e vou
enviar uma solicitação de postagem para nosso terminal de locação E aqui no corpo
da solicitação, temos um ID de
cliente e um ID de carro válidos. Agora, deixe-me mostrar o que
acontece se alterarmos esse ID de objeto para
um valor como 1234 Portanto, esse não é um ID de objeto
válido. Vamos enviar essa solicitação. Você pode ver que obtivemos
o status 500, que é um erro interno do servidor. No entanto, esse não é o caso, pois enviamos um ID de cliente
inválido Como eu disse antes, temos uma seção separada sobre tratamento
de erros e
registro no curso. Então, não vamos nos
preocupar com essa parte. Por enquanto, vamos registrar esse erro no console para ver o que
exatamente aconteceu lá. Então, de volta ao código aqui
no bloco de cache, console dot log per, vamos
enviar a solicitação novamente. Agora, se você olhar
no terminal,
converta para o campo ID do objeto
para o valor um, dois,
três, quatro, digite string no ID de sublinhado do
caminho
para o cliente do modelo Essa mensagem pode parecer um
pouco técnica ou confusa, mas vou simplificá-la
muito para você Então, aqui estamos falando sobre esse modelo de cliente
ou classe de cliente. Estamos falando sobre
a propriedade ID. No Mongoose, você
vê a palavra caminho
porque caminho pode representar
uma cadeia de propriedades Por exemplo, um cliente
pode ter endereço e endereço pode ter rua. É por isso que usamos caminhos. Agora, aqui, Mangus está
reclamando
que não conseguiu converter o
valor 1234 para a Obviamente, porque 1234 não
é um ID de objeto válido. Mas o problema que temos em nossa implementação é
que, em primeiro lugar, estamos recebendo uma resposta
genérica aqui e estamos recebendo esse
erro no terminal. Nessa situação, quando
enviamos um ID de cliente inválido, devemos receber um erro 400 Essa é uma solicitação ruim porque um servidor não pode
atender a essa solicitação. Então, de volta ao RentOstrgs esse é o responsável pela
criação de um Além disso, estamos
validando a solicitação
e isso garante
que, em nossa solicitação, tenhamos uma
identificação do cliente e uma identificação do carro Mas não importa se esses
valores são IDs de objetos válidos. Essa exceção foi lançada
nesta linha na linha 21. Quando tentamos encontrar
um cliente por ID, se você passar uma ID de objeto
inválida, é aí
que obtemos
essa exceção Então, uma maneira de resolver esse
problema é assim. Se os tipos de pontos Mangus fizerem o ID do
objeto, isso é válido. Por isso, passamos a solicitação
body dot, ID do cliente. Agora, se isso não for válido, retornaremos
o erro 400. Então, status 400 com uma mensagem como cliente inválido E então temos que
repetir o mesmo para validar a propriedade de identificação do carro No entanto, essa é uma implementação
ruim. Essa é uma abordagem ruim para resolver esse problema porque, anteriormente, definimos essa função
para validar nossa solicitação Então, essa lógica realmente
pertence a essa função. Então, nessa função,
queremos ter
certeza de que o
ID do cliente é uma string. Ela tem um valor e é
uma ID de objeto válida. Então, se a entrada estiver
na forma correta, vamos ao banco de dados
para encontrar esse cliente. Está bem? Então, vou deletar
essas duas linhas daqui. Vamos voltar à nossa função de
validação. Então, isso está em rental dot JS. Aqui está nossa função de validação
de aluguel. Agora, aqui precisamos adicionar validação
personalizada porque
precisamos conversar com o mangoose Precisamos chamar esse
método válido do tipo de ID do objeto. Agora, estender essa validação
é um pouco complexo e você não
quer repetir isso
toda vez que tiver
uma função de validação Na verdade, existe
um pacote NPM para adicionar suporte à validação de IDs de
objetos, aproveite Então, de volta ao terminal, vamos instalar o Joy Object ID. Então não é isso, a versão atual que estou usando é a versão 4.0 0.2. Agora, de volta ao código
aqui no ponto de aluguel Gs, na parte superior,
precisamos carregar esse módulo. Portanto, exija o Joy Object ID. Agora, isso retorna uma função. Precisamos chamar essa
função e passar uma referência a esse módulo Joy. Então, passamos Joy aqui
e, a propósito, você não
precisa memorizar isso. Você pode simplesmente consultar a documentação
do NPM. Outro resultado
disso é uma função, então podemos definir joy dot
Object ID para essa função. Portanto, o ID do objeto é um método
nesse objeto Joy. Agora, voltando à nossa
função de validação, aqui, vou mudar a
definição desse ID de cliente de joy dot string
para joy dot object ID Esse é o método que
definimos na parte superior
deste módulo, certo? E também é obrigatório. Vamos fazer a mesma alteração
na propriedade
de identificação do carro. Então, ID do objeto. Agora, de volta ao terminal, vamos executar o aplicativo novamente. Vou enviar uma solicitação com esse ID de cliente inválido O mesmo. Ok, olha,
recebemos um pedido ruim. O ID do cliente com o valor 1234 não corresponde
ao padrão exigido E se você olhar
no terminal C, não
recebemos mais aquele erro de falha na conversão
para ID de objeto. Agora, há uma
implementação muito melhor para
essa abordagem. Então, de volta ao rental dot JS, é provável que
usemos esse método em outros
lugares em nosso aplicativo, como no módulo do carro
ou no módulo do cliente. Não queremos redefinir esse método de ID de objeto
em cada módulo Então, na parte superior do arquivo, é
aqui que definimos o método de ID do objeto
no objeto joy. Vou mover isso
daqui para o ponto de índice Gs. Então, nós o carregamos uma vez e podemos reutilizá-lo
em qualquer lugar em nosso aplicativo Então, vamos pegar isso e
ir para index dot JS. Na parte superior, vamos
adicionar essa linha aqui. Também devemos carregar alegria. Tão constante alegria. Definimos isso para exigir alegria. Está bem? Então, essa é uma implementação
melhor. Há mais um lugar
que precisamos modificar aqui. Então, em nossa pasta de modelos, veja car dot js. Portanto, ao criar um carro, precisamos passar um ID
válido da empresa. Então, vou substituir isso
pelo ID do objeto joy dot. Agora, uma última mudança antes de
terminarmos esta palestra. Então, em nossa pasta de rotas, vamos dar uma
olhada em cars dot JS. Aqui está o responsável pela
criação de um carro novo. Então, aqui criamos
um novo objeto de carro, o
salvamos no banco de dados
e o devolvemos. Agora, nesta implementação, estou reiniciando esse carro depois de
salvá-lo no banco de dados Isso foi apenas para
demonstrar que esse método de salvamento
retorna um documento de carro Além disso, não
queria distraí-lo com muitos detalhes sobre
como os IDs de objetos funcionam Agora que você sabe, os IDs de objetos
são, na verdade, gerados
pelo driver MongoDB, não pelo banco de dados Mongo Você sabe que quando
criamos um novo objeto de carro, Mongoose fala com o
motorista do MongoDB e define o ID aqui mesmo antes de salvar
esse carro Então, tecnicamente,
não precisamos reiniciar esse carro para devolver
essa identificação ao cliente Então, podemos remover isso e mudar o cartão de uma
variável para uma constante. O mesmo princípio se aplica ao criar um novo cliente
e uma nova empresa.