Mongoose错误:模型路径“_id”处的值“null”(类型字符串)转换为ObjectId失败.“

svujldwt  于 2023-10-19  发布在  Go
关注(0)|答案(2)|浏览(91)

我目前正在创建一个简单的CRUD应用程序,让我创建产品并将其存储在Mongo数据库中。该应用程序工作正常,只是当我试图进入我的“/产品/显示”页面(或使用特定产品时)时,它会不断抛出错误消息。
我真的不知道发生了什么,因为这是我第一次使用Mongoose和MongoDB。应用程序运行正常,这是应该的,但这个错误消息导致程序继续加载,即使一切都在屏幕上。

我的index.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 }
}

我尝试过的解决方案

我在网上找不到太多关于这个主题的信息,而且可用的信息非常混乱。我尝试添加一个if语句来检查给定的id是否为isValid,但这只是使程序完全停止工作。我还尝试将Mongoose给出的ID转换为一个简单的字符串,并将其存储在一个单独的变量中,以便以后使用它,但这也使程序完全停止工作。

所需解决方案

我想知道是什么导致了这个错误以及如何修复它。我有一种感觉,当我转到'/show'页面时,代码继续运行并检查Mongoose中的新ID值,该值不存在。然而,我可能完全错了。
提前感谢!

jchrr9hc

jchrr9hc1#

好的,事实证明,通过将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);
    }
});

它不再抛出错误消息。我现在的问题是,这段代码是否像这样好,或者它是否可以在某种程度上得到改进?此外,页面继续加载,直到永恒,这是一个刺在我的眼睛。这是正常的行为,还是不好?如果不好,我该怎么补救?😊

qyyhg6bp

qyyhg6bp2#

你绝对需要运行一个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和mongoose并没有创建产品,当你尝试重定向时,这会产生连锁React。您认为您正在重定向到:

res.redirect(`/products/${newProduct._id}`);
//            /products/64f7728ac8718d458e441283

但实际上你是重定向到:

res.redirect(`/products/${newProduct._id}`);
//            /products/null

所以req.params.idnull在你的:

app.get('/products/:id', async (req, res) => {
   try {
      const product = await Product.findById(req.params.id); //< req.params.id = null
   }
   //...
   //...
});

app.post('/products'...)中需要一个try/catch块来找出产品创建失败的时间。在那一刻,你只是盲目地重定向。实施此更改:

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

你的代码看起来很好,否则,它可能只是一个问题,与数据,你实际上是造成产品不创建。

相关问题