Mongoose, CastError: Cast to Array не удалось получить значение при попытке сохранить модель, содержащую модель.

Я пытаюсь создать модель для моей базы данных mongodb, используя mongoose. Это то, что я пытаюсь сделать:

var Class = mongoose.model('Class', {className: String, marks: [{type: Number}], grades: [{type: Number}]});
var User = mongoose.model('User', {email: String, classes: [Class] });


//Lets create a new user
var class1 = new Class({className: 'aaa', marks: [72, 88, 63], grades: [30, 40, 30]});
var user1 = new User({email: '[email protected]', classes: [class1]});

Сохранение class1 похоже, работает нормально, но когда я проверяю mongodb, это отображается: { "_id": ObjectId("someId"), "className": "TEST1234", "grades": [ 30, 40, 30 ], "marks": [ 72, 88, 63 ], "__v": 0 }

Что такое "__v: 0"?

Сохранение пользователя не выполняется вообще, это следующая ошибка: ValidationError: CastError: Cast to Array failed for value "{ marks: [ 72, 88, 63 ], grades: [ 30, 40, 30 ], _id: someId, className: 'TEST1234' }" at path "classes"

Что именно означает ошибка? Почему это отличает массив от массива? Не должны ли classes: [Class] быть массивом типа class?

Ответ 1

Человек, у меня была аналогичная проблема, создающая схему вроде этого:

QuestionnaireSchema = mongoose.Schema({
    formId: Number,
    name: String,
    questions: [
        {
            type: String,
            title: String,
            alternatives:[{
                label: String,
                value: "Mixed"
            }]
        }
    ]
});

Моя ошибка заключалась в том, что я использую "тип" в качестве имени поля, и это зарезервированное слово в мангусте.

Я просто меняю:

            type: String,

в

            formType: String,

и это работает.

см.: https://github.com/Automattic/mongoose/issues/1760

Ответ 2

Попробуйте изменить определение класса:

var classSchema = mongoose.Schema({className: String, marks: [{type: Number}], grades: [{type: Number}]});
var userSchema = mongoose.Schema({email: String, classes: [classSchema] });
var User = mongoose.model('User',userSchema);

Это необходимо, так как мангуста не может анализировать объект без соответствующей схемы. Теперь, когда вы создаете новую схему для внутреннего объекта класса и ссылаетесь на нее в основном userSchema, mongoose должен иметь возможность анализировать ваш объект.

Ответ 3

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

type: {type: String}

Ответ 4

Ваше определение модели неверно, вы должны исправить это, как показано ниже.

// var Schema = mongoose.Schema;
var User = mongoose.model('User',{ 
  email: String, 
  classes: [ {type: Schema.Types.ObjectID, ref: 'Class'}] 
});

var Class1 = new Class({/*yourDataWillBeHere*/})

Class1.save(function(err, classData) {
   var User1 = new User({/*YourDataWillBeHere*/})
   User1.classes.push(classData._id);
   User1.save(function(err, userData) {
      //make something with userData object 
   })
})

Затем вы можете получать извлеченные данные с помощью функции populate() как это

User
.find()
.populate('classes')
.exec()

Ответ 5

Просто для обновления

Теперь Mongoose поддерживает поддокументы, которые являются документированным способом вложения массивов,

var arraySchema = new Schema({
    property: String
});

var objectSchema = new Schema({
    arrays: [arraySchema]
});

источники

http://mongoosejs.com/docs/schematypes.html

Ответ 6

По умолчанию, если у вас есть объект с ключом "type" в вашей схеме, mongoose интерпретирует его как объявление типа.

// Mongoose interprets this as 'loc is a String'
var schema = new Schema({ loc: { type: String, coordinates: [Number] } });

Изменение типаKey:

var schema = new Schema({
  // Mongoose interpets this as 'loc is an object with 2 keys, type and coordinates'
  loc: { type: String, coordinates: [Number] },
  // Mongoose interprets this as 'name is a String'
  name: { $type: String }
}, { typeKey: '$type' }); // A '$type' key means this object is a type declaration

Ссылка: http://mongoosejs.com/docs/guide.html#typeKey