Can't push a json object into array using javascript and mongodb - javascript

I have a problem pushing into my Student model data and its schema looks as below:
var StudentSchema = new Schema({
firstName: {
type: String,
trim: true,
default: ''
//validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
type: String,
trim: true,
default: ''
//validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
worksnap: {
user: {
type: Object
},
timeEntries : [],
},
timeEntries : []
});
While my javascript code for pushing items looks like this:
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.exec(function (err, student) {
if (err) {
throw err;
}
//student.timeEntries.push(item); // this works
student.worksnap.timeEntries.push(item); // this does not work
student.save(function (err) {
if (err) {
//return res.status(400).send({
// message: errorHandler.getErrorMessage(err)
//});
} else {
console.log('item inserted...');
}
});
});
As you can see, if I use timeEntries array outside the worksnap object it works fine, it inserts the item as object into that array... I just don't know why it is not working the same being inside worksnap object.
Is there any other option that I can add json objects into an array type in mongo
Thanks

Use .lean()
Documents returned from queries with the lean option enabled are plain JavaScript objects, not MongooseDocuments. They have no save method, getters/setters or other Mongoose magic applied.
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.lean()//-----Added!
.exec(function(err, student) {
if (err) {
throw err;
}
//student.timeEntries.push(item); // this works
student.worksnap.timeEntries.push(item); // this does not work
student.save(function(err) {
if (err) {
//return res.status(400).send({
// message: errorHandler.getErrorMessage(err)
//});
} else {
console.log('item inserted...');
}
});
});

Related

Use Rename collection in mongoose

I have a problem. I renamed my collection responses into old. It works really well but now I need to retrieve my data and my impediment is that I only used the model to retrieve my data from a collection. But now I need to retrieve my data from my renamed collection but I have no model and schema. I tried to create a schema and a model but it didn't work. It returns no elements.
Here is a part of the code :
app.get("/Play", function(req, res) {
var urlTempBox = 'http://localhost:3000/Play';
///////////////////////////////////////////////////////////
request(urlTempBox, function(error, response, body) {
if (error) {
throw (error);
} else {
var jobj = JSON.parse(response.body);
persistRS(jobj);
setTimeout(function() {
ResponseDatabase.find()
.populate('unitCode')
.exec(function(err, finalData) {
if (err) throw (err);
mongoose.connection.db.listCollections({
name: 'old'
})
.next(function(err, collinfo) {
if (err) throw (err);
if (collinfo) {
console.log('lookinOld');
OldResponseDatabase.find()
.populate('unitCode')
.exec(function(err, oldData) {
if (err) throw (err);
console.log('itsOld');
console.log(oldData);
res.send(finalData);
});
} else {
console.log('fk');
res.send(finalData);
}
})
})
}, 5000);
}
});
Here is the part where it doesn't work: console.log(oldData) returns nothing. And I know that my data is in the database when I try to retrieve them.
if (collinfo) {
console.log('lookinOld');
OldResponseDatabase.find()
.populate('unitCode')
.exec(function(err, oldData) {
if (err) throw (err);
console.log('itsOld');
console.log(oldData);
res.send(finalData);
});
}
Finally I found how to do maybe it will be usefull for someone
You just need in your schema to precise the name of your collection like this
( collection : 'old' )
var nameSchemaOldRS = new mongoose.Schema({
MainClass: String,
BookingClass: String,
carID: String,
unitCode:{type: String, ref: 'Map' ,required: [true,'No post id found']},
Deck:Number,
Orientation:String,
Position:String,
}, {
versionKey: false,
collection : 'old'
},);

Mongoose find not executing

Here's what I've got in a file called Zone.js,
var mongoose = require('mongoose');
mongoose.set('debug', true);
var zoneSchema = new mongoose.Schema({
name: {type: String, required: true, default: '', required: true},
timestamp: {type: Date, default: Date.now, required: true},
zipCodes: {type: [String], default: [], required: true}
});
module.exports = mongoose.model('Zone', zoneSchema);
And then here's what I've got in a file called zoneController.js,
var Zone = require('../models/Zone');
module.exports = {
find: function(params, callback){
console.log('Finding zone');
Zone.find(params, function(err, zones){
console.log('Got results');
if (err){
callback(err, null);
return;
}
callback(null, zones);
});
}
}
And then, I have,
ZoneController = require('../controllers/zoneController');
ZoneController.find({}, function(err, results){
console.log('Zone results received');
}
The problem is that the .find() method doesn't give me anything. I get 'Finding zone' in my console, but absolutely nothing after that.
My folder structure is correct and I am referencing the correct files.
try this, I think that you must to return your find method in your controller.
let me know if it work.
module.exports = {
return {
find: function(params, callback) {
console.log('Finding zone');
Zone.find(params, function(err, zones) {
console.log('Got results');
if (err) {
callback(err, null);
return;
}
callback(null, zones);
});
}
}
}
Here is a .find example for Tweet model in one of my old projects.
Tweet.find({}).sort({date: -1}).populate('_creator').exec((err, tweets) => {
res.render('tweet-all', {title: `All Tweets`, tweets: tweets});
});
I think you must use .exec() in Model.

Mongoose not saving an updated document to the database

EDIT: This question was asked earlier, but I didn't do a good job of asking it. I've rewritten the question. Thanks in advance for your help!
I'm in the process of writing a simple messaging server for a school project. Among its other functionalities, the server allows the user to update the information stored in their account. When the user does update their account, an authentication token is generated for them. Here's the schema that defines all of that. Note, header and body are parts of the user input:
UserSchema = new Schema({
_id: {type: ObjectId, select: false},
username: {type: String, required: true, index: {unique: true} },
password: {type: String, required: true, select: false},
email: {type: String},
token: {type: String, select: false}
}, {
autoIndex: false
});
UserSchema.pre("save", function(next) {
// Create a new token for the user
var self = this;
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) {
next(err);
} else {
crypto.randomBytes(256, function(err, bytes) {
if (err) {
next(err);
} else {
bytes = bytes.toString("hex");
bcrypt.hash((new Date() + bytes), salt, function(err, tokenHash) {
if (err) {
next(err);
} else {
self.token = tokenHash;
next();
}
});
}
});
}
});
});
UserSchema.pre("save", function(next) {
// Hash the password before saving
var self = this;
if (!self.isModified("password")) {
next();
} else {
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) {
next(err);
} else {
bcrypt.hash(self.password, salt, function(err, passwordHash) {
if (err) {
next(err);
} else {
self.password = passwordHash;
next();
}
});
}
});
}
});
I'm running into an issue when updating a particular user. Because I want to use the Model middleware, the way I'm updating a user is by using Model#findOne() followed by Model#save(). Here's the code I have to do that:
// Make sure user provided all necessary information.
if (!header.token) {
return callback(new errors.MissingHeaderDataError("Missing 'token' parameter in the header."));
} else {
// Update the user account based on what's in the envelope's body.
User.findOne({"token": header.token}, "+token +password", function (err, user) {
if (err) {
return callback(err);
} else {
// Get a list of all parameters the user wants to change.
var paramsToChange = Object.keys(body);
// Now update the parameters
paramsToChange.forEach(function(param) {
user[param] = body[param];
});
console.log("Updated user:");
console.dir(user);
user.save(function(err, user) {
if (err) {
return callback(err);
} else {
console.log("Returned user:");
console.dir(user);
User.find({}, "+token +password", function(err, foundUser) {
if (err) {
throw err;
} else {
console.log(JSON.stringify(foundUser));
}
});
callback(null, new SuccessEnvelope(user));
}
});
}
});
}
When I run my tests and come to the last bit of code (after save() is returned), I get this output:
Updated user:
{ token: '$2a$10$5VWWqjJ52aGbS4xc6NDKjuGPv8brX7pRmwiKyYjP8VHoTKCtYZiTu',
username: 'jim_bob',
password: '$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZxF3SwkwadC6D1JsIC9xAUhTbCC',
email: 'joe_bob#email.com',
__v: 0 }
Returned user:
{ token: '$2a$10$fRwED..7fFFhN46Vn.ZJW..xYql5t5P39LHddjFS4kl/pmhwfT.tO',
username: 'jim_bob',
password: '$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZxF3SwkwadC6D1JsIC9xAUhTbCC',
email: 'joe_bob#email.com',
__v: 0 }
[{"token":"$2a$10$5VWWqjJ52aGbS4xc6NDKjuGPv8brX7pRmwiKyYjP8VHoTKCtYZiTu","username":"joe_bob","password":"$2a$10$ue08HUsunzzzcbZURzXF7uaH1dZ
xF3SwkwadC6D1JsIC9xAUhTbCC","email":"joe_bob#email.com","__v":0}]
As you can see, the document is not properly saved to the database, as the previous data is still there. My question is: why? Why is the user not being updated when calling save? I think I'm doing everything properly, but obviously I'm not. Any help with this would be great since I'm going mad!
Apparently, in order to save a document to the database, it needs an _id. Kinda silly that Mongoose doesn't give an error when it doesn't find a document. Alas...
I updated my code to reflect the change:
// Make sure user provided all necessary information.
if (!header.token) {
return callback(new errors.MissingHeaderDataError("Missing 'token' parameter in the header."));
} else {
// Update the user account based on what's in the envelope's body.
User.findOne({"token": header.token}, "+_id +token +password", function (err, user) {
if (err) {
return callback(err);
} else {
console.log("Found user:");
console.dir(user);
// Get a list of all parameters the user wants to change.
var paramsToChange = Object.keys(body);
// Now update the parameters
paramsToChange.forEach(function(param) {
user[param] = body[param];
});
console.log("Updated user:");
console.dir(user);
user.save(function(err, user, numberTouched) {
if (err) {
return callback(err);
} else {
console.log("Returned user:");
console.dir(user);
console.log(numberTouched);
User.find({}, "+token +password", function(err, foundUser) {
if (err) {
throw err;
} else {
console.dir(foundUser);
}
});
callback(null, new SuccessEnvelope(user));
}
});
}
});
}

findByIdAndUpdate $set does not check for unique?

I have a schema and specify login is unique is true. When I use findByIdAndUpdate and pass query $set to update an user object, it did not throw back error when login is dup. Does anyone know why and how I should update an object and force schema validation?
Thanks!
// UserSchema.js
var schema = new Schema({
login: {
required: true,
unique: true
},
password: {
index: true,
type: String
}
});
// Update
UserSchema.findByIdAndUpdate('someID', { '$set': { login: 'abc' } }, function (error, user) {
callback(error, user);
});
You simply need to set runValidators to true:
findByIdAndUpdate(req.params.id, {$set: data}, {runValidators: true}, function (err, doc) {
if (err) {
// Handle validation errors
}
})
More here: http://mongoosejs.com/docs/api.html#findOneAndUpdate
Using the shorthand helper methods in Mongoose bypasses validation, so you need to use a 3 step approach:
Find
Edit
Save
For example:
// 1: Find
UserSchema.findById( 'someID',
function (err, user) {
if(!err){
// 2: Edit
user.login = 'abc';
// 3: Save
user.save(function (err, user) {
if (err) {
console.log(err);
return;
}
console.log('User saved: ' + user);
});
}
}
);

Mongoose - Self-referential deep populate error

I'm trying to populate a self-referential model a few times recursively. Here's my schema:
var TestSchema = new Schema({
title: { type: String },
counter: { type: Number },
children: [ { type: Schema.Types.ObjectId, ref: 'test' } ]
});
var models = {
Test: mongoose.model('test', TestSchema)
};
So far, this functioning code populates everything one level:
models.Test.find().populate('children').exec(function(err, doc) {
if (err)
res.send(err);
else {
res.send(doc);
} });
But when I try to do something like:
models.Test.find().populate('children').populate('children.children').exec(function(err, doc) {
or even:
models.Test.find().populate('children').exec(function(err, doc) {
if (err)
res.send(err);
else {
models.Test.populate(doc, 'children.children', function(err, doc) {
res.send(doc);
});
}
});
I get this error:
TypeError: Cannot call method 'path' of undefined
at search (..../api/node_modules/mongoose/lib/model.js:2059:28)
at search (..../api/node_modules/mongoose/lib/model.js:2078:22)
at Function._getSchema (..../api/node_modules/mongoose/lib/model.js:2085:5)
at populate (..../api/node_modules/mongoose/lib/model.js:1706:22)
at Function.Model.populate (..../api/node_modules/mongoose/lib/model.js:1686:5)
at Promise.<anonymous> (..../api/api.js:22:19)
at Promise.<anonymous> (..../api/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)
at Promise.EventEmitter.emit (events.js:95:17)
at Promise.emit (..../api/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38)
at Promise.fulfill (..../api/node_modules/mongoose/node_modules/mpromise/lib/promise.js:92:20)
The mongoose 3.6 release notes say that deep populates are allowed using Model.populate, but that's giving me an error. Does anyone know what's going on?
The Mongoose docs for the Model.populate method states that the second parameter should be an options object, and not a string.
Here's the example they provide:
User.findById(id, function (err, user) {
var opts = [
{ path: 'company', match: { x: 1 }, select: 'name' }
, { path: 'notes', options: { limit: 10 }, model: 'override' }
]
User.populate(user, opts, function (err, user) {
console.log(user);
})
})
So yours should look something like:
models.Test.find().populate('children').exec(function(err, doc) {
if (err)
res.send(err);
else {
var opts = [
{ path: 'children.children' }
];
models.Test.populate(doc, opts, function(err, doc) {
res.send(doc);
});
}
});

Categories

Resources