Mongoose: Como find() funciona

Image for post
Image for post

alguma confusão na internet sobre o que acontece quando você chama Model.find() no Mongoose. Não se engane, Model.find() faz o que você espera: encontra todos os documentos que correspondem a uma consulta. Mas há alguma confusão entre Model.find() e Query#find(), opções de configuração, suporte a Promises. Neste artigo, fornecerei uma visão geral conceitual do que acontece quando você chama Model.find() para poder responder a perguntas semelhantes.

Configuração

Para os fins deste artigo, presumo que você já tenha uma instância do MongoDB em execução no localhost:27017. Caso contrário, confira o run-rs, ele baixa e executa o MongoDB para você, sem dependências além do Node.js. Aqui está um script independente que demonstra a criação de alguns documentos e o uso de .find():

Modelos e Consultas

O Mongoose realmente tem duas funções find(). O exemplo acima usa Model.find(), mas também existe o Query#find(). O Query#find()é abreviado para Query.prototype.find(), o .find() é um método de instância da classe Query.

Já o Model.find() retorna uma instância da classe Query do Mongoose. A classe Query representa uma operação CRUD crua (raw) que você pode enviar para o MongoDB. Ele fornece uma interface encadeada para criar consultas mais sofisticadas. Você não instancia uma Query diretamente, o Customer.find() instancia um para você.

Então, Model.find() retorna uma instância de Query. Você pode encadear chamadas .find() para adicionar operadores de consulta adicionais, também conhecidos como filtros. Por exemplo, as duas consultas a seguir encontrarão todos os clientes que o email contenha 'foo.bar' e cujo age mínimo seja 30.

Os objetos de consulta têm vários auxiliares para criar operações sofisticadas de CRUD. Os mais utilizados são Query#sort(), Query#limit() e Query#skip().

Uma grande vantagem do Mongoose é que o Mongoose lança consultas para corresponder ao esquema do modelo. Isso significa que você não precisa converter explicitamente cadeias de caracteres para ObjectIds ou se preocupar com as nuances de converter cadeias de caracteres em números.

Opções de configuração

Os ajudantes sort(), limit() e skip() modificam as opções de consulta. Por exemplo, o query.getOptions() abaixo retornará um objeto que contém sort e limit propriedades.

A função Model.find() usa três argumentos que ajudam a inicializar uma consulta sem encadeamento. O primeiro argumento é o filtro de consulta (também conhecido como conditions). O segundo argumento é a projeção da consulta, que define quais campos incluir ou excluir da consulta. Por exemplo, se você deseja excluir o campo email por questões de privacidade, pode usar uma das sintaxes abaixo.

O terceiro argumento de Model.find() é as opções gerais de consulta. Aqui está uma lista completa de opções . Por exemplo, você pode definir limit e skip no terceiro argumento.

Perceba que o Model.find() tem uma assinatura de função diferente do que a função collection.find() do driver do MongoDB. O driver do MongoDB leva apenas 2 argumentos, filter e options. Para converter uma chamada find() de driver do MongoDB em uma chamada Model.find() do Mongoose, sem encadeamento, adicione null como o segundo argumento.

Promises e Async/Await

Model.find() retorna uma instância de consulta, então por que você pode fazer await Model.find()? Isso ocorre porque uma consulta do Mongoose é um thenable, o que significa que eles têm uma função .then(). Isso significa que você pode usar as consultas da mesma maneira que Promises, inclusive com o encadeamento de delas, como mostrado abaixo.

As consultas também têm uma função .catch(). Em geral, um thenablenão precisa ter uma função .catch(), mas o Mongoose adicionou uma para sua conveniência. Abaixo está um exemplo de .catch() e como manipular um número incorreto na sua consulta.

As consultas são editáveis, mas as consultas não são Promises. Em alguns casos, você pode precisar de uma Promise, não apenas de um thenable. Por exemplo, você pode estar usando TypeScript em modo strict ou pode estar usando o módulo cls-hooked. A função Query#exec() retorna uma Promise completa.

Continuando

Encontrar todos os documentos que correspondem a uma consulta no Mongoose é intuitivo, mas há nuances que aparecem quando você vai além das consultas mais básicas. O Mongoose permite estruturar consultas usando encadeamento ou, equivalentemente, usando POJOs em uma única chamada de função. Model.find() retorna uma consulta, que possui um método .find() separado que permite anexar filtros adicionais. As consultas não são Promises, mas são próximas o suficiente para a maioria dos usos práticos. Lembre-se desses três conceitos e você saberá o suficiente para resolver os problemas mais comuns do Mongoose.

Créditos

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store