node.js - 对于模型的路径“_id”处的值,转换为 ObjectId 失败
问题描述
错误是
Cast to ObjectId failed for value "hist" at path "_id" for model "books"
你好呀!
问题:
我正在尝试在另一个模型中使用其他模型,确切地说,一个模型中有两个模型。型号如下
models: {
'Professor'
'Book'
}
我想使用另一个名为 checkoutHistory 的猫鼬模型中的模式。
我的理解是,为了做到这一点,我需要这样做
{类型:猫鼬.Schema.Types.ObjectID,参考:'书'}
这是我要从中创建和检索数据的模型。
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)
}
我希望你能理解我的困惑,也许让我了解这里到底发生了什么,我不明白任何帮助表示赞赏。
解决方案
您没有向我们展示您为您的应用定义的其他路线:
router.get('/book/hist', BookCtrl.getCheckoutHistory)
但我可以打赌你的router.get('/book/:id', ....)
路线是 BEFORE 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 中声明路线真的不是很多。但是,您应该注意一些问题。这篇文章非常简短但内容丰富,您当然应该利用它。
至于您关于“在同一个路由文件中具有两个 findById 函数并转到两个单独的 [sic] 文档”的其他问题,我认为它没有任何问题。只要他们为他们定义了两条单独的路线。例如:
router.get('/profs/:profid', ProfCtrl.findProfById);
router.get('/admins/:adminid', AdminCtrl.findAdminById);
这是一种完全有效的方法。
推荐阅读
- r - 修改函数以查找每行连续运行的数字的最大长度
- javascript - 在 Nativescript-vue 中从一个页面转到另一个页面时出错
- python - 如何将日期字符串添加到 URL?
- mongodb - 如何在 MongoDB Ops Manager 中启用可查询快照
- php - 如何使用简单的 html dom 获取隐藏输入的值?
- arrays - 如何将匹配的字符串从 kotlin 中的二维数组打印到整数?
- r - 无法在 Windows 10 的 R Studio 中安装汽车包
- quarkus - 在 Quarkus 中运行非 API 服务的正确方法是什么?
- python - postgres 触发器通知 - 更好的是:之前或之后
- python - 在函数内访问 scipy.integrate.odeint 中的当前时间步