什么是Mongoose错误对于路径“_id”的值XXX,对ObjectId的转换失败?

问题描述 投票:86回答:16

当向/customers/41224d776a326fb40f000001发送请求和_id 41224d776a326fb40f000001的文件不存在时,docnull,我正在返回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);
    });
  };

然而,当_id与Mongoose所期望的“格式”(我猜)例如与GET /customers/foo不匹配时,会返回一个奇怪的错误:

CastError:对于路径“_id”处的值“foo”,转换为ObjectId失败。

那么这个错误是什么?

mongodb mongoose
16个回答
150
投票

Mongoose的findById方法将id参数强制转换为模型的_id字段的类型,以便它可以正确查询匹配的doc。这是一个ObjectId,但是"foo"不是有效的ObjectId,因此转换失败。

41224d776a326fb40f000001不会发生这种情况,因为该字符串是有效的ObjectId。

解决此问题的一种方法是在findById调用之前添加一个检查,以查看id是否是有效的ObjectId,如下所示:

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

0
投票

或者你可以这样做

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

正如这里提到的Mongoose's find method with $or condition does not work properly


0
投票

始终在查询中使用mongoose.Types.ObjectId('your id')for条件,它将在运行查询之前验证id字段,因此您的应用程序不会崩溃。


0
投票

我解决这个问题的方法是将id转换为字符串

我喜欢用反击来表达:`${id}`

这应该解决问题没有开销


0
投票

ObjectId由以下内容组成。

  1. 一个4字节的值,表示自Unix纪元以来的秒数
  2. 一个5字节的随机值(机器ID 3字节和处理器ID 2字节)
  3. 一个3字节的计数器,以随机值开始。

验证objectId是否有效的正确方法是使用ObjectId类本身的静态方法。

mongoose.Types.ObjectId.isValid(sample_object_id)


0
投票

将字符串转换为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
投票

我不得不将我的路线移到其他捕捉路线参数的路线上:

// 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
投票

检测并纠正ObjectID错误 当我尝试使用mongoose删除项目并遇到同样的错误时,我偶然发现了这个问题。查看返回字符串后,我发现返回的字符串中有一些额外的空格,这导致了我的错误。所以,我应用了这里提供的一些答案来检测错误的id,然后从字符串中删除多余的空格。以下是最终解决问题的代码。

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("/");
      }
    });
});

这对我有用,我假设如果其他项目开始出现在返回字符串中,则可以以类似的方式删除它们。

我希望这有帮助。


33
投票

使用现有函数检查ObjectID。

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

11
投票

你是否将该字符串解析为ObjectId

在我的应用程序中,我所做的是:

ObjectId.fromString( myObjectIdString );

3
投票

您还可以使用ObjectId.isValid,如下所示:

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

2
投票

我有同样的问题我添加 _id:String .in架构然后它开始工作


1
投票

这是一个老问题,但您也可以使用express-validator包来检查请求参数

express-validator版本4(最新):

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);
    });

});

express-validator版本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
投票
 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"});
        }

最好是检查有效性


1
投票
//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
投票

我选择了@gustavohenke解决方案,在原始代码的try-catch中实现了强制转换ObjectId,以利用ObjectId转换失败作为验证方法。

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);
  }
};
© www.soinside.com 2019 - 2024. All rights reserved.