Operações de CRUD com MongoDB
Tags: ptbr, braziliandevs, mongodb, beginners
Published: 2021-02-07 01:09:20

- [Inserindo documentos](#inserindo-documentos)
  - [Inserindo um documento](#inserindo-um-documento)
  - [Inserindo vários documentos ao mesmo tempo](#inserindo-vários-documentos-ao-mesmo-tempo)
- [Buscando por documentos](#buscando-por-documentos)
  - [Buscando todos os documentos da coleção](#buscando-todos-os-documentos-da-coleção)
  - [Buscando por algum campo especifico](#buscando-por-algum-campo-especifico)
  - [Definindo quais campos do documento queremos que sejam retornados](#definindo-quais-campos-do-documento-queremos-que-sejam-retornados)
  - [Busca com paginação](#busca-com-paginação)
  - [Buscando documentos com expressões regulares](#buscando-documentos-com-expressões-regulares)
  - [Buscando documentos a partir de informações de sub documentos](#buscando-documentos-a-partir-de-informações-de-sub-documentos)
  - [Buscando documentos a partir de informações de sub listas](#buscando-documentos-a-partir-de-informações-de-sub-listas)
  - [Buscando documentos utilizando operador $in](#buscando-documentos-utilizando-operador-in)
- [Atualizando documentos](#atualizando-documentos)
  - [Substituindo um documento inteiro](#substituindo-um-documento-inteiro)
  - [Atualizando parte de um documento](#atualizando-parte-de-um-documento)
  - [Atualizando muitos documentos](#atualizando-muitos-documentos)
  - [Atualizando campo de um documento de forma incremental](#atualizando-campo-de-um-documento-de-forma-incremental)
  - [Atualizando sub lista de documento com novos registros](#atualizando-sub-lista-de-documento-com-novos-registros)
- [Deletando documentos](#deletando-documentos)
- [Conclusão](#conclusão)

Gostaria de compartilhar com vocês e também para consulta própria no futuro, algumas das operações disponíveis no MongoDB para inserir, atualizar, buscar e deletar dados em coleções de documentos no MongoDB.

Vamos começar criando uma coleção de documentos chamada `posts`, onde vamos inserir alguns documentos que representam um post feito em um blog, depois vamos manipular suas informações.

```js
// Input
db.createCollection("posts");
// Output
{
    "ok" : 1
}
```

Pronto, já temos nossa coleção chamada `posts`.

## Inserindo documentos

Como estamos trabalhando com um banco de dados orientado a documentos, isso significa que cada **registro** em nosso banco é um **documento**. Esse documento basicamente é um JSON qual podemos adicionar nossas informações, incluindo sub documentos e sub listas de documentos. Lembrando que cada documento de uma coleção não pode passar de _16MB_ de dados. Também não pode ultrapassar 100 níveis de sub documentos.

### Inserindo um documento

Vamos inserir um documento que representa nosso post do blog, utilizando a função `insertOne`.

```js
// Input
db.posts.insertOne({
  title: "Introdução a banco de dados NoSQL",
  content: "...",
  categories: [ "database", "nosql", "mongodb"],
  author: { name: "Marcelo Michels", about: "..."},
  likes: 0
});
// Output
{
    "insertedId" : ObjectId("601ea27a4fb18f6b8e31fd3c")
}
```

A função `insertOne` retornou um `insertedId` que vai ser o identificador do nosso documento. Esse identificador que o MongoDB gerou automaticamente vai ficar salvo dentro de um campo do nosso documento chamado _\_id_. Caso seja informado um campo chamado _\_id_ dentro do nosso JSON que estamos salvando, o MongoDB não vai gerar um novo valor para ele, e vai considerar a informação que estamos passando.

### Inserindo vários documentos ao mesmo tempo

Também podemos inserir mais do que um documento ao mesmo tempo utilizando a função `insertMany`.

```js
// Input
db.posts.insertMany([
  {
    title: "Introdução a Rust",
    content: "...",
    categories: ["languages", "rust"],
    author: { name: "Marcelo Michels", about: "..." },
    likes: 0,
  },
  {
    title: "Fazendo backup automatizado do MongoDB",
    content: "...",
    categories: ["database", "nosql", "mongodb", "infra"],
    author: { name: "Marcelo Michels", about: "..." },
    likes: 0,
  },
  {
    title: "Performance para páginas WEB",
    content: "...",
    categories: ["performance", "front-end"],
    author: { name: "Marcelo Michels", about: "..." },
    likes: 0,
  },
  {
    title: "Introdução a PWA",
    content: "...",
    categories: ["front-end", "pwa"],
    author: { name: "Joaquim Augusto Michels", about: "..." },
    likes: 0,
  },
]);
// Output
{
    "insertedIds" : [
        ObjectId("601ed2614fb18f6b8e31fd43"),
        ObjectId("601ed2614fb18f6b8e31fd44"),
        ObjectId("601ed2614fb18f6b8e31fd45"),
        ObjectId("601ed2614fb18f6b8e31fd46")
    ]
}
```

## Buscando por documentos

Com alguns registros já inseridos na nossa coleção de `posts`, já podemos buscar as informações que tem nela. Abaixo veremos algumas das operações de buscas que temos.

### Buscando todos os documentos da coleção

Para buscar todos os registros de uma coleção usaremos o a função `find`.

```js
// Input
db.posts.find({});
// Output
[
  {
    "_id" : ObjectId("601ed2504fb18f6b8e31fd42"),
    "title" : "Introdução a banco de dados NoSQL",
    "content" : "...",
    "categories" : [ "database", "nosql", "mongodb" ],
    "author" : { "name" : "Marcelo Michels", "about" : "..." },
    "likes" : 0
  }
,
  ...
]
// colei aqui apenas a primeira linha do que foi retornado
// mas no total foram 5 documentos quais inserimos anteriormente
```

Podemos observar que dentro de cada documento temos o campo `_id` ObjectId que foi gerado automaticamente pelo MongoDB para cada registro

### Buscando por algum campo especifico

Para buscar um documento a partir de alguma referencia que necessitamos basta passarmos um JSON para função `find`. Nesse JSON vamos passar apenas os campos quais queremos fazer a busca, no exemplo abaixo estamos passando um JSON contendo apenas o campo chamado _title_, isso significa que todos os documentos que tiverem o _title_ igual ao que estamos passando no JSON serão retornando na nossa consulta.

```js
// Input
db.posts.find({title: "Introdução a PWA"});
// Output
{
    "_id" : ObjectId("601ed2614fb18f6b8e31fd46"),
    "title" : "Introdução a PWA",
    "content" : "...",
    "categories" : [  "front-end", "pwa" ],
    "author" : { "name" : "Marcelo Michels", "about" : "..." },
    "likes" : 0
}
```

### Definindo quais campos do documento queremos que sejam retornados

Na função `find` podemos passar no primeiro parâmetro um JSON para a consulta que desejamos, assim como também podemos passar no segundo parâmetro quais campos dos documentos queremos que sejam retornados para utilizarmos.
No exemplo abaixo vamos passar no primeiro parâmetro `{}`, isso vai retornar todos os posts, no segundo parâmetro vamos passar o JSON `{ title: 1}` o que sinaliza que queremos que seja retornado apenas o campo `title` de cada documento, porem o campo `_id` sempre vai ser retornado, a não ser que indiquemos que não o queremos da seguinte forma `{ _id: 0, title: 1}`, ou seja, nesse segundo JSON passamos `0` para os campos que não queremos e `1` para os campos que queremos.

```js
// Input
db.posts.find({}, { _id: 0, title: 1 });
// Output
[
  { title: "Introdução a banco de dados NoSQL" },
  { title: "Introdução a Rust" },
  { title: "Fazendo backup automatizado do MongoDB" },
  { title: "Performance para páginas WEB" },
  { title: "Introdução a PWA" },
];
```

### Busca com paginação

Em casos onde temos muitos documentos, buscar esses documentos em quantidades menores pode ser uma boa opção, para isso podemos acrescentar ao `find` as funções `skip` e `limit` onde define quantos registros ignorar e quantos registros retornar, respectivamente.

```js
// Input
db.posts.find({}, { _id: 0, title: 1 }).skip(1).limit(3);
// Output
[
  { title: "Introdução a Rust" },
  { title: "Fazendo backup automatizado do MongoDB" },
  { title: "Performance para páginas WEB" },
];
```

### Buscando documentos com expressões regulares

No JSON que passamos para a função `find` também podemos passar expressões regulares, ampliando nossas possibilidades de buscas, permitindo por exemplo, buscar todos os usuários que tenham um e-mail valido, entre outros tipos de validações, no exemplo atual vamos buscar por todos os `posts` que contenham no titulo do post a palavra `Introdução` e vamos querer apenas o `title` de cada post.

```js
// Input
db.posts.find({ title: /Introdução/ }, { _id: 0, title: 1 });
// Output
[
  { title: "Introdução a banco de dados NoSQL" },
  { title: "Introdução a Rust" },
  { title: "Introdução a PWA" },
];
```

### Buscando documentos a partir de informações de sub documentos

Nosso documento de `posts` contem dentro dele um sub documento que contem os dados do autor, caso queiramos buscar todos os documentos de `posts` filtrando pelos dados do sub documento `author` também é possível e muito fácil.

```js
// Input
db.posts.find(
  { "author.name": "Joaquim Augusto Michels" },
  { _id: 0, title: 1 }
);
// Output
[{ title: "Introdução a PWA" }];
```

### Buscando documentos a partir de informações de sub listas

Vamos buscar um documento a partir de uma informação que está dentro de uma sub lista no nosso documento, que no caso é a lista de categorias que ficam dentro do campo `categories`.

```js
// Input
db.posts.find({ categories: "database" }, { _id: 0, title: 1 });
// Output
[
  { title: "Introdução a banco de dados NoSQL" },
  { title: "Fazendo backup automatizado do MongoDB" },
];
```

### Buscando documentos utilizando operador $in

Mongo nos ofere alguns operadores para agregamos mais poderes em nossas buscas, um deles é o `$in`, podemos encontrar mais alguns na documentação em <https://docs.mongodb.com/manual/reference/operator/>.

```js
// Input
db.posts.find(
  { categories: { $in: ["infra", "performance"] } },
  { _id: 0, title: 1 }
);
// Output
[
  { title: "Fazendo backup automatizado do MongoDB" },
  { title: "Performance para páginas WEB" },
];
```

## Atualizando documentos

Já aprendemos inserir e buscar dados em uma coleção do MongoDB, agora vamos atualizar alguns desses documentos para depois realizarmos umas consultas mais avançadas.

### Substituindo um documento inteiro

Utilizaremos a função `updateOne` qual no primeiro parâmetro espera um JSON para localizar o
Quando queremos substituir todas as informações do documento por um novo documento passamos no segundo parâmetro um operador `$replaceWith` que é onde vai ser passado o novo documento a

```js
// Input
db.posts.updateOne(
  { title: "Performance para páginas WEB" },
  [
    {
      "$replaceWith": {
        title: "Performance em páginas WEB",
        content: "...",
        categories: ["performance", "front-end"],
        author: { name: "Marcelo Michels", about: "..." },
        likes: 0,
      },
    },
  ]
);
// Output
{
    "matchedCount" : 1,
    "modifiedCount" : 1
}
```

### Atualizando parte de um documento

Para atualizar parte de um documento utilizaremos o operador `$set` no lugar de `$replaceWith`, dessa forma o JSON que passarmos dentro desse operador será adicionado ao documento sem modificar as demais informações do documento (como se fosse um merge entre o documento que já está salvo e o JSON que estamos enviando no $set).
Dessa forma vamos atualizar a quantidade de likes de um post para 1.

```js
// Input
db.posts.updateOne(
  { title: "Introdução a banco de dados NoSQL" },
  [
    {
      "$set": {
        likes: 1,
      },
    },
  ]
);
// Output
{
    "matchedCount" : 1,
    "modifiedCount" : 1
}
```

### Atualizando muitos documentos

Caso queira atualizar muitos documentos utilizaremos a função `updateMany`, onde pode atualizar mais que um documento na mesma operação, assim todos os documentos que se aplicarem na query no primeiro parâmetro serão atualizados. Da mesma forma que buscamos todos os documentos passando um JSON vazio, para atualizar todos os documentos passamos um JSON vazio também na query do nosso `updateMany`.

```js
// Input
db.posts.updateMany(
  { },
  [
    {
      "$set": {
        published: true,
      },
    },
  ]
);
// Output
{
    "matchedCount" : 5,
    "modifiedCount" : 5
}
```

Com a operação acima todos os nossos posts receberam o campo `published` com valor `true`.

### Atualizando campo de um documento de forma incremental

Seguindo o comando anterior `$set`, cada vez que um post receber um like teríamos que buscar o post para saber quantos likes ele tinha para adicionar mais 1 nesse valor e salvar a informação novamente, mas com o operador `$inc` podemos apenas incrementar o valor que já temos salvo com o valor que queremos incrementar.

```js
// Input
db.posts.updateOne(
  { title: "Introdução a banco de dados NoSQL" },
  {
    "$inc": {
      likes: 1,
    },
  }
);
// Output
{
    "matchedCount" : 1,
    "modifiedCount" : 1
}
```

### Atualizando sub lista de documento com novos registros

Vamos imaginar os comentários de um post, caso queiramos gravar eles dentro de uma sub lista do nosso documento vamos precisar utilizar o operador `$push`

```js
// Input
db.posts.updateOne(
  { title: "Introdução a banco de dados NoSQL" },
  {
    "$push": {
      "comments": {
        "$each": [{
          "name" : "Marcelo"
          "message": "Muito legal, parabéns"
        }]
      }
    }
  }
);
// Output
{
    "matchedCount" : 1,
    "modifiedCount" : 1
}
```

## Deletando documentos

Com base no conhecimento nas operações que já temos deletar um documento não se torna muito diferente do que já aprendemos, então segue abaixo um exemplo com a utilização da função `remove`, usando também um operador novo `$lte` (qual também pode ser usado no `find`) que retorna todos os documentos que tenham um determinado campo com valor menor do que estamos passando na _query_.
Com o `remove` abaixo estamos removendo todos posts que o campo `likes` seja menor ou igual a 1.

```js
// Input
db.posts.remove({ "likes": { "$lte": 1 } });
// Output
Removed 4 record(s)
```

Consulte também outros operador de maior e menor <https://docs.mongodb.com/manual/reference/operator/query-comparison/>

## Conclusão

Se você executou todos os comandos que aprendemos aqui, na nossa coleção de `posts` deve ter sobrado apenas um único documento igualmente o que consta abaixo.

```js
{
    "_id" : ObjectId("601ed2504fb18f6b8e31fd42"),
    "title" : "Introdução a banco de dados NoSQL",
    "content" : "...",
    "categories" : [
        "database",
        "nosql",
        "mongodb"
    ],
    "author" : {
        "name" : "Marcelo Michels",
        "about" : "..."
    },
    "likes" : 2,
    "published" : true,
    "comments" : [
        {
            "name" : "Marcelo",
            "message" : "Muito legal, parabéns"
        }
    ]
}
```

Espero utilizar desses exemplos no futuro e espero que possa ser útil para alguém também.