Search code examples
javascriptnode.jsmongodbexpressmongoose

Cast to ObjectId failed for value \"hello\" (type string) at path \"_id\" for model \"product\


i have mongodb local database and im using node and express and mongoose.

all routes i made work properly except the last one /hello im getting this error:

{
    "stringValue": "\"hello\"",
    "valueType": "string",
    "kind": "ObjectId",
    "value": "hello",
    "path": "_id",
    "reason": {},
    "name": "CastError",
    "message": "Cast to ObjectId failed for value \"hello\" (type string) at path \"_id\" for model \"product\""
}

this is my index.js

import mongoose from "mongoose";
import  express, { json }  from "express";
import 'dotenv/config'
import productRouter from './routes/productR.js' 

const app = express()

const connectionToDB = async () => {
  try {
    await mongoose.connect('mongodb://127.0.0.1:27017/testingDB')
    console.log('Connected to mongoDB');
  } catch (error) {
    console.log(error);
  }
}

app.use(json())
app.use('/products', productRouter)

app.listen(process.env.PORT, ()=>{
    connectionToDB()
    console.log('Server in up at '+ process.env.PORT);
})

this is my product model

import mongoose from "mongoose";

const productSchema = new mongoose.Schema({
    name:{
        type:String
    },
    brand:{
        type: String,
    },
    size:{
        type:[String],
    },
    desc:{
        type:String
    },
    price:{
        type:Number
    }, 
    category:{
        type:String
    },
    picture:{
        type:String
    }
})

export default mongoose.model('product',productSchema)

my product router

import express  from "express";
import { addProduct, deleteProduct, getProduct, getProducts, updateProduct } from "../controllers/productC.js";

const router = express.Router()

router.post('/',addProduct)
router.put('/:id',updateProduct)
router.delete('/:id',deleteProduct)
router.get('/:id',getProduct)
router.get('/',getProducts)

router.get("/hello",(req, res)=>{
    res.json('5464')
})

export default router;

my product controller

import Product from '../models/productM.js'

export const addProduct = async (req, res)=>{
    const newProduct = Product(req.body)
    try {
        const savedProduct = await newProduct.save()
        res.status(200).json(savedProduct)
    } catch (error) {
        res.status(500).json(error)
    }
}

export const updateProduct = async (req, res) => {
    try {
        const updatedProduct = await Product.findById(req.params.id)
        if(req.body.name) { updatedProduct.name = req.body.name}
        if(req.body.brand) { updatedProduct.brand = req.body.brand}
        if(req.body.size) { updatedProduct.size =(req.body.size)}
        if(req.body.desc) { updatedProduct.desc = req.body.desc}
        if(req.body.price) { updatedProduct.price = req.body.price}
        if(req.body.picture) { updatedProduct.picture = req.body.picture}
        if(req.body.category) { updatedProduct.category = req.body.category}
        await updatedProduct.save()
        res.status(200).json(updatedProduct)
    } catch (error) {
        res.status(500).json(error)
    }
}

export const deleteProduct = async (req, res) => {
    
    try {
        await Product.findByIdAndDelete(req.params.id)
        res.status(200).json(`The product (${req.params.id}) has been deleted`)
    } catch (error) {
        res.status(500).json(error)
    }
}

export const getProduct = async (req, res) => {
    const productID = req.params.id
    try {
        const foundProduct = await Product.findById(productID)
        res.status(200).json(foundProduct)
    } catch (error) {
        res.status(500).json(error)
    }
}

export const getProducts = async (req, res) => {
    const {min,max, ...others} = req.query
    const name = req.query.name || "";
    const category = req.query.category || "";
    const brand = req.query.brand || "";
    console.log(name);
    try {
        // const foundProducts = await Product.find({
        //     price:{$gt:parseInt(min) || 1, $lt:parseInt(max) || 999}
        // })
        const foundProducts = await Product.find({$and:[
            { price:{$gte:parseInt(min) || 1, $lte:parseInt(max) || 9999}},
            {name: {$regex: `${name}` || "" , $options: 'i' }},
            {brand: {$regex: `${brand}` || "" , $options: 'i' }},
            {category: {$regex: `${category}` || "" , $options: 'i' }}
        ]})
        res.status(200).json(foundProducts)
    } catch (error) {
        res.status(500).json(error)
    }
}

// export const getCats = async () => {
//     try {
//         res.status(200).json('here')
//     } catch (error) {
//         res.status(500).json(error)
//     }
// }

i changed the method to post it worked, but when i return it to get method i get the same problem even if i remove the route the error remain :(


Solution

  • In your product router, you have the following route: router.get('/:id', getProduct)

    This route expects an id parameter to be passed in the URL, but when you access /hello it's treating hello as the id parameter, which results in the error because hello cannot be cast to an ObjectId.

    You should use a linting tool, like eslint. And you should read the following article: How do I ask a good question?.