Filtrando campos retornados em buscas com MongoDB
Tags: mongodb, mongoose, javascript, node
Published: 2020-04-11 20:58:33

##Filtrando campos em SQL

Se você já usou bancos relacionais, com certeza já se deparou com as famosas querys de busca, coisas como:
```
select nome, idade from usuario
``` 
Muito comuns e úteis, já que nem sempre queremos todas as colunas de uma tabela.


##Mas e no MongoDB ?

Bom, geralmente aprendemos em vários eventos e cursos as funções básicas para fazer o famoso __CRUD__ *(Create, read, update, delete)*, com __mongoose__, que são ótimos para dar uma base prática a quem acaba de conhecer a tecnologia e dar ideias de desafios para quem já domina a tecnologia, nesses cursos aprendemos a fazer buscar com condições como essa:

```JavaScript
const user = await User.find({name: "Nome do alvo"})
```

E como sabemos, isso retorna todo o Schema (modelo especificado por nós do documento) do usuário, cujo nome seja "Nome do alvo". Vamos supor que esse seja o Schema do User:

```JavaScript
const UserSchema = new mongoose.Schema({
    name: {
        required: true,
        type: String,
        unique: false
    },
    githubUser: {
        required: true,
        type: String, 
        unique: true
    },
    bio: {
        required: false,
        type: String,
        unique: false
    },
    avatar_url: {
        required: true,
        type: String,
        unique: true
    },
    techs: [String]
    githubFollowers: [UserSchema],
    githubFollowing: [UserSchema]
});
```

Suponha que em dado momento da nossa aplicação, somente nos importe buscar os dados { name, githubUser, avatar_url }, não faz sentido buscarmos todos os dados se apenas queremos estes!

##O segundo parâmetro do método find
Para resolvermos esse problema da requisição desnecessária de campos, podemos usar o segundo parâmetro do métodos find, chamado __Projection__, um JSON em que podemos filtrar quais campos queremos que sejam retornados, ou não, exemplo:

```JavaScript
/*
  O 1 indica a inclusão do campo no retorno da query
  os demais campos não serão inclusos
*/
{
 name: 1,
 githubUser: 1,
 avatar_url: 1
}
/*
  O 0 indica a exclusão do campo no retorno da query
  os demais campos serão inclusos
*/
{
 bio: 0,
 techs: 0,
 githubFollowers: 0,
 githubFollowing: 0
}
```

###IMPORTANTE: NÃO SE PODE MISTURAR 1s E 0s NA MESMA PROJEÇÃO!

Assim, temos o mesmo resultado nos dois casos! Filtramos então os campos para recebermos { name, githubUser, avatar_url }!

##Mas como ficaria isso no código? Como se parece a resposta dessa query?

```JavaScript
//Query
const result = await Dev.find({name: "Algum nome"},{name:1, githubUser: 1, avatar_url: 1})

//Resposta
 {
    "_id": "Array do ID",
    "name": "Pedro Victor",
    "githubUser": "stormsamurai1",
    "avatar_url": "https://avatars2.githubusercontent.com/u/37453874?v=4"
  }
```
##PROBLEMA DE VIRTUALS!!!
Se você usa algum campo virtual no seu modelo, provavelmente vai se deparar com um problema: __Os campos virtuais não são afetados.__
Bem, isso ocorre por eles não persistirem no banco de dados, e, por isso, não temos tanto controle, mas isso não será um problema, podemos adicionar uma função a mais para remover esses campos e resolver o empecilho. __Trata-se da função lean()__

```JavaScript
//Antes do lean
{
    "_id": "Array do ID",
    "name": "Pedro Victor",
    "githubUser": "stormsamurai1",
    "avatar_url": "https://avatars2.githubusercontent.com/u/37453874?v=4",
    "virtual_field": "virtual result",
    "id": "5e7aa3fc0cf9ea14d47fa461"
}
```
```JavaScript
//Query atualizada
const result = await Dev.find({},{name:1, githubUser:1, avatar_url:1}).lean()
```
```JavaScript
//Resultado atualizado
{
    "_id": "Array do ID",
    "name": "Pedro Victor",
    "githubUser": "stormsamurai1",
    "avatar_url": "https://avatars2.githubusercontent.com/u/37453874?v=4",
}   
```


##Conclusão
Apesar de ser um tema básico, é algo que senti vontade de escrever, via poucas pessoas utilizando essas funções e vi uma boa oportunidade de explorar o tema, pesquisar e começar com um projeto de escrita sobre coisas que aprendi. Qualquer dúvida que tenha, entre em contato! Críticas construtivas? Por favor, diga! É isto, obrigado a quem leu!