3
respostas

Pra caso alguém esteja com problemas na atualização do Livro - Versão Mongoose 7.1.0

Nas versões mais atuais do mongoose na publicação desta resposta (7.1.0), a maioria dos métodos estão sendo convertidos de Callback, para Promises. Por exemplo, o método findByIdAndUpdate já não funciona mais como callback, ao invéz disso, pra pegar o registro atualizado (caso encontre) podemos lançar mão da sintaxe async await ou then, observem:

static async update(req, res) {
    try {
        const { id } = req.params;
        const newBook = await book.findByIdAndUpdate(id, req.body, {
            new: true
        });

        res.status(200).json(newBook);
    } catch (error) {
        res.status(500).json({ error: error });
    }
}

Algo que não entendi ainda e estou tentando entender é, por que, que passadado um ID inexistente o erro retornado é de erro de casting de dado e não um erro do tipo not found por exemplo? O retorno é esse:

{
    "error": {
        "stringValue": "\"64553878012cfe4c92d0868\"",
        "valueType": "string",
        "kind": "ObjectId",
        "value": "64553878012cfe4c92d0868",
        "path": "_id",
        "reason": {},
        "name": "CastError",
        "message": "Cast to ObjectId failed for value \"64553878012cfe4c92d0868\" (type string) at path \"_id\" for model \"books\""
    }
}

Se alguém souber porque comenta aqui.


[UPDATE-1]

Visto que aparentemente todos os métodos findX retornam um erro da classe CastError do mongoose, eu fiz uma condição pra modificar a mensagem de retorno, como aqui:

// [...] outros imports
import { Error } from 'mongoose';

static async get(req, res) {
    try {
        const { id } = req.params;
        const book = await BookModel.findById(id);

        return res.status(200).json(book);
    } catch (error) {
        if (error instanceof Error.CastError) {
            return res.status(400).json({ error: 'book not found' });
        }
        return res.status(500).json(error);
    }
}

Porém, isso não faz muito sentido, visto que aparentemente o mongoose tem uma classe específica para tratar erro de registros não encontrados.

Notem aqui no arquivo error.d.ts que pode ser encontrado no diretório node_modules/mongoose/types/error.d.ts

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Vejam, eles especificam uma classe DocumentNotFoundError (Que acho que serviria para esse caso).

Porém olhando a documentação oficial sobre DocumentNotFoundError, noto que o método só é aplicado ao método save(), o que novamente, não entendi...

Me ajudem aí

3 respostas

Oi, Victor, tudo bem?

Muito bacana ver seu empenho em ir atrás dos porquês de cada problema, vi que você já descobriu muitas coisas por conta própria.

Sim, a versão 7 do mongoose está disponível desde fevereiro de 2023, como pode ser conferido na página Releases do github do mongoose. Se a pessoa optar por fazer o curso com essa versão, ela realmente não poderá utilizar funções callback, e ela precisaria fazer essas conversões que você demonstrou.

Caso a pessoa opte por não fazer todas essas conversões, ela pode instalar a versão 6 do mongoose no projeto, com o comando npm i mongoose@6, pois essa versão ainda aceita funções callbacks nos métodos de banco de dados.

Obrigado por indicar essa diferença entre versões!

Algo que não entendi ainda e estou tentando entender é, por que, que passadado um ID inexistente o erro retornado é de erro de casting de dado e não um erro do tipo not found por exemplo?

Eu explico sobre isso no curso que vem logo na sequência, que também fala sobre tratamento de erros, mais especificamente a atividade Para saber mais: erros do Mongoose e o ObjectId.

Vou parafrasear aqui a explicação:

O método findById receberá uma string, e o Mongoose tentará convertê-la para ObjectId, um tipo reservado dessa biblioteca. O ObjectId abstrai o tipo de mesmo nome do MongoDB. Ou seja, o MongoDB também armazena dados do tipo ObjectId, que são exatamente os IDs únicos gerados para cada documento armazenado no banco de dados.

Tanto no MongoDB quanto no Mongoose, um ObjectId deve ser uma sequência de 12 ou 24 caracteres hexadecimais. Se o método findById receber uma string que não cumpre esses requisitos, ele falhará em converter a string para o tipo ObjectId e lançará um CastError.

Ou seja, o erro CastError é lançado quando é passada uma string mal formatada no caminho da rota, que não atende aos requisitos do ObjectId (assim, na verdade faz sentido que o erro CastError seja lançado). Se você passar um ID que atende esses requisitos, mas não existe no banco de dados, o método de busca na verdade não lançará nenhum erro, e apenas retornará o valor null.

Esses casos realmente não são tratados nesse curso, apenas no seguinte, mais especificamente nesse vídeo.

É muito bacana que você já esteja se preocupando com essas questões, pois elas são abordadas no curso seguinte e as soluções são até semelhantes com essas que você propôs.

Por fim, sobre o erro DocumentNotFoundError, ele realmente só é lançado quando utilizamos o método save para cadastrar ou atualizar um registro. Ou seja, quando vamos buscar por um registro utilizando, por exemplo, o método findById, e informando um ID que não está cadastrado, o mongoose apenas retornará um valor null sem lançar um erro.

Espero ter ajudado! Abraços e bons estudos :)

Poxa, ajudou muitíssimo!!

Eu achei que estava fazendo algo de errado

Obrigado pelo suporte, abraços

Disponha, Victor, qualquer coisa estamos aqui!