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

bvpmtnay  于 2022-11-13  发布在  Go
关注(0)|答案(7)|浏览(265)

我遇到了一个奇怪的问题,无法找出问题是什么。错误消息没有帮助。
我正在向服务器发送一个“警报”,并希望将此警报保存到数据库中已存在的“设备”。
我发送到服务器的报警对象如下所示:

{
  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”对象推送到我的设备的alarms-array时,我会收到一个Exception/Error。
错误说:
将路径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"

**EDIT:**我不想使用嵌套模式。也可以使用数组。我在一些其他模式中使用数组。
EDIT 2:我添加了一个属性lastAlarm并执行

device.lastAlarm = alarm;

但是在那之后,temperature.lastAlarm仍然是未定义的...但是alarm是一个对象。那么设备对象是否可能以某种方式被锁定呢?

jrcvhitl

jrcvhitl1#

Mongoose将Schema中的对象解释为该对象的类型定义,而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

dldeef67

dldeef672#

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

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

gt0wga4j3#

也许已经太晚了,但是mongoose在这里假设deviceId不是对象,而是String类型

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

简单的解决方案:

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

jq6vz3qz4#

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

oiopk7p5

oiopk7p55#

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

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

5ssjco0h

5ssjco0h6#

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

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

7ajki6be7#

当我填写登录表单时,我在前端也遇到了同样的问题,然后像dispatch({email , password});一样,你可以看到上面我 Package 成curly braces,我只是删除了 curl 的{},然后它在我的情况下工作。
如果您从前端面对这个问题,那么尝试这个

相关问题