# MongoDB: Intro e Implementação

{% hint style="info" %}
Desenvolva habilidades com o MongoDB, um banco de dados NoSQL líder, e aprenda a realizar o deploy de um banco de dados na nuvem usando o MongoDB Cloud Atlas. Esta etapa é essencial para preparar o ambiente para integração com aplicações hospedadas em plataformas de cloud, como o CodeSpaces.
{% endhint %}

## Vídeo

{% embed url="<https://youtu.be/Csk1U5b-uuI>" %}

**Link direto:** <https://youtu.be/Csk1U5b-uuI>

## Tópicos

1. **Introdução ao MongoDB:**
   * Explanação sobre bancos de dados NoSQL e o ecossistema do MongoDB.
   * Instalação do MongoDB Compass e introdução às suas funcionalidades.
2. **Deploy no MongoDB Cloud Atlas:**
   * Criação de uma conta no MongoDB Cloud Atlas.
   * Configuração do cluster MongoDB no Cloud Atlas.
   * Conexão do MongoDB Compass com o banco de dados no Cloud Atlas.
3. **CRUD com MongoDB:**
   * Execução de operações CRUD utilizando o MongoDB Compass conectado ao Cloud Atlas.
   * Integração do MongoDB Cloud Atlas com o projeto backend Node.js.

## Material de Apoio

### Repositório no GitHub

{% embed url="<https://github.com/SalvatoreAcademy/backend-missao-aprendizado-iniciante-mongodb-intro-e-implementacao>" %}

### PDF para Download

{% file src="<https://1989749987-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FRonehqhrmNdVr43Njmfs%2Fuploads%2Fgit-blob-65236cd484ae2a741aca3c1cf7684dd8c8a329d6%2FBackend%20-%20Iniciante%20-%20Miss%C3%A3o%20de%20Aprendizado%20-%20MongoDB%20Intro%20e%20Implementa%C3%A7%C3%A3o.pdf?alt=media>" %}

### Miro

{% embed url="<https://miro.com/app/board/uXjVNQ6PZjQ=/?moveToWidget=3458764587647670381&cot=14>" %}

## Exercícios de Fixação

{% hint style="info" %}
Use esses exercícios para reforçar o que acabou de aprender. Se errar, leia a explicação para entender melhor o conceito.
{% endhint %}

<details>

<summary>Qual comando usamos para instalar o MongoDB Driver no Node.js?</summary>

A) `npm install mongodb`

B) `npm install mongoose`

C) `npm install mongo`

D) `npm install mongodriver`

</details>

<details>

<summary>Resposta correta</summary>

**Qual comando usamos para instalar o MongoDB Driver no Node.js?**

**Resposta Correta**: A

**Feedback**: O comando `npm install mongodb` é usado para instalar o driver oficial do MongoDB para Node.js.

</details>

***

<details>

<summary>Complete o código para conectar ao MongoDB usando o MongoClient, inicializar o banco de dados e exibir uma mensagem de sucesso.</summary>

{% code lineNumbers="true" %}

```javascript
const { MongoClient } = require('mongodb');
const dbUrl = 'mongodb+srv://<user>:<password>@cluster0.mongodb.net';
const client = new MongoClient(dbUrl);

async function main() {
  await client._________();
  const db = client.db('testdb');
  console.log('Banco de dados conectado com sucesso!');
}

main();
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

**Complete o código para conectar ao MongoDB usando o MongoClient.**

**Resposta Correta**:

```javascript
await client.connect();
```

**Feedback**: O método `connect` é usado para estabelecer a conexão com o banco de dados, e a mensagem `Banco de dados conectado com sucesso!` é exibida após a conexão ser bem-sucedida.

</details>

***

<details>

<summary>Verdadeiro ou Falso: O MongoDB é um banco de dados relacional.</summary>

A) Verdadeiro

B) Falso

</details>

<details>

<summary>Resposta correta</summary>

**Verdadeiro ou Falso: O MongoDB é um banco de dados relacional.**

**Resposta Correta**: B

**Feedback**: O MongoDB é um banco de dados NoSQL, não relacional, que armazena dados em documentos JSON-like.

</details>

***

<details>

<summary>Qual comando usamos para iniciar a aplicação com Nodemon?</summary>

A) `npm start`

B) `npm run start`

C) `npm run dev`

D) `nodemon app.js`

</details>

<details>

<summary>Resposta correta</summary>

**Qual comando usamos para iniciar a aplicação com Nodemon?**

**Resposta Correta**: C

**Feedback**: O comando `npm run dev` é comumente usado para iniciar a aplicação com Nodemon, conforme configurado no `package.json`.

</details>

***

<details>

<summary>Complete o código para criar um endpoint que adicione um novo documento à collection no MongoDB.</summary>

{% code lineNumbers="true" %}

```javascript
const express = require("express");
const { MongoClient } = require("mongodb");
const app = express();
app.use(express.json());

const dbUrl = 'mongodb+srv://<user>:<password>@cluster0.mongodb.net';
const client = new MongoClient(dbUrl);

async function main() {
  await client.connect();
  const db = client.db('testdb');
  const collection = db.collection('personagens');

  app.post("/personagem", async function (req, res) {
    const novoItem = req.body;
    if (!novoItem.nome) {
      return res.status(400).send('Corpo da requisição deve conter a propriedade nome.');
    }

    await collection._________(novoItem);
    res.status(201).send(novoItem);
  });

  app.listen(3000, function () {
    console.log("Aplicação rodando em http://localhost:3000");
  });
}

main();
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

**Complete o código para criar um endpoint que adicione um novo documento à collection no MongoDB.**

**Resposta Correta**:

```javascript
await collection.insertOne(novoItem);
```

**Feedback**: O método `insertOne` é usado para adicionar um novo documento à collection do MongoDB.

</details>

## Exercícios de Validação

{% hint style="info" %}
Esses exercícios testarão sua compreensão prática. Revise o feedback para melhorar suas habilidades.
{% endhint %}

### Desafio de Código

Crie um endpoint adicional na aplicação ExpressJS que atualize um documento existente na collection do MongoDB. Se o documento não existir, o endpoint deve responder com "Item não encontrado".

* Implementar o novo endpoint no arquivo `index.js`.

<details>

<summary>Resposta esperada</summary>

{% code lineNumbers="true" %}

```javascript
app.put("/personagem/:id", async function (req, res) {
  const id = req.params.id;
  const novoItem = req.body;

  if (!novoItem.nome) {
    return res.status(400).send('Corpo da requisição deve conter a propriedade nome.');
  }

  const resultado = await collection.updateOne({ _id: new ObjectId(id) }, { $set: novoItem });

  if (resultado.matchedCount === 0) {
    return res.status(404).send('Item não encontrado.');
  }

  res.send('Item atualizado com sucesso.');
});
```

{% endcode %}

**Feedback:** Certifique-se de que o servidor está ouvindo na porta correta e que a rota `/personagem/:id` está devidamente configurada.

</details>

### Revisão de Código

{% hint style="danger" %}
**Analise o código a seguir, encontre e corrija o erro.**
{% endhint %}

{% code lineNumbers="true" %}

```javascript
const express = require("express");
const { MongoClient, ObjectId } = require("mongodb");
const app = express();

const dbUrl = 'mongodb+srv://<user>:<password>@cluster0.mongodb.net';
const client = new MongoClient(dbUrl);

const db = client.db('biblioteca');
const collection = db.collection('livros');

app.use(express.json());

app.get("/livros/:id", async function (req, res) {
  const id = req.params.id;
  const livro = await collection.findOne({ _id: id });

  if (!livro) {
    return res.status(404).send('Livro não encontrado.');
  }

  res.send(livro);
});

app.listen(3000, function () {
  console.log("Aplicação rodando em http://localhost:3000");
});
```

{% endcode %}

<details>

<summary>Resposta Correta</summary>

**Erros:**

1. Conexão com o banco de dados MongoDB não é estabelecida.
2. O ID do livro não é convertido para `ObjectId` ao buscar o documento.

{% code lineNumbers="true" %}

```javascript
const express = require("express");
const { MongoClient, ObjectId } = require("mongodb");
const app = express();

const dbUrl = 'mongodb+srv://<user>:<password>@cluster0.mongodb.net';
const client = new MongoClient(dbUrl);

app.use(express.json());

async function main() {
  await client.connect();
  const db = client.db('biblioteca');
  const collection = db.collection('livros');

  app.get("/livros/:id", async function (req, res) {
    const id = req.params.id;
    const livro = await collection.findOne({ _id: new ObjectId(id) });

    if (!livro) {
      return res.status(404).send('Livro não encontrado.');
    }

    res.send(livro);
  });

  app.listen(3000, function () {
    console.log("Aplicação rodando em http://localhost:3000");
  });
}

main();
```

{% endcode %}

**Feedback**: Certifique-se de que a conexão com o banco de dados MongoDB está estabelecida antes de acessar o banco de dados e a collection. Além disso, converta corretamente o ID do livro para `ObjectId` ao buscar o documento.

</details>

### Projeto Prático

Implemente um CRUD completo para gerenciar uma entidade de "Livros" em uma biblioteca usando ExpressJS e MongoDB. Os livros devem ter as propriedades "título", "autor" e "ano de publicação". Crie endpoints para adicionar, listar, atualizar e deletar livros. Se o livro não for encontrado, o endpoint deve responder com "Livro não encontrado".

#### Tarefas

* **Configuração Inicial**:
  * Inicialize um novo projeto NodeJS.
  * Instale o ExpressJS e o MongoDB Driver.
  * Configure o Nodemon para reiniciar o servidor automaticamente.
* **Conexão com o MongoDB**:
  * Conecte-se ao MongoDB utilizando o MongoClient.
  * Inicialize o banco de dados e a collection "livros".
* **Implementação dos Endpoints**:
  * Implemente um endpoint para adicionar um novo livro (`POST /livros`).
  * Implemente um endpoint para listar todos os livros (`GET /livros`).
  * Implemente um endpoint para obter um livro específico por ID (`GET /livros/:id`).
  * Implemente um endpoint para atualizar um livro por ID (`PUT /livros/:id`).
  * Implemente um endpoint para deletar um livro por ID (`DELETE /livros/:id`).

<details>

<summary>Código esperado</summary>

{% code title="index.js" lineNumbers="true" %}

```javascript
const express = require("express");
const { MongoClient, ObjectId } = require("mongodb");
const app = express();
app.use(express.json());

const dbUrl = 'mongodb+srv://<user>:<password>@cluster0.mongodb.net';
const client = new MongoClient(dbUrl);

async function main() {
  await client.connect();
  const db = client.db('biblioteca');
  const collection = db.collection('livros');

  // Endpoint para adicionar um novo livro
  app.post("/livros", async function (req, res) {
    const novoLivro = req.body;

    if (!novoLivro.titulo || !novoLivro.autor || !novoLivro.anoPublicacao) {
      return res.status(400).send('Corpo da requisição deve conter as propriedades título, autor e ano de publicação.');
    }

    await collection.insertOne(novoLivro);
    res.status(201).send(novoLivro);
  });

  // Endpoint para listar todos os livros
  app.get("/livros", async function (req, res) {
    const livros = await collection.find().toArray();
    res.send(livros);
  });

  // Endpoint para obter um livro específico por ID
  app.get("/livros/:id", async function (req, res) {
    const id = req.params.id;
    const livro = await collection.findOne({ _id: new ObjectId(id) });

    if (!livro) {
      return res.status(404).send('Livro não encontrado.');
    }

    res.send(livro);
  });

  // Endpoint para atualizar um livro por ID
  app.put("/livros/:id", async function (req, res) {
    const id = req.params.id;
    const novoLivro = req.body;

    if (!novoLivro.titulo || !novoLivro.autor || !novoLivro.anoPublicacao) {
      return res.status(400).send('Corpo da requisição deve conter as propriedades título, autor e ano de publicação.');
    }

    const resultado = await collection.updateOne({ _id: new ObjectId(id) }, { $set: novoLivro });

    if (resultado.matchedCount === 0) {
      return res.status(404).send('Livro não encontrado.');
    }

    res.send('Livro atualizado com sucesso.');
  });

  // Endpoint para deletar um livro por ID
  app.delete("/livros/:id", async function (req, res) {
    const id = req.params.id;
    const resultado = await collection.deleteOne({ _id: new ObjectId(id) });

    if (resultado.deletedCount === 0) {
      return res.status(404).send('Livro não encontrado.');
    }

    res.send('Livro deletado com sucesso.');
  });

  app.listen(3000, function () {
    console.log("Aplicação rodando em http://localhost:3000");
  });
}

main();
```

{% endcode %}

**Feedback Detalhado**

* **Verificação dos Endpoints**: Certifique-se de testar cada rota (`/livros`, `/livros/:id`, `/livros` com POST, PUT e DELETE) acessando `http://localhost:3000` e verificando as respostas.
* **Estrutura**: A estrutura básica da aplicação deve seguir a mesma lógica apresentada na missão original.
* **Diferença Sutil**: A inclusão da entidade "Livros" oferece um exercício prático de aplicação do conhecimento adquirido, sem introduzir novos conceitos.

</details>
