对于模型的路径“_id”处的值,转换为 ObjectId 失败

Posted

技术标签:

【中文标题】对于模型的路径“_id”处的值,转换为 ObjectId 失败【英文标题】:Cast to ObjectId failed for value at path "_id" for model 【发布时间】:2021-05-12 17:03:30 【问题描述】:

错误是

Cast to ObjectId failed for value "hist" at path "_id" for model "books"

你好!

问题:

我正在尝试在另一个模型中使用其他模型,确切地说,一个模型中有两个模型。型号如下

models: 
   'Professor'
   'Book'

我想在另一个名为 checkoutHistory 的猫鼬模型中使用模式。

据我了解,为了做到这一点,我需要这样做

type: mongoose.Schema.Types.ObjectID, ref: 'book'

这是我要从中创建和检索数据的模型。

const  mongoose = require('mongoose');
const Schema = mongoose.Schema;


const checkoutHistory = new Schema(
    book:  type: mongoose.Schema.Types.ObjectId, ref: 'books',required: true ,
    checkoutCopiesNum: type: Number, required: true,
    profChosen:  type: mongoose.Schema.Types.ObjectId, ref: 'prof', required: true ,
    dueDate: type: String, required: true

)



/* Exporting it as a mongoose model so that it can be put into the data base */
module.exports = mongoose.model('checkoutHist', checkoutHistory)

当我使用此模型创建文档时,这很有效。就这样……

const checkoutHistoryMiddle = (req, res, next) => 
    try 
        //get the body of the request
        const body = req.body
    
        //check for data
        if(!body)
            return res.status(400).json(
                success: false,
                error: 'no body given'
            )
        

        const history = new CheckoutHist(body)


        history.save().then(() => next()).catch(error => 
            return res.status(400).json(
                success: false, 
                message: error,
                msg: "checkout save failed"

            )
        )




     catch (error) 
        res.status(400).json(
            success: false,
            message: error,
            msg: "checkoutHist failed"
        )
    




所以上面的代码会将一个新的历史对象保存到数据库中,这目前可以正常工作。

这是我们进入实际问题的地方。由于上述错误,我无法从 mongo 数据库中检索这些文档。我的路线设置正确:

router.get('/book/hist', BookCtrl.getCheckoutHistory)


getCheckoutHistory = async (req, res) => 
    try 
        return res.status(200).json(success: true, msg:"success")
     catch (err) 
        return res.status(400).json(success: false, msg:"failed")
    
    

    // await CheckHist.find(, (err, hist) => 
    //     if (err) 
    //         return res.status(400).json( success: false, error: err )
    //     

    //     if (!hist) 
    //         return res
    //             .status(404)
    //             .json( success: false, error: `History not found` )
    //     
    //     return res.status(200).json( success: true, data: hist )
    // ).catch(err => console.log(err))


我注释掉了代码以显示我正在尝试做的事情,并强调无论在这个函数中做了什么,它都不会运行。

现在这个错误特别奇怪的是它指向文件中与我在这里所做的事情无关的部分是错误:

at getBookById (/Users/devintripp/Desktop/unt-library-system/server/controllers/book-ctrl.js:376:13)

这有什么奇怪的,当我访问 /book/hist 端点时,我实际上并没有在任何地方调用这个函数。下面是这个函数的作用:

getBookById = async (req, res) => 
    await Book.findOne( _id: req.params.id , (err, book) => 
        if (err) 
            return res.status(400).json( success: false, error: err )
        

        if (!book) 
            return res
                .status(404)
                .json( success: false, error: `Book not found` )
        
        return res.status(200).json( success: true, data: book )
    ).catch(err => console.log(err))

很奇怪。因为我是这样访问端点的。

useEffect( () => 
        const getHistory = async () => 
            // await Axios.get('http://localhost:8174/api/book/hist').then(bookHist => 
          
            //     console.log(bookHist.data.data)

           
            // )

            api.getCheckoutHist().then(hist => 
                console.log(hist)
            )
        

        getHistory()
    , [])

api.getCheckoutHist()Axios.get 执行相同的操作并产生相同的错误,我将其留在那里以显示我正在访问的端点。访问 findById 函数的端点位于不同的字符串 http://localhost:8174/api/book/:id

这是我得到的完整错误:

CastError: Cast to ObjectId failed for value "hist" at path "_id" for model "books"
    at model.Query.exec (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/query.js:4358:21)
    at model.Query.Query.catch (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/query.js:4464:15)
    at getBookById (/Users/devintripp/Desktop/unt-library-system/server/controllers/book-ctrl.js:376:13)
    at Layer.handle [as handle_request] (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/layer.js:95:5)
    at /Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:281:22
    at param (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:354:14)
    at param (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:365:14)
    at Function.process_params (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:410:3)
    at next (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:174:3)
    at router (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:47:12)
    at Layer.handle [as handle_request] (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/Users/devintripp/Desktop/unt-library-system/server/node_modules/express/lib/router/index.js:317:13) 
  messageFormat: undefined,
  stringValue: '"hist"',
  kind: 'ObjectId',
  value: 'hist',
  path: '_id',
  reason: Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
      at new ObjectID (/Users/devintripp/Desktop/unt-library-system/server/node_modules/bson/lib/bson/objectid.js:59:11)
      at castObjectId (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/cast/objectid.js:25:12)
      at ObjectId.cast (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/schema/objectid.js:279:12)
      at ObjectId.SchemaType.applySetters (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/schematype.js:1110:12)
      at ObjectId.SchemaType._castForQuery (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/schematype.js:1545:15)
      at ObjectId.SchemaType.castForQuery (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/schematype.js:1535:15)
      at ObjectId.SchemaType.castForQueryWrapper (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/schematype.js:1512:20)
      at cast (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/cast.js:331:32)
      at model.Query.Query.cast (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/query.js:4759:12)
      at model.Query.Query._castConditions (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/query.js:1841:10)
      at model.Query.<anonymous> (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/query.js:2098:8)
      at model.Query._wrappedThunk [as _findOne] (/Users/devintripp/Desktop/unt-library-system/server/node_modules/mongoose/lib/helpers/query/wrapThunk.js:16:8)
      at /Users/devintripp/Desktop/unt-library-system/server/node_modules/kareem/index.js:370:33
      at processTicksAndRejections (internal/process/task_queues.js:75:11)

我希望您能理解我的困惑,也许可以让我了解这里到底发生了什么,我不明白任何帮助表示感谢。

【问题讨论】:

【参考方案1】:

除此之外,您没有向我们展示您为应用定义的其他路线:

router.get('/book/hist', BookCtrl.getCheckoutHistory)

但我可以打赌你的router.get('/book/:id', ....) 路线在router.get('/book/hist', ...) 之前。对吧?

所以当你向.../api/book/hist 发出请求时,猜猜谁在那里拦截它?这家伙/book/:id。并且它假设hist 是一本书的ID。然后它调用getBookById,它运行

await Book.findOne( _id: req.params.id , (err, book) => 

它试图将 hist 转换为 ObjectID 并且不能。

所以把router.get('/book/hist', BookCtrl.getCheckoutHistory)放在router.get('/book/:id', ....)之前


在 express 中声明路线真的不是很多。但是,您应该注意一些问题。 This article 非常简短但内容丰富,您一定要好好利用它。

至于您关于“两个 findById 函数在同一个路由文件中转到两个单独的 [sic] 文档”的其他问题,我认为它没有任何问题。只要他们为他们定义了两条单独的路线。例如:

router.get('/profs/:profid', ProfCtrl.findProfById);
router.get('/admins/:adminid', AdminCtrl.findAdminById);

这是一种完全有效的方法。

【讨论】:

两个问题:你的大脑怎么这么大?我在哪里可以找到更多信息?还可以安全地假设我不应该在同一个路由文件中有两个 findById 函数去两个单独的文档吗?例如教授和管理员,我不会将 findAdminById(id) 和 findProfById(id) 放在同一个文件中吗? @devin 大脑大小适中,但我过去曾遇到过这个确切的问题。我已经更新了我的答案,尽我所能解决您的问题。 非常感谢,我已经为此苦苦挣扎了几个小时,并且能够用您的评论解决它。 @codemonkey

以上是关于对于模型的路径“_id”处的值,转换为 ObjectId 失败的主要内容,如果未能解决你的问题,请参考以下文章

CastError:对于猫鼬中模型的路径“_id”处的值“findByName”,转换为 ObjectId 失败

Mongoose:CastError:对于模型“”的路径“_id”处的值“”,转换为 ObjectId 失败

护照注销()错误:对于模型“somemodel(不是用户模型)”的路径“_id”处的值“注销”,转换为 ObjectId 失败

模型的路径“_id”处的值“”转换为 ObjectId 失败

CastError:模型的路径“_id”处的值“:id”转换为 ObjectId 失败

模型“Coach”的路径“_id”处的值“”转换为 ObjectId 失败