node.js Mongoose Schema 错误:将对象推送到空数组时,“Cast to string failed for value”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33846939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 19:34:11  来源:igfitidea点击:

Mongoose Schema Error: "Cast to string failed for value" when pushing object to empty array

node.jsexpressmongoose

提问by Laokoon

I have a strange problem and cannot figure out what the problem is. The Error-message doesn't help.

我有一个奇怪的问题,无法弄清楚问题是什么。错误消息没有帮助。

I'm sending an "alarm" to the server and want to save this alarm to my "device" which already exist in the database.

我正在向服务器发送“警报”,并希望将此警报保存到数据库中已存在的“设备”中。

The alarm object I send to the server looks like this:

我发送到服务器的警报对象如下所示:

{actionTaken: "none", 
dateTime: "20152111191512", 
difference: 4.88, 
timestamp: 1448128894781}

The Schema for the device is as follows:

该设备的架构如下:

var deviceSchema = new Schema({
   deviceId: {
        type : String,
        index : {
            unique : true,
            dropDups : true
        }
    },
    alarms : [ {
        timestamp : Number,
        dateTime : String, //yyyymmddhhss
        difference : Number,
        actionTaken : String, //"send sms"
    } ]
});

I load the device from the database (deviceId is set):

我从数据库加载设备(设置了 deviceId):

Thermometer.findOne({
        deviceId : deviceId
}, function(error, device){ 
   //error handling
   var now = (new Date().getTime());
   var nowDateTime = (new Date()).toISOString().slice(0, 19).replace(/[-T\s:]/g, "");
   var newAlarm = {
       timestamp : now,
       dateTime : nowDateTime, // yyyymmddhhmmss
       difference : diff,
       actionTaken : "none"
   };
   device.alarms.push(newAlarm);  //EXCEPTION !

   //       device.save //doesn't get called
});

As you can see in the comment, I get an Exception/Error when I want to push the "newAlarm"-object to the alarms-array of my device.

正如您在评论中看到的那样,当我想将“newAlarm”对象推送到设备的警报数组时,出现异常/错误。

The Error says: Cast to string failed for value "[object Object]" at path "alarms"

错误说:Cast to string failed for value "[object Object]" at path "alarms"

Error-Object:

错误对象:

   kind: "string",
   message: "Cast to string failed for value "[object Object]" at path "alarms"",
   name: "CaseError",
   path: "alarms",
   stack: undefined,
   value: {actionTaken: "none", dateTime: "20152111191512", difference: 4.88, timestamp: 1448128894781}

Do you have an idea?

你有想法吗?

For me it doesn't make any sense. The array and its content (object) is specified in the Schema. Why is there a string cast error with the whole object as value?

对我来说没有任何意义。数组及其内容(对象)在 Schema 中指定。为什么将整个对象作为值出现字符串转换错误?

What I use:

我使用的是:

"express": "3.2.6",
"express-session":"1.7.6",
"hjs": "*",
"mongoose": "4.0.5",
"nodemailer": "1.4.0"


EDIT:I don't want to use nested Schemas. It is also possible to do it with arrays. I do it with arrays in some other Schemas.

编辑:我不想使用嵌套模式。也可以用数组来做到这一点。我用其他一些模式中的数组来做。

EDIT 2: I added an property "lastAlarm" and do

编辑 2:我添加了一个属性“lastAlarm”并执行

device.lastAlarm = alarm;

but after that, thermometer.lastAlarm is still undefined... but alarm is an object. So is it possible that the device object is locked some how?

但在那之后, thermometer.lastAlarm 仍然未定义......但 alarm 是一个对象。那么设备对象是否有可能被锁定?

回答by Krishna Pravin

Mongoose interprets the object in the Schema with key 'type' in your schema as type definition for that object.

Mongoose 使用模式中的键“type”将模式中的对象解释为该对象的类型定义。

deviceId: {
  type : String,
  index : {
    unique : true,
    dropDups : true
    }
}

So for this schema mongoose interprets deviceId as a String instead of Object and does not care about all other keys inside deviceId.

因此,对于此模式,猫鼬将 deviceId 解释为 String 而不是 Object,并且不关心 deviceId 中的所有其他键。

SOLUTION:

解决方案:

Add this option object to schema declaration { typeKey: '$type' }

将此选项对象添加到架构声明 { typeKey: '$type' }

var deviceSchema = new Schema(
{
   deviceId: {
        type : String,
        index : {
            unique : true,
            dropDups : true
        }
    },
    alarms : [ {
        timestamp : Number,
        dateTime : String, //yyyymmddhhss
        difference : Number,
        actionTaken : String, //"send sms"
    } ]
},
{ typeKey: '$type' }
);

By adding this we are asking mongoose to use $typefor interpreting the type of a key instead of the default keyword type

通过添加这个,我们要求 mongoose$type用于解释键的类型而不是默认关键字type

Mongoose Docs reference: https://mongoosejs.com/docs/guide.html#typeKey

猫鼬文档参考:https: //mongoosejs.com/docs/guide.html#typeKey

回答by mr.freeze

I would declare alarm as its own schema and set the alarms property as an array of alarm aka subdocuments. This will allow you to add validation to the alarm schema, etc. NOTE: Subdocuments don't get saved until the parent is saved.

我会将 alarm 声明为它自己的架构,并将 alarms 属性设置为 alarm aka subdocuments数组。这将允许您向警报架构等添加验证。注意:在保存父文档之前不会保存子文档。

var alarmSchema = new Schema({
        timestamp : Number,
        dateTime : String, //yyyymmddhhss
        difference : Number,
        actionTaken : String, //"send sms"

});

var deviceSchema = new Schema({
   deviceId: {
        type : String,
        index : {
            unique : true,
            dropDups : true
        }
    },
    alarms : [alarmSchema]
});

回答by AJoboori

Maybe it is too late, but here mongoose is assuming that deviceId is not an object and it is of type String

也许为时已晚,但这里 mongoose 假设 deviceId 不是对象并且它是 String 类型

deviceId: {
  type : String,
  index : {
    unique : true,
    dropDups : true
  }
},

SIMPLE SOLUTION:

简单的解决方案:

deviceId: {
  type: {
    type: String
  },
  index: {
    unique: true,
    dropDups: true
  }
},

回答by Sprotte

var deviceSchema = new Schema({
 deviceId: {
    type : String,
    index : {
        unique : true,
        dropDups : true
    },
    alarms : {type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Alarm' }]}
});

var alarmSchema = new Schema({
    timestamp : Number,
    dateTime : String, //yyyymmddhhss
    difference : Number,
    actionTaken : String, //"send sms"
});

I would recommend to make an own schema for the alarms. I think u cant define an array in a schema like you do.

我建议为警报制作自己的架构。我认为你不能像你那样在模式中定义一个数组。

回答by Vinoth Rajendran

Use inner schema to solve this,

使用内部架构来解决这个问题,

var SchemaObject = require('node-schema-object');

// Create custom basic type 
// Type can be extended with more properties when defined 
var NotEmptyString = {type: String, minLength: 1};

// Create sub-schema for user's Company 
var Company = new SchemaObject({
  startDate: Date,
  endDate: Date,
  name: NotEmptyString
});

// Create User schema 
var User = new SchemaObject({
  // Basic user information using custom type 
  firstName: NotEmptyString,
  lastName: NotEmptyString,

  // "NotEmptyString" with only possible values as 'm' or 'f' 
  gender: {type: NotEmptyString, enum: ['m', 'f']},

  // Index with sub-schema 
  company: Company,

  // An array of Objects with an enforced type 
  workHistory: [Company],

  // Create field which reflects other values but can't be directly modified 
  fullName: {type: String, readOnly: true, default: function() {
    return (this.firstName + ' ' + this.lastName).trim();
  }}
});

// Initialize a new instance of the User with a value 
var user = new User({firstName: 'Scott', lastName: 'Hovestadt', gender: 'm'});

// Set company name 
user.company.name = 'My Company';

// The date is automatically typecast from String 
user.company.startDate = 'June 1, 2010';

// Add company to work history 
user.workHistory.push({
  name: 'Old Company',
  startDate: '01/12/2005',
  endDate: '01/20/2010'
});

console.log(user.toObject());

// Prints: 
{ firstName: 'Scott',
  lastName: 'Hovestadt',
  gender: 'm',
  company: 
   { startDate: Tue Jun 01 2010 00:00:00 GMT-0700 (PDT),
     endDate: undefined,
     name: 'My Company' },
  workHistory: 
   [ { startDate: Wed Jan 12 2005 00:00:00 GMT-0800 (PST),
       endDate: Wed Jan 20 2010 00:00:00 GMT-0800 (PST),
       name: 'Old Company' } ],
  fullName: 'Scott Hovestadt' }