Какая ошибка Mongoose Cast to ObjectId не удалась для значения XXX по пути "_id"?
При отправке запроса на /customers/41224d776a326fb40f000001
и документа с _id
41224d776a326fb40f000001
не существует, doc
есть null
, и я возвращаю 404
:
Controller.prototype.show = function(id, res) {
this.model.findById(id, function(err, doc) {
if (err) {
throw err;
}
if (!doc) {
res.send(404);
}
return res.send(doc);
});
};
Однако, когда _id
не соответствует тому, что ожидает Mongoose как "формат" (я полагаю), например, с помощью GET /customers/foo
возвращается странная ошибка:
CastError: Cast to ObjectId не удалось присвоить значение "foo" в пути "_id".
Итак, что это за ошибка?
Ответы
Ответ 1
Метод Mongoose findById
передает параметр id
в тип поля модели _id
, чтобы он мог правильно запросить соответствующий документ. Это ObjectId, но "foo"
не является допустимым ObjectId, поэтому сбой выполняется.
Это не происходит с 41224d776a326fb40f000001
, потому что эта строка является допустимым ObjectId.
Один из способов решения этой проблемы - добавить проверку перед вызовом findById
, чтобы увидеть, является ли id
допустимым ObjectId или нет:
if (id.match(/^[0-9a-fA-F]{24}$/)) {
// Yes, it a valid ObjectId, proceed with `findById` call.
}
Ответ 2
Используйте существующие функции для проверки ObjectID.
var mongoose = require('mongoose');
mongoose.Types.ObjectId.isValid('your id here');
Ответ 3
Вы разбираете эту строку как ObjectId
?
Здесь, в моем приложении, я делаю:
ObjectId.fromString( myObjectIdString );
Ответ 4
У меня та же проблема, которую я добавляю
_id: Строка. в схеме, затем она начинает работать
Ответ 5
Вы также можете использовать ObjectId.isValid, как показано ниже:
if (!ObjectId.isValid(userId)) return Error({ status: 422 })
Ответ 6
Мне пришлось переместить мои маршруты поверх других маршрутов, которые отслеживают параметры маршрута:
// require express and express router
const express = require("express");
const router = express.Router();
// move this '/post/like' route on top
router.put("/post/like", requireSignin, like);
// keep the route with route parameter '/:postId' below regular routes
router.get("/post/:postId", singlePost);
Ответ 7
Это старый вопрос, но вы также можете использовать пакет express-validator для проверки параметров запроса
Экспресс-валидатор версии 4 (последний):
validator = require('express-validator/check');
app.get('/show/:id', [
validator.param('id').isMongoId().trim()
], function(req, res) {
// validation result
var errors = validator.validationResult(req);
// check if there are errors
if ( !errors.isEmpty() ) {
return res.send('404');
}
// else
model.findById(req.params.id, function(err, doc) {
return res.send(doc);
});
});
Экспресс-валидатор версии 3:
var expressValidator = require('express-validator');
app.use(expressValidator(middlewareOptions));
app.get('/show/:id', function(req, res, next) {
req.checkParams('id').isMongoId();
// validation result
req.getValidationResult().then(function(result) {
// check if there are errors
if ( !result.isEmpty() ) {
return res.send('404');
}
// else
model.findById(req.params.id, function(err, doc) {
return res.send(doc);
});
});
});
Ответ 8
if(mongoose.Types.ObjectId.isValid(userId.id)) {
User.findById(userId.id,function (err, doc) {
if(err) {
reject(err);
} else if(doc) {
resolve({success:true,data:doc});
} else {
reject({success:false,data:"no data exist for this id"})
}
});
} else {
reject({success:"false",data:"Please provide correct id"});
}
лучше всего проверить правильность
Ответ 9
//Use following to check if the id is a valid ObjectId?
var valid = mongoose.Types.ObjectId.isValid(req.params.id);
if(valid)
{
//process your code here
} else {
//the id is not a valid ObjectId
}
Ответ 10
Я пошел с адаптацией решения @gustavohenke, реализуя cast ObjectId в try-catch , обернутом вокруг исходного кода, чтобы использовать отказ метода CastId как метод проверки.
Controller.prototype.show = function(id, res) {
try {
var _id = mongoose.Types.ObjectId.fromString(id);
// the original code stays the same, with _id instead of id:
this.model.findById(_id, function(err, doc) {
if (err) {
throw err;
}
if (!doc) {
res.send(404);
}
return res.send(doc);
});
} catch (err) {
res.json(404, err);
}
};
Ответ 11
ИЛИ вы можете это сделать
var ObjectId = require('mongoose').Types.ObjectId;
var objId = new ObjectId( (param.length < 12) ? "123456789012" : param );
как упоминалось здесь Метод поиска Mongoose с условием $или не работает должным образом
Ответ 12
Всегда используйте mongoose.Types.ObjectId('your id')
для условий в вашем запросе. Он проверит поле идентификатора перед выполнением запроса, в результате ваше приложение не будет аварийно завершено.
Ответ 13
Привести строку в ObjectId
import mongoose from "mongoose"; // ES6 or above
const mongoose = require('mongoose'); // ES5 or below
let userid = _id
console.log(mongoose.Types.ObjectId(userid)) //5c516fae4e6a1c1cfce18d77
Ответ 14
Способ решения этой проблемы - преобразование идентификатора в строку.
Мне нравится это с галочкой: '${id}'
это должно решить проблему без накладных расходов
Ответ 15
ObjectId состоит из следующих вещей.
- 4-байтовое значение, представляющее секунды с начала эпохи Unix
- 5-байтовое случайное значение (идентификатор машины 3 байта и идентификатор процессора 2 байта)
- 3-байтовый счетчик, начиная со случайного значения.
Правильный способ проверки правильности objectId - использование статического метода из самого класса ObjectId.
mongoose.Types.ObjectId.isValid(sample_object_id)
Ответ 16
Обнаружение и исправление ошибки ObjectID
Я столкнулся с этой проблемой при попытке удалить элемент с помощью mongoose и получил ту же ошибку. Просматривая возвращаемую строку, я обнаружил, что внутри возвращенной строки было несколько лишних пробелов, что вызвало для меня ошибку. Итак, я применил несколько ответов, представленных здесь, чтобы обнаружить ошибочный идентификатор, а затем удалить лишние пробелы из строки. Вот код, который помог мне окончательно решить проблему.
const mongoose = require("mongoose");
mongoose.set('useFindAndModify', false); //was set due to DeprecationWarning: Mongoose: 'findOneAndUpdate()' and 'findOneAndDelete()' without the 'useFindAndModify'
app.post("/delete", function(req, res){
let checkedItem = req.body.deleteItem;
if (!mongoose.Types.ObjectId.isValid(checkedItem)) {
checkedItem = checkedItem.replace(/\s/g, '');
}
Item.findByIdAndRemove(checkedItem, function(err) {
if (!err) {
console.log("Successfully Deleted " + checkedItem);
res.redirect("/");
}
});
});
Это сработало для меня, и я предполагаю, что если другие элементы начинают появляться в возвращаемой строке, они могут быть удалены аналогичным образом.
Надеюсь, это поможет.
Ответ 17
Если кто-то сталкивается с этим, то, что я решил, менялось с одной цитаты в требовании '.
Вместо:
const something = require('./models/something');
использовать:
const something = require('./models/something');
Знайте, это звучит смешно, но на самом деле это работает.
Ответ 18
В моем случае мне пришлось добавить _id: Object
в мою схему, и тогда все работало нормально.