Reputation: 65
I was hoping someone can help me figure out what I'm doing wrong here. I've been searching and I can find a lot of similar issues, but nothing that I'm smart enough to solve my issue from. I'm getting the following error:
CastError: Cast to ObjectId failed for value "customers" at path "_id" for model "customer"
It was working before and I managed to break it, and I undid everything I thought I changed and I'm still getting the error.
Here is my Schema:
const Schema = mongoose.Schema;
const CustomerSchema = new Schema({
custName: {
type: String,
required: true
},
custStreet: {
type: String
},
custCity: {
type: String
},
custState: {
type: String
},
custZip: {
type: String
}
});
module.exports = Customer = mongoose.model('customer', CustomerSchema);
My Routes:
const router = express.Router();
const customerController = require('../../controllers/customer')
const Customer = require('../../models/Customer');
router.route('/')
.get(customerController.index)
.post(customerController.newCustomer);
router.route('/:customerID')
.get(customerController.getCustomer)
module.exports = router;
And my controller:
module.exports = {
index: async (req, res, next) => {
try {
const customers = await Customer.find({})
res.status(200).json(customers);
} catch(err) {
next(err);
}
},
newCustomer: async (req, res, next) => {
try {
const newCustomer = await Customer(req.body);
const customer = await newCustomer.save();
res.status(201).json(customer);
} catch(err) {
next(err);
}
},
getCustomer: async(req, res, next) => {
try {
const { customerID } = req.params;
const customer= await Customer.findById(customerID);
res.status(200).json(customer);
} catch(err) {
next(err);
}
}
};
Also, here is the whole message I get:
CastError: Cast to ObjectId failed for value "customers" at path "_id" for model "customer" at model.Query.exec (C:\Users\natha\Desktop\Coding\HAMMER\node_modules\mongoose\lib\query.js:4371:21) at model.Query.Query.then (C:\Users\natha\Desktop\Coding\HAMMER\node_modules\mongoose\lib\query.js:4463:15) at processTicksAndRejections (internal/process/task_queues.js:93:5)
Something else that is confusing me, I have another Route file and Controller for another collection in my database. It's basically the same code, except instead of routing to '/:Customers' it routes to '/:Tickets' and it works just fine. I don't see how this code is working and the Customers
code is not.
Routes:
const router = express.Router();
const ticketController = require('../../controllers/ticket');
router.route('/')
.get(ticketController.index)
.post(ticketController.newTicket);
router.route('/:ticketID')
.get(ticketController.getTicket)
.put(ticketController.replaceTicket)
.patch(ticketController.updateTicket);
module.exports = router;
Controller:
module.exports = {
index: async(req, res, next) => {
try {
const tickets = await Ticket.find({})
res.status(200).json(tickets);
} catch(err) {
next(err);
}
},
newTicket: async (req, res, next) => {
try {
const newTicket = await Ticket(req.body);
const ticket = await newTicket.save();
res.status(201).json(ticket);
} catch(err) {
next(err);
}
},
getTicket: async(req, res, next) => {
try {
const { ticketID } = req.params;
const ticket = await Ticket.findById(ticketID);
res.status(200).json(ticket);
} catch(err) {
next(err);
}
},
replaceTicket: async(req, res, next) =>{
try {
const { ticketID } = req.params;
const newTicket = req.body;
const result = await Ticket.findByIdAndUpdate(ticketID, newTicket);
res.status(200).json({ Success: true });
} catch(err) {
next(err);
}
},
updateTicket: async(req, res, next) =>{
try {
const { ticketID } = req.params;
const newTicket = req.body;
const result = await Ticket.findByIdAndUpdate(ticketID, newTicket);
res.status(200).json({ Success: true });
} catch(err) {
next(err);
}
}
};
I'd appreciate any help!
Thanks
-N8
Upvotes: 1
Views: 2864
Reputation: 92
I upvoted the solution of the OP. To save a lot of time, I just want to explain why that is an issue and what someone else could look out for as I. So in OP server.js, '/' comes before other routes which defy the rule to list specific routes first. Meaning, if '/' was moved after other routes problem is solved. More importantly, where does this error come from? when you call any of the other routes, your app calls '/' first and uses the customers' routes while passing the route paths (i.e. '/customers', '/materials', '/tickets') as id params and then mongo is trying to cast customer, materials, and tickets as an id inside the customer collection.
app.use('/customers', customers);
app.use('/materials', materials)
app.use('/tickets', tickets)
app.use('/', customers);
This will have solved the problem for OP.
In my case this was the problem:
router.get('/', getAllUser);
router.get('/:id', getUserById)
router.get('/facebook', facebookPassport)
router.get('/google', customersPassport);
So here I get this error Cast error for value "facebook"/"google" at path "_id" for model User because the strings, "facebook" and "google" in the last two routes are specific but will never be reached because the '/:id' route will accept any value that comes after the '/' as an id. When I rearrange like this:
router.get('/', getAllUser);
router.get('/facebook', facebookPassport)
router.get('/google', customersPassport);
router.get('/:id', getUserById)
Take away: move specific routes to the top of dynamic routes (routes with params) both at the app level and in your route files.
Upvotes: 2
Reputation: 65
I found the problem. I had this in my server.js file:
app.use('/', customers);
app.use('/customers', customers);
app.use('/materials', materials)
app.use('/tickets', tickets)
Once I got rid of the app.use('/', customers);
all is good.
Upvotes: 2
Reputation: 1255
You have an error in getCustomer
handler.
You shouldn't use the string id to find the customer, instead, you must first use mongoose.Types.ObjectId(STRING_ID)
.
getCustomer: async(req, res, next) => {
try {
const { customerID } = req.params;
const customer= await Customer.findById(mongoose.Types.ObjectId(customerID));
res.status(200).json(customer);
} catch(err) {
next(err);
}
}
Upvotes: 0