web-dev-qa-db-fra.com

Qu'est-ce que l'erreur Mongoose Cast en ObjectId a échoué pour la valeur XXX au chemin "_id"

Lors de l'envoi d'une demande à /customers/41224d776a326fb40f000001 et qu'un document avec _id41224d776a326fb40f000001 n'existe pas, doc est null et je retourne un 404:

  Controller.prototype.show = function(id, res) {
    this.model.findById(id, function(err, doc) {
      if (err) {
        throw err;
      }
      if (!doc) {
        res.send(404);
      }
      return res.send(doc);
    });
  };

Cependant, lorsque _id ne correspond pas à ce que Mongoose attend comme "format" (je suppose), par exemple avec GET /customers/foo, une erreur étrange est renvoyée:

CastError: La conversion vers ObjectId a échoué pour la valeur "foo" sur le chemin "_id".

Alors, quelle est cette erreur?

77
gremo

La méthode findById de Mongoose convertit le paramètre id dans le type du champ _id du modèle afin qu'il puisse interroger correctement le document correspondant. Ceci est un ObjectId mais "foo" n'est pas un ObjectId valide et la conversion échoue.

Cela n'arrive pas avec 41224d776a326fb40f000001 car cette chaîne est un ObjectId valide.

Une façon de résoudre ce problème consiste à ajouter une vérification avant votre appel findById pour voir si id est un ObjectId valide ou différent de celui-ci:

if (id.match(/^[0-9a-fA-F]{24}$/)) {
  // Yes, it's a valid ObjectId, proceed with `findById` call.
}
134
JohnnyHK

Utilisez les fonctions existantes pour vérifier ObjectID.

var mongoose = require('mongoose');
mongoose.Types.ObjectId.isValid('your id here');
29
xpepermint

Est-ce que vous analysez cette chaîne en tant que ObjectId?

Ici, dans mon application, ce que je fais est:

ObjectId.fromString( myObjectIdString );
10
gustavohenke

Vous pouvez également utiliser ObjectId.isValid comme suit: 

if (!ObjectId.isValid(userId)) return Error({ status: 422 })
3
Ze Rubeus

J'ai le même problème que j'ajoute
_ id: String .in schema puis il commence à fonctionner

1
s.babar

C'est une vieille question, mais vous pouvez également utiliser le paquet express-validator pour vérifier les paramètres de la demande.

validateur express version 4 (dernière):

validator = require('express-validator/check');

app.get('/show/:id', [

    validator.param('id').isMongoId().trim()

], function(req, res) {

    // validation result
    var errors = validator.validationResult(req);

    // check if there are errors
    if ( !errors.isEmpty() ) {
        return res.send('404');
    }

    // else 
    model.findById(req.params.id, function(err, doc) { 
        return res.send(doc);
    });

});

validateur express version 3:

var expressValidator = require('express-validator');
app.use(expressValidator(middlewareOptions));

app.get('/show/:id', function(req, res, next) {

    req.checkParams('id').isMongoId();

    // validation result
    req.getValidationResult().then(function(result) {

        // check if there are errors
        if ( !result.isEmpty() ) {
            return res.send('404');
        }

        // else
        model.findById(req.params.id, function(err, doc) {
            return res.send(doc);
        });

    });

});
1
YouneL
 if(mongoose.Types.ObjectId.isValid(userId.id)) {
        User.findById(userId.id,function (err, doc) {
            if(err) {
                reject(err);
            } else if(doc) {
                resolve({success:true,data:doc});
            } else {
                reject({success:false,data:"no data exist for this id"})

            }
        });
        } else {
            reject({success:"false",data:"Please provide correct id"});
        }

le mieux est de vérifier la validité

1
yogesh agrawal

J'ai dû déplacer mes itinéraires par-dessus d'autres itinéraires capturant les paramètres d'itinéraire:

// require express and express router

const express = require("express");
const router = express.Router();

// move this `/post/like` route on top

router.put("/post/like", requireSignin, like);

// keep the route with route parameter `/:postId` below regular routes

router.get("/post/:postId", singlePost);
0
Ryan Dhungel

La façon dont je résous ce problème est de transformer l'identifiant en une chaîne

je l'aime fantaisie avec backtick: `${id}`

cela devrait résoudre le problème sans surcharge

0
AiU

Je suis allé avec une adaptation de la solution @gustavohenke, en implémentant ObjectId cast dans un try-catch encapsulé autour du code d'origine pour tirer parti de l'échec de la conversion ObjectId comme méthode de validation.

Controller.prototype.show = function(id, res) {
  try {
    var _id = mongoose.Types.ObjectId.fromString(id);



    // the original code stays the same, with _id instead of id:

    this.model.findById(_id, function(err, doc) {
      if (err) {
        throw err;
      }
      if (!doc) {
        res.send(404);
      }
      return res.send(doc);
    });



  } catch (err) {
    res.json(404, err);
  }
};
0
Charney Kaye

Utilisez toujours les conditions mongoose.Types.ObjectId('your id')for dans votre requête pour valider le champ d'identifiant avant de l'exécuter. Ainsi, votre application ne plantera pas.

0
Suman

ObjectId est composé des éléments suivants.

  1. une valeur de 4 octets représentant les secondes depuis l'époque Unix
  2. une valeur aléatoire de 5 octets (identifiant d'ordinateur 3 octets et identifiant de processeur 2 octets)
  3. un compteur de 3 octets, commençant par une valeur aléatoire

La méthode correcte pour valider si objectId est valide consiste à utiliser la méthode statique de la classe ObjectId elle-même.

mongoose.Types.ObjectId.isValid (sample_object_id)

0
Sushil Kadu

OU vous pouvez le faire

var ObjectId = require('mongoose').Types.ObjectId; var objId = new ObjectId( (param.length < 12) ? "123456789012" : param );

comme mentionné ici La méthode de recherche de Mongoose avec $ ou condition ne fonctionne pas correctement

0
Madhu Kumar

Détection et correction de l'erreur ObjectID

Je suis tombé sur ce problème en essayant de supprimer un article en utilisant de la mangouste et j'ai eu la même erreur. Après avoir examiné la chaîne de retour, j'ai trouvé qu'il y avait des espaces supplémentaires à l'intérieur de la chaîne renvoyée qui ont provoqué l'erreur pour moi. J'ai donc appliqué quelques-unes des réponses fournies ici pour détecter l'identifiant erroné, puis supprimer les espaces supplémentaires de la chaîne. Voici le code qui a fonctionné pour moi pour enfin résoudre le problème.

const mongoose = require("mongoose");
mongoose.set('useFindAndModify', false);  //was set due to DeprecationWarning: Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the `useFindAndModify`



app.post("/delete", function(req, res){
  let checkedItem = req.body.deleteItem;
  if (!mongoose.Types.ObjectId.isValid(checkedItem)) {
    checkedItem = checkedItem.replace(/\s/g, '');
  }

  Item.findByIdAndRemove(checkedItem, function(err) {
    if (!err) {
      console.log("Successfully Deleted " + checkedItem);
        res.redirect("/");
      }
    });
});

Cela a fonctionné pour moi et je suppose que si d'autres éléments commencent à apparaître dans la chaîne de retour, ils peuvent être supprimés de la même manière.

J'espère que ça aide.

0
Jim Bray
//Use following to check if the id is a valid ObjectId?

var valid = mongoose.Types.ObjectId.isValid(req.params.id);
if(valid)
{
  //process your code here
} else {
  //the id is not a valid ObjectId
}
0
Brajalal Pal

Chaîne de chaîne en ObjectId

import mongoose from "mongoose"; // ES6 or above
const mongoose = require('mongoose'); // ES5 or below

let userid = _id
console.log(mongoose.Types.ObjectId(userid)) //5c516fae4e6a1c1cfce18d77
0
WasiF

Si quelqu'un se heurte à cela, ce qui a résolu le problème pour moi a été de passer d'une citation unique dans l'exigence à ".

Au lieu de:

const something = require('./models/something');

utilisation:

const something = require(`./models/something`);

Sachez que ça a l'air drôle, mais que ça fonctionne.

0
Yossi Saadi