Mongoose: CastError: сбой при преобразовании в ObjectId для значения [object Object] на пути _id

Я новичок в node.js, поэтому у меня есть ощущение, что это будет что-то глупое, что я упустил из виду, но я не смог найти ответ, который решает мою проблему. Я пытаюсь создать путь, который создаст новый дочерний объект, добавит его в родительский массив дочерних элементов, а затем вернет дочерний объект запрашивающей стороне. Проблема, с которой я сталкиваюсь, заключается в том, что если я передаю идентификатор строки в findById, узел выйдет из строя с

TypeError: объект {} не имеет метода 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»: [ ], "геттеры": [], "_ index": null}

Я пробовал использовать findOne и вместо этого передавал {_id: id}, но похоже, что это именно то, что делает findById. Я пробовал разные классы для ObjectId, которые я видел на других сайтах. Я пробовал вызывать ObjectId () как функцию вместо конструктора, и она возвращает undefined. На данный момент у меня заканчиваются идеи, и поиск ответа в Google не помогает. Есть идеи о том, что я делаю неправильно?

Кроме того, как я уже сказал, я новичок в node / Mongo / Mongoose / Express, поэтому, если есть лучший способ достичь моей цели, сообщите мне. Я ценю все отзывы.

РЕДАКТИРОВАТЬ:

После обходного пути от Питера Лайонса я погуглил еще одну ошибку, с которой я столкнулся, и нашел findByIdAndUpdate, который работает, как ожидалось, и делает именно то, что я надеялся сделать. Я до сих пор не уверен, почему findById и findOne вызывают у меня такие проблемы, и мне любопытно узнать (возможно, необходимо отправить отчет об ошибке), поэтому я оставлю это открытым на случай, если у кого-то еще есть ответ.


person jmblackmer    schedule 20.06.2013    source источник


Ответы (14)


Краткий ответ: используйте mongoose.Types.ObjectId.

Mongoose (но не mongo) может принимать идентификаторы объектов в виде строк и правильно "преобразовывать" их для вас, поэтому просто используйте:

MyClass.findById(req.params.id)

Однако предостережение заключается в том, что если req.params.id не является допустимым форматом для строки идентификатора mongo, это вызовет исключение, которое вы должны перехватить.

Итак, основная непонятная вещь, которую нужно понять, это то, что mongoose.SchemaTypes имеет материал, который вы используете только при определении схем мангуста, а mongoose.Types имеет материал, который вы используете при создании объектов данных, которые вы хотите сохранить в базе данных или объектах запроса. Итак, mongoose.Types.ObjectId("51bb793aca2ab77a3200000d") работает, предоставит вам объект, который вы можете сохранить в базе данных или использовать в запросах, и выдаст исключение, если задана недопустимая строка идентификатора.

findOne принимает объект запроса и передает один экземпляр модели в функцию обратного вызова. А findById - это буквально оболочка findOne({_id: id}) (см. Исходный код здесь). Просто find принимает объект запроса и передает в функцию обратного вызова массив соответствующих экземпляров модели.

Просто не торопись. Это сбивает с толку, но я могу гарантировать, что вы запутались и не столкнетесь с ошибками в мангусте. Это довольно зрелая библиотека, но нужно время, чтобы освоиться.

Другая подозрительная вещь, которую я вижу в вашем фрагменте, - это не использование new при создании экземпляра ChildClass. Кроме того, вам нужно будет опубликовать код схемы, чтобы мы помогли вам устранить любые оставшиеся ошибки CastErrors.

person Peter Lyons    schedule 20.06.2013
comment
Если я попытаюсь использовать mongoose.Types.ObjectId (51c35e5ced18cb901d000001); (помещая его непосредственно в код), я все равно получаю ошибку TypeError: Object {} не имеет метода cast. Я также попытался создать его как объект и получил ту же ошибку. - person jmblackmer; 21.06.2013
comment
Обновиться до последней версии мангуста? Я на 3.6.11. - person Peter Lyons; 21.06.2013
comment
Вызов MyClass.find (req.params.id) работает. Разве findOne и findById не должны работать одинаково? Просто кажется немного нелогичным, чтобы find была функцией, которая возвращает один документ, когда существуют два других. Я изменил код, чтобы получить первый элемент массива, но теперь он не работает в addToSet () с TypeError: Object {} не имеет метода cast. - person jmblackmer; 21.06.2013
comment
Я тоже на 3.6.11. Я только что настроил все это накануне вечером, так что я ожидаю, что все уже обновлено. - person jmblackmer; 21.06.2013
comment
Не работает с 3 июля 2014 года !! Почему new mongoose.Schema.ObjectId("51bb793aca2ab77a3200000d") работает нормально, а new mongoose.Schema.ObjectId(request.params[0]) выдает ошибку ?? При этом я помещаю строку "51bb793aca2ab77a3200000d" в URL /51bb793aca2ab77a3200000d. И при получении с URL-адреса выдает ошибку. - person Green; 03.07.2014
comment
Вы используете неправильную функцию-конструктор. Используйте 1_. mongoose.Schema.ObjectId предназначен только для определения схем. - person Peter Lyons; 03.07.2014

Я столкнулся с этой ошибкой, потому что значение, которое вы хотите отфильтровать в поле _id, не в формате идентификатора, одно «если» должно решить вашу ошибку.

const mongoose = require('mongoose');

console.log(mongoose.Types.ObjectId.isValid('53cb6b9b4f4ddef1ad47f943'));
// true
console.log(mongoose.Types.ObjectId.isValid('whatever'));
// false

Чтобы решить эту проблему, всегда проверяйте, является ли значение критерия для поиска допустимым ObjectId.

const criteria = {};
criteria.$or = [];

if(params.q) {
  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
})
person gsalgadotoledo    schedule 11.10.2016
comment
Верный. Я тестировал конечную точку для GET пользователя с findById, оказалось, что параметр id должен быть 12 бит, иначе mongoose не сможет выполнить приведение. Я использовал случайные короткие числа. - person 10110; 18.04.2019

Для всех тех, кто застрял с этой проблемой, но все еще не мог ее решить: я наткнулся на ту же ошибку и обнаружил, что поле _id пусто.

Я описал это здесь более подробно деталь. До сих пор не нашел решения, кроме изменения полей в _id на поля без идентификатора, что для меня является грязным хакерством. Я, наверное, собираюсь отправить отчет об ошибке для мангуста. Любая помощь будет оценена по достоинству!

Изменить: я обновил свою ветку. Я подал заявку, и они подтвердили отсутствие _id проблемы. Это будет исправлено в версии 4.x.x, релиз-кандидат которой доступен прямо сейчас. ПДУ не рекомендуется для продуктивного использования!

person Stefan Medack    schedule 04.02.2015
comment
интересно, я думаю, что у меня такая же проблема, мой _id был undefined и поэтому не мог быть приведен к ObjectId - person Alexander Mills; 27.03.2015

Если у вас возникла эта проблема и вы выполняете заполнение где-то по строкам, см. Эту проблему с Mongoose .

Обновите Mongoose 4.0, и проблема исправлена.

person ac360    schedule 28.04.2015

Была та же проблема, я просто привел идентификатор в строку.

Моя схема:

const product = new mongooseClient.Schema({
    retailerID: { type: mongoose.SchemaTypes.ObjectId, required: true, index: true }
});

А потом при вставке:

retailerID: `${retailer._id}`
person camstuart    schedule 19.04.2017

Мое решение состоит в том, что мне нужны данные из всех документов, а _id мне не нужен, поэтому

User.find({}, {_id:0, keyToShow:1, keyToNotShow:0})
person jazeb007    schedule 11.12.2019

У меня была такая же проблема, которая возникла после того, как я обновил свою схему, я забыл, что вызывал модель, используя старый идентификатор, который был создан мной; Я обновил свою схему примерно так:

patientid: {
           type: String,
            required: true,
            unique: true
          }, 

to

patientid: { type: mongoose.SchemaTypes.ObjectId, ref: "Patient" },

Оказалось, что, поскольку мой код большой, я звонил findOne со старым идентификатором, следовательно, проблема.

Я пишу здесь, чтобы помочь кому-то еще: пожалуйста, проверьте свой код на неизвестные неправильные вызовы! это может быть проблемой, и это может спасти ваши огромные головные боли!

person Jorge Guerra Pires    schedule 06.04.2020
comment
Всем привет! Это тоже было решением моей проблемы! Мне пришлось вставить новые данные о новой модели, чтобы она заработала. Хорошего дня! - person destroyer22719; 02.04.2021

Я получал эту ошибку CastError: CastError: Cast to ObjectId не удалось для значения «[object Object]» в пути «_id» после создания схемы, а затем изменения ее и не удалось ее отследить. Я удалил все документы в коллекции и смог добавить 1 объект, но не второй. Я закончил тем, что удалил коллекцию в Mongo, и это сработало, поскольку Mongoose воссоздала коллекцию.

person Enkode    schedule 15.05.2014

Для справки: у меня была эта ошибка при попытке неправильно заполнить вложенный документ:

{
[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 - это массив, содержащий массив. Вот почему мангуст пытается заполнить _id (или любое другое поле) массивом, а не Scheme.ObjectId (или любым другим типом данных). Следующие работы:

$history = json_encode(
array(
  'timestamp'  => date('c', time()),
  'date_start' => date('c', time()),
  'date_end'   => date('c', time()),
  'operation'  => 'Deactivation'
));
person Igor Parra    schedule 03.07.2014

Я также столкнулся с этой ошибкой мангуста CastError: Cast to ObjectId не удалось для значения \ "583fe2c488cf652d4c6b45d1 \" в пути \ "_ id \" для модели User

Поэтому я запускаю команду npm list, чтобы проверить версию mongodb и mongoose в моем локальном файле. Вот отчет: ......
......
├── [email protected]
├── [email protected]
.....

Кажется, в этой версии mongodb есть проблема, поэтому я удалил ее и попытался использовать другую версию, такую ​​как 2.2.16.

$ npm uninstall mongodb, он удалит mongodb из вашего каталога node_modules. После этого установите более низкую версию mongodb.
$ npm install [email protected]
Наконец, я перезапускаю приложение, и ошибка CastError исчезает !!

person Arman Ortega    schedule 10.01.2017

У меня была та же проблема. Оказывается, мой Node.js устарел. После обновления все заработало.

person Rajesh Barik    schedule 10.01.2017

Я не уверен, что это поможет, но я решил проблему, импортировав мангуста, как показано ниже, и реализовав его, как показано ниже.

const mongoose = require('mongoose')

_id: new mongoose.Types.ObjectId(),
person Kingsley Akpan    schedule 12.11.2020

просто измените путь, он будет работать например

app.get('/myClass/:Id/childClass/create', function(request, result) .....

изменить на

app.get('/myClass**es**/:Id/childClass/create', function(request, result) .....

Я просто добавил --es-- к пути (myClass), чтобы стать (myClasses)

теперь должно работать и не увидит эту ошибку

person happyCoder    schedule 26.11.2018

Для меня идентификатор был неопределенным (req.params.id возвращает undefined)

person Zeyad Shaban    schedule 09.04.2021