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

孤人 提交于 2019-12-30 17:32:08

问题


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):

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.

The Error says: 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?

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

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?


回答1:


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.

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]
});



回答2:


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

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.

SOLUTION:

Add this option object to schema declaration { 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 $type for interpreting the type of a key instead of the default keyword type

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




回答3:


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

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

SIMPLE SOLUTION:

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



回答4:


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.




回答5:


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' }


来源:https://stackoverflow.com/questions/33846939/mongoose-schema-error-cast-to-string-failed-for-value-when-pushing-object-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!