Mongoose sub-schema shows '[object Object]' in document. [duplicate] - node.js

I have sub document as in metrics. But I don't think I am saving correctly, because each document doesn't have metrics data correctly..instead it shows metrics: [ '[object Object]', '[object Object]', '[object Object]' ] and the data is impossible to access. This is really difficult to figure out since Mongoose doesn't give errors for this kind of stuff. If anyone could please tell me what is wrong.
EDIT: To make things more confusing, in the browser it shows that metrics has 3 arrays:
Object {cpuResult: Object}
cpuResult: Object
__v: 0
_id: "53b781d9fb272c4f44d8d1d8"
avaiable: true
metrics: Array[3]
0: "[object Object]"
1: "[object Object]"
2: "[object Object]"
length: 3
Here is my schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CpuSchema = new Schema({
timeStamp : { type : Date, index: true },
avaiable : Boolean,
status : String,
metrics : [ { duration : String,
data : Number,
type : String,
unit : String
} ,
{ duration : String,
data : Number,
type : String,
unit : String
},
{ duration : String,
data : Number,
type : String,
unit : String
}
]
});
module.exports = CpuSchema;
Here is my save function:
function saveCpu(cpuResult) {
var cpu = new Cpu ({
timeStamp : cpuResult.timestamp,
avaiable : cpuResult.available,
status : cpuResult.status,
metrics : [ { duration : "15m",
data : cpuResult.metrics["15m"].data,
type: cpuResult.metrics["15m"].type,
unit: cpuResult.metrics["15m"].unit
},
{ duration : "5m",
data : cpuResult.metrics["5m"].data,
type: cpuResult.metrics["5m"].type,
unit: cpuResult.metrics["5m"].unit
},
{ duration : "1m",
data : cpuResult.metrics["1m"].data,
type: cpuResult.metrics["1m"].type,
unit: cpuResult.metrics["1m"].unit
}]
});
cpu.save(function (err, product, numberAffected) {
db_finish(err, product, numberAffected,
cpuResult, "cpuResult") });
Here is my data that gets inserted:
{ timestamp: 1404534588528,
available: true,
status: 'success',
metrics:
{ '15m': { data: 0.05, type: 'n', unit: 'unknown' },
'5m': { data: 0.01, type: 'n', unit: 'unknown' },
'1m': { data: 0, type: 'n', unit: 'unknown' } } }

When including a field named type in a sub-doc of a Mongoose schema, you need to define its type using an object or it looks to Mongoose like you're declaring the type of the parent field.
So change your schema to:
var CpuSchema = new Schema({
timeStamp : { type : Date, index: true },
avaiable : Boolean,
status : String,
metrics : [ { duration : String,
data : Number,
type : {type: String},
unit : String
} ,
{ duration : String,
data : Number,
type : {type: String},
unit : String
},
{ duration : String,
data : Number,
type : {type: String},
unit : String
}
]
});

Related

how to update specific subdocument in array with mongoose

postSchema
let postSchema = new mongoose.Schema({
data : Buffer,
contentType : String,
caption : String,
likes : [mongoose.ObjectId],
likesCount : {type :Number, default : 0},
comment :[{userId :mongoose.ObjectId, cmnt : String, reply :[{}]}],
commentCount : {type :Number, default : 0},
date : {type : Date, default: Date.now}
})
userSchema
let userSchema = new mongoose.Schema({
qr : {
data : Buffer,
contentType : String
},
profile_pic:{
data:Buffer,
contentType : String
},
first_name:String,
last_name:String,
email:{
type:String,
unique:true
},
mobile_number:Number,
DOB : Date,
gender:{
type : String,
enum : ["Male","Female","Other"]
},
password : {
type : String
},
address:{
city : String,
state : String
},
followers : {
type : [mongoose.ObjectId]
},
followersCount : {
type : Number,
default : 0
},
following : {
type : [mongoose.ObjectId]
},
followingCount : {
type : Number,
default : 0
},
//this is my post schema
posts : [postSchema],
postsCount :{type :Number, default : 0},
reset_password_token : {
OTP:Number,
is_varify_password_token : {
type:Boolean,
default : false
},
time : {
type : Date,
}
}
})
** 1) i want to find specific user
2) after finding user i want to find and update specific post (caption) in array of posts **
i have tried but not working
await USERMODEL.findOneAndUpdate({_id:req.user._id,posts:{$elemMatch:{_id: req.params.postId}}},{"posts.$.caption ":caption})mongodb document image
PLEASE HELP I AM NEW TO MONGODB
**by mistake I have pasted some code out of block please do not mind **
It looks like your post is mostly code; please add some more details

MongoDB: Cannot use complex condition in subdocument [duplicate]

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?
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
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]
});
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
}
},
Wow, 5 years late but I recently faced this problem. All you need to do is specify the type in an object for nested routes. So your code would change to:
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"
} ]
});
So for nested objects, you'd need to use field: {type: String} and not field: String
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.
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' }
i was facing same issue in frontend when I was filling the login form then
like dispatch({email , password});
you can see above i wrapped up into curly braces , i just remove curly {} then it worked in my case.
If your facing this issue from frontend then try this

Mongoose dup key

I'm getting a duplicate key error and not sure why.
I have the following schema:
var walletSchema = mongoose.Schema({
currencyName : {type : String, required : true, unique : true},
amount : {type : Number, default : 0}
}, {strict : false});
// define the schema for our user model
var userSchema = mongoose.Schema({
local : {
username : { type: String, required: true, unique: true },
password : { type: String, required: true, unique : true },
email : { type: String, required: true, unique: true },
country : { type: String, required: true },
inventory : {
food : { type : Number, default : 0},
energyDrinks : { type : Number, default : 0 }
},
wallet : [walletSchema],
lastAttackedAt : { type: Date, default: Date.now },
lastJobChange : {type: Date, default: '03/30/1988' },
lastWorked : {type: Date},
referredBy : {type : String, default : 'Admin'},
energy : { type: Number, default: 100 },
energyUpdatedAt : { type : Date, default: Date.now },
resetPasswordToken: String,
resetPasswordExpires: Date
}
},{timestamps : true});
I create a new user with this code :
...
newUser.local.username = capitalizeUser(username);
newUser.local.password = newUser.generateHash(password);
newUser.local.email = req.body.email;
newUser.local.country = req.body.country;
newUser.local.wallet.push({
// Create the default currencies
currencyName: 'Euro',
}, {
currencyName: 'Gold',
}, {
currencyName: result.countryCurrency
}
);
// save the user
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
Everything works fine for the first user however if I try to make another user I get MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: xyz.users.$local.wallet.currencyName_1 dup key: { : "Euro" }.
Why is this happening, doesn't each user has it's own wallet? How should I handle it, keep in mind that there are about ~230 currencies available for each user.
currencyName : {type : String, required : true}
Remove unique from there and you will be good to go. Mongo checks unique keys for collection. In your case walletSchema collection will have a lot of same values so that's why it's gives error.
As your currencyName has been set unique so it has to be different for each user you save. In fact you with this schema you won't even be able to have two users from the same country.
So to avoid this you need to remove the unique keyword from you schema and it is done. It then looks something like this.
var walletSchema = mongoose.Schema({
currencyName : {type : String, required : true},
amount : {type : Number, default : 0}
}, {strict : false});

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

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?
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
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]
});
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
}
},
Wow, 5 years late but I recently faced this problem. All you need to do is specify the type in an object for nested routes. So your code would change to:
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"
} ]
});
So for nested objects, you'd need to use field: {type: String} and not field: String
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.
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' }
i was facing same issue in frontend when I was filling the login form then
like dispatch({email , password});
you can see above i wrapped up into curly braces , i just remove curly {} then it worked in my case.
If your facing this issue from frontend then try this

mongoose: update field, push object in array [duplicate]

This question already has answers here:
Stop Mongoose from creating _id property for sub-document array items
(7 answers)
Closed 7 years ago.
I would like to add an element in an array in a mongo database:
db.keypairs.update( {pubkey: "1234567890"}, { $push: {listTxId: {txHash: "yyy", spent: false} } } )
The result is perfect:
listTxId" : [ { "txHash" : "xxx", "spent" : true },{ "txHash" : "yyy", "spent" : false } ]
Now I would like to do the same with node.js and mongoose
var res = wait.forMethod(Keypair,'update', {pubkey: "1234567890"}, { $push: { "listTxId": {"txHash":"zzz", "spent":false} } } );
Keypair is my node.js model for the mongoose collection:
var Keypair = require('./app/models/Keypair');
and wait.forMethod comes from a node module:
var wait = require('wait.for');
In the result, I have this "_id" element :
{ "txHash" : "zzz", "spent" : false, "_id" : ObjectId("56561571fea5d9a10a5771fd") }
QUESTION: where this ObjectId come from ? How can I get rid of it ?
UPDATE: mongoose schema:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});
Mongoose will put ids in your subdocument arrays. listTxId is a subdocument array. You can add _id: false to your schema to prevent this:
var keypairSchema = mongoose.Schema({
userId : { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
pubkey : String,
privkeyWIF : String, // temp
balance : Number,
listTxId : [{
_id: false,
txHash : String,
spent : Boolean
}],
walletId : { type: mongoose.Schema.Types.ObjectId, ref: 'Wallet' },
description : { type: String, maxlength: 40 },
comments : String,
isMasterKey : { type: Boolean, default: false },
date : Date
});

Resources