提问人:Niels Koop 提问时间:9/5/2023 更新时间:9/6/2023 访问量:130
猫鼬错误:“模型路径”_id“处的值”null“(类型字符串)强制转换为 ObjectId 失败......"
Mongoose error: "Cast to ObjectId failed for value "null" (type string) at path "_id" for model ... "
问:
我目前正在创建简单的 CRUD 应用程序,让我可以创建产品并将其存储在 Mongo 数据库中。该应用程序运行良好,但当我尝试转到“/products/show”页面(或使用特定产品时)时,它不断抛出错误消息。
我真的不知道发生了什么,因为这是我第一次使用 Mongoose 和 MongoDB。该应用程序运行正常,这是应该的,但是即使屏幕上的所有内容都显示在屏幕上,此错误消息也会导致程序继续加载。
我的索引 .js 文件
const express = require('express');
const app = express();
const path = require('path');
const mongoose = require('mongoose');
const Product = require('./models/product');
mongoose.connect('mongodb://localhost:27017/farmStand', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log("MONGO CONNECTION IS OPEN!");
})
.catch(err => {
console.log("Oh no.. Mongo error");
console.log(err);
});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true }));
app.get('/products', async (req, res) => {
const products = await Product.find({});
res.render('products/index', { products });
});
app.get('/products/new', (req, res) => {
res.render('products/new');
});
app.post('/products', async (req, res) => {
const newProduct = new Product(req.body);
await newProduct.save();
console.log(newProduct);
res.redirect(`/products/${newProduct._id}`);
});
// This is where the error is occuring.
app.get('/products/:id', async (req, res) => {
try {
const product = await Product.findById(req.params.id);
res.render('products/show', { product });
}
catch (error) {
console.log(error);
}
});
app.listen(3000, () => {
console.log("APP IS LISTENING ON PORT 3000");
});
我的 productSchema 文件
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true,
min: 0
},
category: {
type: String,
lowercase: true,
enum: ['fruit', 'vegetables', "dairy"]
}
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
我的 EJS '/show' 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= product.name %></title>
</head>
<body>
<h1><%= product.name %></h1>
<ul>
<li>Price: $<%= product.price %></li>
<li>Category: <%= product.category %></li>
</ul>
<a href="/products">All products</a>
</body>
</html>
错误消息
CastError: Cast to ObjectId failed for value "null" (type string) at path "_id" for model "Product"
at ObjectId.cast (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/schema/objectid.js:250:11)
at SchemaType.applySetters (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/schematype.js:1220:12)
at SchemaType.castForQuery (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/schematype.js:1632:15)
at cast (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/cast.js:356:32)
at Query.cast (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:4910:12)
at Query._castConditions (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:2232:10)
at model.Query._findOne (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:2519:8)
at model.Query.exec (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:4429:28)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/index.js:40:25 {
stringValue: '"null"',
messageFormat: undefined,
kind: 'ObjectId',
value: 'null',
path: '_id',
reason: BSONError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
at new ObjectId (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/bson/lib/bson.cjs:2006:23)
at castObjectId (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/cast/objectid.js:25:12)
at ObjectId.cast (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/schema/objectid.js:248:12)
at SchemaType.applySetters (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/schematype.js:1220:12)
at SchemaType.castForQuery (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/schematype.js:1632:15)
at cast (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/cast.js:356:32)
at Query.cast (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:4910:12)
at Query._castConditions (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:2232:10)
at model.Query._findOne (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:2519:8)
at model.Query.exec (/Users/nielskoop/Coding/UdemyCourse/MongoDB/38_mongoose-express/node_modules/mongoose/lib/query.js:4429:28),
valueType: 'string',
model: Model { Product }
}
我尝试过的解决方案
我在网上找不到太多关于这个主题的信息,而且可用的信息非常混乱。我尝试添加一个语句来检查给定的 id ,但这只会完全阻止程序工作。我还尝试将 Mongoose 给出的 ID 转换为一个简单的字符串,并将其存储在一个单独的变量中,以便我以后可以使用它,但这也完全阻止了程序的工作。if
isValid
所需解决方案
我想找出导致此错误的原因以及如何修复它。我有一种感觉,当我转到“/show”页面时,代码会继续运行并检查 Mongoose 中的新 ID 值,而该值不存在。然而,我可能完全错了。
提前致谢!
答:
好吧,事实证明,通过将电话放在声明中,我非常接近我的解决方案。这是我现在的代码:findByID()
if
app.get('/products/:id', async (req, res) => {
try {
const { id } = req.params;
if (id.match(/^[0-9a-fA-F]{24}$/)) {
const product = await Product.findById(id);
res.render('products/show', { product });
}
}
catch (error) {
console.log(error);
}
});
它不再抛出错误消息。我现在的问题是,这样的代码是否好,或者是否可以以某种方式改进?此外,页面会继续加载直到永恒,这是我眼中的一根刺。这是正常行为,还是不好?如果不好,我该如何解决?😊
你绝对不需要运行一个声明来制作你的工作。if (id.match...){...}
findById(id)
错误消息告诉您:
Cast to ObjectId failed for value "null" (type string) at path "_id"
所以在这个代码中:
app.post('/products', async (req, res) => {
const newProduct = new Product(req.body);
await newProduct.save();
console.log(newProduct);
res.redirect(`/products/${newProduct._id}`); //< You are sending null
});
我怀疑在某些情况下,您的和猫鼬有些不太对劲,猫鼬没有创建产品,然后当您尝试重定向时会产生连锁反应。您认为您正在重定向到:const newProduct
res.redirect(`/products/${newProduct._id}`);
// /products/64f7728ac8718d458e441283
但实际上,您正在重定向到:
res.redirect(`/products/${newProduct._id}`);
// /products/null
所以在你的:req.params.id
null
app.get('/products/:id', async (req, res) => {
try {
const product = await Product.findById(req.params.id); //< req.params.id = null
}
//...
//...
});
您需要一个块来找出产品创建何时失败。目前,您只是盲目地重定向。实现此更改:try/catch
app.post('/products'...)
app.post('/products', async (req, res, next) => {
try{
const newProduct = new Product(req.body);
await newProduct.save();
console.log(newProduct);
res.redirect(`/products/${newProduct._id}`);
} catch(err){
console.log(err);
next(err);
}
});
否则,您的代码看起来不错,可能只是您实际发布的数据存在问题,导致产品无法创建。
评论
if
next(err)
res.status(400).json({ error : err });
req.params.id
req.params.id
console.log('id', req.params.id)
app.get('/products/:id
id 64f763ae585b41f59f85c7c5
id null
这是我这样做时得到的输出。
评论