【问题标题】:Mongoose Schema Error: "Cast to string failed for value" when pushing object to empty arrayMongoose Schema 错误:将对象推送到空数组时“转换为字符串失败”
【发布时间】:2016-02-24 03:16:37
【问题描述】:

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

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

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

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

设备的Schema如下:

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”对象推送到我设备的警报阵列时,我得到了一个异常/错误。

错误说:

在路径 alarms 处的值 [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"

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

编辑 2: 我添加了一个属性lastAlarm 并做

device.lastAlarm = alarm;

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

【问题讨论】:

  • 可能对你有帮助--Link--
  • 我已经找到了,但不幸的是没有帮助

标签: node.js express mongoose


【解决方案1】:

我会将警报声明为其自己的架构,并将警报属性设置为警报数组,即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]
});

【讨论】:

    【解决方案2】:
    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"
    });
    

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

    【讨论】:

      【解决方案3】:

      使用内部模式来解决这个问题,

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

      【讨论】:

        【解决方案4】:

        Mongoose 将 Schema 中带有键“type”的对象解释为该对象的类型定义。

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

        因此对于这个模式,mongoose 将 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' }
        );
        

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

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

        【讨论】:

        • 这是我的问题。
        【解决方案5】:

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

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

        简单的解决方案:

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

        【讨论】:

          【解决方案6】:

          哇,晚了 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

          【讨论】:

            猜你喜欢
            • 2020-02-23
            • 1970-01-01
            • 2021-12-13
            • 2019-04-08
            • 2018-07-12
            • 2017-01-21
            • 2017-08-24
            • 2015-06-09
            • 2021-02-17
            相关资源
            最近更新 更多