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

gre*_*emo 102 mongoose mongodb

当发送请求/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);
    });
  };
Run Code Online (Sandbox Code Playgroud)

但是,如果_id不匹配Mongoose所期望的"格式"(我想),例如GET /customers/foo返回一个奇怪的错误:

CastError:对于路径"_id"处的值"foo",转换为ObjectId失败.

那么这个错误是什么?

Joh*_*yHK 163

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.
}
Run Code Online (Sandbox Code Playgroud)

  • @Gremo你只能在Mongoose模式中选择一个用于`_id`的类型.在``bla"`的情况下,你会使用一种`String`而不是默认的`ObjectId`,你不需要添加这个检查,因为任何东西都可以强制转换为字符串. (3认同)
  • 我了解,但我想避免进行此检查。如何从给定的字符串(从“ GET”请求中)创建一个新的“ ObjectId”,以将其传递给“ findById”方法? (2认同)
  • 您可以使用 find({_id: yourId},...) 来查询具有该(唯一)ID 的文档。那,以及 JohnnyHK 将 _id 添加到您的架构(使用您想要的“字符串”类型)的答案是您问题的完整解决方案。 (2认同)
  • 现在,也可以将 12 个字符串转换为 ObjectId。`ObjectId("000000000000") --> 303030303030303030303030` (2认同)

xpe*_*int 38

使用现有函数检查ObjectID.

var mongoose = require('mongoose');
mongoose.Types.ObjectId.isValid('your id here');
Run Code Online (Sandbox Code Playgroud)

  • 小心使用该方法,因为它具有将任何12字节字符串视为有效的奇怪行为.所以它甚至会为你的'你的身份'这个例子返回真实.https://github.com/mongodb/js-bson/issues/106 (14认同)

Har*_*rma 27

如果您有两条不同的路线,如下所示,这可能是路线不匹配的情况

router.route("/order/me") //should come before the route which has been passed with params
router.route("/order/:id")
Run Code Online (Sandbox Code Playgroud)

那么你必须小心地将使用参数的路线放在对我有用的常规路线之后

  • 嘿@IamToobDude 在这种情况下,通常会发生的情况是,当您使用参数高于简单路线的路线时,那么在这种情况下,您传递的任何参数都将与该路线匹配例如 /order/e5h57f 这里 e5h57f 是 id 所以它将与 /order/:id 路由匹配,在这种情况下我们不会看到任何问题,但如果路由是 /order/me 或 /order/profile 在这种情况下,它也会再次与 /order/:id 匹配,因为在执行 'me 时' 或 'profile' 将被视为 /order/:id 中的 :id 它只是在匹配 id 参数时不检查用法。 (3认同)

Rya*_*gel 16

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

// 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);
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用。我很好奇这个错误背后的原因。您能否解释一下将路线移至常规路线下方如何导致错误消失? (5认同)
  • 这对我也有用。看起来 /test/create 满足这个 /test/:id 和 id=create 。并且字符串不能转换为_id。 (2认同)

Blo*_*gic 12

当您将无效的 id 传递给 mongoose 时,就会发生这种情况。isValid所以在继续之前首先使用 mongoose函数检查它

import mongoose from "mongoose";

// add this inside your route
if( !mongoose.Types.ObjectId.isValid(id) ) return false;
Run Code Online (Sandbox Code Playgroud)


gus*_*nke 11

你在解析那个字符串ObjectId吗?

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

ObjectId.fromString( myObjectIdString );
Run Code Online (Sandbox Code Playgroud)

  • 试试 `mongoose.Types.ObjectId`。 (2认同)
  • `fromString` 不是函数 (2认同)

Cro*_*asr 8

就我而言,我必须添加_id: Object到我的架构中,然后一切正常。


thi*_*ous 7

截至2019年11月19日

您可以isValidObjectId(id)从 mongoose 版本 5.7.12 开始使用

https://mongoosejs.com/docs/api/mongoose.html#mongoose_Mongoose-isValidObjectId


小智 5

 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"});
        }
Run Code Online (Sandbox Code Playgroud)

最好是检查有效性


s.b*_*bar 5

我在添加
_id时遇到了同样的问题:String .in schema然后它开始工作