Mongoose: CastError: сбой приведения к ObjectId для значения "[object Object]" по пути "_id"
Я новичок в node.js, поэтому у меня есть ощущение, что это будет что-то глупое, что я упустил из виду, но я не смог найти ответ, который решит мою проблему. Я пытаюсь создать путь, который создаст новый дочерний объект, добавит его в массив дочерних элементов родительского объекта, а затем вернет дочерний объект запрашивающей стороне. Проблема, с которой я сталкиваюсь, состоит в том, что, если я передаю идентификатор строки в findById, происходит сбой узла с
TypeError: Object {} не имеет метода cast
Если я попытаюсь передать ObjectId вместо этого, я получу
CastError: сбой приведения к ObjectId для значения "[object Object]" по пути "_id"
Вот примерный план моего кода:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId; //Have also tried Schema.Types.ObjectId, mongoose.ObjectId
mongoose.connect('mongodb://user:password@server:port/database');
app.get('/myClass/:Id/childClass/create', function(request, result) {
var id = new ObjectId(request.params.Id);
MyClass.findById(id).exec( function(err, myClass) {
if (err || !myClass) { result.send("error: " + err + "<br>" + JSON.stringify(id) || ("object '" + request.params.Id + "' not found: " + id)); return; }
var child = ChildClass();
myClass.Children.addToSet(child);
myClass.save();
result.send(child);
});
});
Если я выполню этот код с путем "/myClass/51c35e5ced18cb901d000001/childClass/create", это будет выводом кода:
ошибка: CastError: сбой приведения к ObjectId для значения "[object Object]" по пути "_id" {"path":"51c35e5ced18cb901d000001","instance":"ObjectID","validators":[],"setters":[],"добытчики":[],"_ индекс": нулевой}
Я попытался использовать findOne и передать вместо него {_id:id}, но, похоже, это именно то, что делает findById. Я пробовал разные классы для ObjectId, которые я видел в списке на других сайтах. Я пытался вызывать ObjectId() как функцию вместо конструктора, и это возвращает неопределенное. На данный момент у меня заканчиваются идеи, и не похоже, что поиск ответа помогает. Есть идеи, что я делаю не так?
Кроме того, как я уже сказал, я новичок в узле /Mongo/Mongoose/Express, поэтому, если есть лучший способ для достижения моей цели, пожалуйста, дайте мне знать. Я ценю все отзывы.
РЕДАКТИРОВАТЬ:
После обходного пути от Питера Лайонса я нашел другую ошибку, с которой столкнулся, и обнаружил findByIdAndUpdate, который работает, как и ожидалось, и делает именно то, что я надеялся сделать. Я до сих пор не уверен, почему findById и findOne давали мне такие проблемы, и мне любопытно знать (возможно, сообщение об ошибке необходимо подать), поэтому я оставлю это открытым, если у кого-то есть ответ.
20 ответов
Краткий ответ: используйте mongoose.Types.ObjectId.
Mongoose (но не mongo) может принимать идентификаторы объектов в виде строк и правильно "приводить" их, так что просто используйте:
MyClass.findById(req.params.id)
Тем не менее, если req.params.id
не является допустимым форматом для строки идентификатора Монго, которая будет выдавать исключение, которое вы должны перехватить.
Таким образом, главная запутанная вещь, чтобы понять, что mongoose.SchemaTypes
есть вещи, которые вы используете только при определении схем мангусты, и mongoose.Types
имеет материал, который вы используете при создании объектов данных, которые вы хотите сохранить в базе данных или запросить объекты. Так mongoose.Types.ObjectId("51bb793aca2ab77a3200000d")
работает, выдаст вам объект, который вы можете сохранить в базе данных или использовать в запросах, и выдаст исключение, если ему будет присвоена неверная строка идентификатора.
findOne
принимает объект запроса и передает один экземпляр модели в функцию обратного вызова. А также findById
буквально обертка findOne({_id: id})
( см. исходный код здесь). Просто find
принимает объект запроса и передает массив соответствующих экземпляров модели в функцию обратного вызова.
Просто иди медленно. Это сбивает с толку, но я могу гарантировать вам, что вы запутались и не попадаете в баг в мангусте. Это довольно зрелая библиотека, но для ее освоения требуется некоторое время.
Другая подозрительная вещь, которую я вижу в вашем фрагменте, не использует new
при создании экземпляра ChildClass
, Кроме того, вам нужно будет опубликовать код вашей схемы, чтобы мы могли помочь вам найти оставшиеся ошибки CastError.
Я сталкивался с этой ошибкой, потому что значение, которое вы хотите отфильтровать в поле _id, не в формате идентификатора, одно "если" должно решить эту проблему.
const mongoose = require('mongoose');
console.log(mongoose.Types.ObjectId.isValid('53cb6b9b4f4ddef1ad47f943'));
// true
console.log(mongoose.Types.ObjectId.isValid('whatever'));
// false
Чтобы решить, всегда проверяйте, является ли значение критерия для поиска действительным ObjectId
if(params.q) {
criteria.$or = []
if(mongoose.Types.ObjectId.isValid(params.id)) {
criteria.$or.push({ _id: params.q })
}
criteria.$or.push({ name: { $regex: params.q, $options: 'i' }})
criteria.$or.push({ email: { $regex: params.q, $options: 'i' }})
criteria.$or.push({ password: { $regex: params.q, $options: 'i' }})
}
return UserModule.find(criteria).exec(() => {
// do stuff
})
Для всех тех, кто застрял с этой проблемой, но все еще не мог ее решить: я наткнулся на ту же ошибку и нашел _id
поле пустое.
Я описал это здесь более подробно. До сих пор не нашли решения, кроме изменения полей в _id
в поля не-ID, что для меня грязное занятие. Я, вероятно, собираюсь подать отчет об ошибке для Мангуста. Любая помощь будет оценена!
Изменить: я обновил свою ветку. Я подал билет, и они подтвердили пропажу _id
проблема. Это будет исправлено в версии 4.xx, в которой уже есть кандидат на релиз. RC не рекомендуется для продуктивного использования!
Если у вас возникла эта проблема, и вы выполняете заполнение где-то вдоль линии, посмотрите эту проблему Mongoose.
Обновите Mongoose 4.0, и проблема была исправлена.
Мое решение состоит в том, что мне нужны данные из всех документов, и мне не нужен _id, поэтому
User.find({}, {_id:0, keyToShow:1, keyToNotShow:0})
Была такая же проблема, я просто привел идентификатор в строку.
Моя схема:
const product = new mongooseClient.Schema({
retailerID: { type: mongoose.SchemaTypes.ObjectId, required: true, index: true }
});
А потом, при вставке:
retailerID: `${retailer._id}`
У меня была та же проблема, которая возникла после того, как я обновил свою схему, я забыл, что вызывал модель, используя старый идентификатор, который был создан мной; Я обновил свою схему примерно так:
patientid: {
type: String,
required: true,
unique: true
},
к
patientid: { type: mongoose.SchemaTypes.ObjectId, ref: "Patient" },
Оказалось, что поскольку мой код большой, я звонил findOne
со старым id, значит, проблема.
Я пишу здесь, чтобы помочь кому-то еще: пожалуйста, проверьте свой код на неизвестные неправильные вызовы! это может быть проблемой, и это может спасти ваши огромные головные боли!
Для справки: у меня была эта ошибка при попытке заполнить поддокумент неправильно:
{
[CastError: Cast to ObjectId failed for value "[object Object]" at path "_id"]
message: 'Cast to ObjectId failed for value "[object Object]" at path "_id"',
name: 'CastError',
type: 'ObjectId',
path: '_id'
value:
[ { timestamp: '2014-07-03T00:23:45-04:00',
date_start: '2014-07-03T00:23:45-04:00',
date_end: '2014-07-03T00:23:45-04:00',
operation: 'Deactivation' } ],
}
look ^ value - это массив, содержащий объект: неправильно!
Объяснение: Я отправлял данные из php в API-интерфейс node.js следующим образом:
$history = json_encode(
array(
array(
'timestamp' => date('c', time()),
'date_start' => date('c', time()),
'date_end' => date('c', time()),
'operation' => 'Deactivation'
)));
Как вы можете видеть, $ history - это массив, содержащий массив. Вот почему mongoose пытается заполнить _id (или любое другое поле) массивом, а не Scheme.ObjectId (или любым другим типом данных). Следующие работы:
$history = json_encode(
array(
'timestamp' => date('c', time()),
'date_start' => date('c', time()),
'date_end' => date('c', time()),
'operation' => 'Deactivation'
));
У меня возникла та же проблема. Оказывается, мой Node.js устарел. После обновления работает.
Я получаю эту ошибку. CastError: сбой приведения к ObjectId для значения "[object Object]" по пути "_id" после создания схемы, затем ее изменения и не может отследить ее. Я удалил все документы в коллекции, и я мог добавить 1 объект, но не второй. Я закончил тем, что удалил коллекцию в Монго, и это сработало, когда Мангуст воссоздал коллекцию.
Я также столкнулся с этой ошибкой mongoose. CastError: сбой приведения к ObjectId для значения \"583fe2c488cf652d4c6b45d1\" по пути \"_id\" для модели User
Поэтому я запускаю команду npm list, чтобы проверить версию mongodb и mongoose в моей локальной системе. Вот отчет:......
......
Ong── mongodb@2.2.19
M── мангуст@4.7.2
.....
Кажется, есть проблема с этой версией mongodb, поэтому я удалил и попытался использовать другую версию, такую как 2.2.16.
$ npm uninstall mongodb
, он удалит mongodb из вашего каталога node_modules. После этого установите нижнюю версию mongodb.$ npm install mongodb@2.2.16
Наконец, я перезагружаю приложение, и CastError исчезает!!
Я не уверен, что это поможет, но я решил проблему, импортировав мангуста, как показано ниже, и реализовав его, как показано ниже.
const mongoose = require('mongoose')
_id: new mongoose.Types.ObjectId(),
поэтому в моем случае я использовал запрос на размещение из документа и запросил файл API, и я неправильно отправил «id» через URL-адрес, это была ошибка «/api/posts/${postId}/like» но замена двойных кавычек на обратные кавычки изменила игру,/api/posts/${postId}/like
и в файле API, когда я использую findbyid(postid), я получил результат без ошибок
Использовать:
MyClass.findOne(id)
Вместо:
MyClass.findById(id)
userRouter.get("/:id/:walletAddress", getDefaultWallet);
userRouter.get("/filterUser/:name", filterUserListByName);
Сначала я использовал это, получил вышеуказанную ошибку, затем изменил положение, которое мне подходит. Оставьте для всех вышеперечисленных маршрутизаторов значение «/: id/XYZ».
userRouter.get("/filterUser/:name", filterUserListByName);
userRouter.get("/:id/:walletAddress", getDefaultWallet);
Просто измените путь, он будет работать, например,
app.get('/myClass/:Id/childClass/create', function(request, result) .....
изменить на
app.get('/myClass**es**/:Id/childClass/create', function(request, result) .....
Я просто добавил --es-- к пути (myClass), чтобы стать (myClasses)
теперь должно работать и не увидит ту ошибку
Если вы находите документ по его «_id» для модели, скажем, «Драйверы», приведенная ниже команда работает достаточно хорошо:
....
const driver = await Drivers.findById(<your id>);
....
Убедитесь, что вы используете синтаксис async-await и try-catch ES6.
Для меня идентификатор был неопределенным (req.params.id возвращает undefined)
просто измените путь , он будет работать, например
app.get('/myClass/:Id/childClass/create', function(request, result)
изменить на
app.get('/myClass**es**/:Id/childClass/create', function(request, result)
я только что добавил
--es--
на путь (myClass), чтобы стать (myClasses)
теперь должно работать и не будет видеть эту ошибку
Для меня я использовал запрос на размещение без отправки каких-либо данных. Я изменил его на почтовый запрос, и это сработало.