Mongoose Schema错误:将对象推送到空数组时“转换为字符串失败”

时间:2015-11-21 18:20:28

标签: node.js express mongoose

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

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

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

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

设备的架构如下:

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

我从数据库加载设备(设置了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
});

正如您在评论中看到的那样,当我想将“newAlarm”对象推送到我的设备的alarm-array时,我会收到异常/错误。

错误说:对于路径“报警”

的值“[object 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}

你有什么想法吗?

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

我用的是什么:

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

编辑:我不想使用嵌套架构。也可以使用数组来完成它。我在其他一些Schema中使用数组。

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

device.lastAlarm = alarm;

但之后,thermometer.lastAlarm仍未定义...但是闹钟是一个对象。那么设备对象可能会被锁定吗?

6 个答案:

答案 0 :(得分:5)

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

http.createServer = function (cb) {
    if (cb()) { /* do something */ }
};

答案 1 :(得分:2)

哇,晚了 5 年,但我最近遇到了这个问题。您需要做的就是在嵌套路由的对象中指定类型。因此您的代码将更改为:

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

因此对于嵌套对象,您需要使用 field: {type: String} 而不是 field: String

答案 2 :(得分:1)

猫鼬将模式中具有键“类型”的模式中的对象解释为该对象的类型定义。

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

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

解决方案:

将此选项对象添加到模式声明{ 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' }
);

通过添加此内容,我们要求猫鼬使用$type来解释键的类型,而不是默认关键字type

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

答案 3 :(得分:1)

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

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

简单的解决方案:

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

使用内部架构解决此问题,

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