Mongoose middleware access other collection - node.js

I am using 'pre' 'save' middleware to create for a 'user' document a corresponding 'userObjects' document.
So there is users collections and userObjects.
And when new user is inserted a userObjects document should be inserted too.
I am trying to use the 'pre' middleware, somehow like this :
//before inserting a new user
Users.pre('save', function(next) {
var UserObjects = db.model('userObjects');
userObjectsIns = new UserObjects({
'userID': this._id,
'myObjects':[],
});
userObjectsIns.save( function(err) {
if (err) console.log("ERROR while saving userObjectsIns: " + err);
next()
})
});
The obvious problem, is that db doesn't exists. How can I reach 'userObjects' collection from within this pre middleware?

You can access other models via the model method of the this doc instance:
Users.pre('save', function(next) {
var UserObjects = this.model('userObjects');
userObjectsIns = new UserObjects({
'userID': this._id,
'myObjects':[],
});
userObjectsIns.save( function(err) {
if (err) console.log("ERROR while saving userObjectsIns: " + err);
next()
})
});

Related

Mongoose not saving document completely

I am trying to save data to my mongo db using mongoose. But unfortunately I am not able to save it completely. However it creates a data array but defaults like company name etc. are not saving. However these values are not available in requested body
I am using:
var seller = new sellers(req.body);
seller.save(function (err) {
if (err) {
return res.status(500).send('An user with this email id or mobile number already exist');
}
res.status(200).send('You have successfully registered');
})
In this case you could use a pre save hook to set an object as the default in your array:
userSchema.pre('save', function(next) {
if (this.data.length == 0) {
var default = {
fieldName: 'Company Name',
fieldValue: 'No Information Provided',
// etc.
};
this.data.push(default);
}
next();
});

Update fields of Mongoose document object from request body

The question(Mongoose save all parameters from request body) shows how to create new mongoose document object with request body in a line of code.
Extending this question, I want to know how to set all fields of mongoose document object at once.
router.route('/car')
.put(function(req, res, next) {
Car.findById(req.params.id, function (err, car) {
if (err) {
res.status(400).send(err);
} else {
if (!car)
return next(new Error('Failed to load car: ' + req.params.id));
car.name = req.body.name; // Code refactoring required
car.seats = req.body.seats;
car.engine_size = req.body.engine_size;
car.save(function(err) {
if(err)
res.status(400).send(err);
else
res.json(car);
});
}
});
});
In creating document var car = new Car(req.body); is perfect way to fill fields from request body.
For updating exist mongoose document, is there better way than below lines:
car.name = req.body.name;
car.seats = req.body.seats;
car.engine_size = req.body.engine_size;
You should use update instead of find.
router.route('/car')
.put(function(req, res, next) {
Car.update({ _id: mongoose.Types.ObjectId(req.params.id) },req.body)
.then(function (success) {
res.json();
})
.catch(function (error) {
res.status(404).send(err);
});
});
You can use Document.set().
car.set(req.body)
try {
await car.save()
}catch(err){
console.error(e)
}
For updating exist mongoose document, Is there better way than below lines?
For the better utilization of network data and performance, You should keep in mind that, update() method updates values in the existing document while the save() method replaces the existing document with the document passed in save() method.
So if your model is large and you want to update only few number of fields then update is better option.
Hope this helps.

How to update linked document in mongoose from parent?

I have a User model with a profile field pointing to profile model, like
UserSchema = new Schema({
name: {
type: String,
require: true,
unique: false,
},
profile:{type:Schema.Types.ObjectId, ref: 'Profile'}});
Now it is saving fine, but I want to update the User and Profile at the same time by sending an object like:
{
name : 'some name',
profile.location : 'some location'
}
my simple update code:
User.update({_id:userId},req.body,{},function(){
res.status(204).end();
});
It seems to only update the User's name, but not the linked Profile document's properties. What would be the best way to do this?
The Population (ref used in profile) is introduced into Mongoose,
Because there are no joins in MongoDB but sometimes we still want references to documents in other collections. Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s).
So it is not related to update operation for the reference document. Here are one sample codes to meet your requirement.
User.update({_id: userId},
{name: req.body.name}, function(err, u) {
if (err)
console.log(err);
else {
Profile.update({_id: u.profile},
{location: req.body.profile.locatio},
function(err) {
// error handling
})
}
});
If you are using DaftMonk's Angular Fullstack Generator, then just do this :
Install lodash npm install lodash
Include lodash in your JS file like this : var _ = require("lodash");
Finally do this :
var newUser = {};
newUser.name = "Some Name";
User.findById(userId, function(err, user){
if(err) console.log(err);
var updated = _.merge(user, newUser);
updated.save(function (err) {
if (err) console.log(err);
Profile.findById(user.profile._id, function(err, profile){
profile.location = "some location";
profile.save(function(err){
if(err) console.log(err);
console.log("Updated User and Profile");
});
});
});
});
Hope this helps.

Mongoose, MongoDb, Node. Mongoose object not registering find()

When i'm getting to my routes and requesting to getUSers from my mongoDB it says the User.find() is not defined. Sorry in advance if i use incorrect terminology i'm jumping in face first.
I'm assuming my routing is done incorrectly somewhere or i didn't include one file somewhere I'm hoping ya'll can help me determine if i'm either storing a file incorrectly in my structure, calling a file at the wrong time, or not initializing a variable correctly? Thanks for the help in advance.
Do i need an additional plugin to read and write to the database?
I keep getting the the following error it says usercontroller.js:20
Error: <!DOCTYPE html><html><head><title></title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>undefined is not a function</h1><h2></h2><pre>TypeError: undefined is not a function
at getUsers (c:\Users\Ravenous\kitchen\routes\user_api.js:5:10)
at c:\Users\Ravenous\kitchen\routes\user_api.js:26:3
file structure in case it helps
-bin
-node_modules-\
-user-app-\
-user.js //this is the model written with mongoose schema
-public-\
-html
-images
-javascripts-\
-userController
-userService //AngularJS factory
-stylesheets
-index.html
-routes-\
-user_api.js //with other useful routes inside.
-views //has some jade view engines that came with express-generator
-app.js
-package.JSON
I have this for the user model -- file: node_modules/user-app/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
user_name: String,
password: String,
email: String,
location: String,
date_created : {type: Date, default: Date.now}
});
var User = mongoose.model('User', UserSchema);
module.exports= {User:User};
I then import user.js file to the ./routes/user_api.js file which looks like this
user_api.js :
var User = require('./node_modules/user-app/user');
function getUsers(res){
User.find().populate('users').exec(function(err, users){
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err){
res.send(err)
}else{
console.log(users[0][0].name)
res.json(users); // return all users in JSON format
db.close();
}
})
};
module.exports = function(app) {
// api -----------------------------------------------------------
// get all users
app.get('/node_modules/user-app/user', function(req, res) {
// use mongoose to get all users in the database
getUsers(res);
});
// create user and send back all users after creation
app.post('/node_modules/user-app/user', function(req, res) {
// create a user, information comes from AJAX request from Angular
User.create({
user_name: User.user_name,
password: User.password,
email: User.email,
location: User.location,
done : false
}, function(err, todo) {
if (err){
res.send(err);
}else{
// get and return all the users after creating one
getUsers(res);
}
});
});
// delete a user
app.delete('/node_modules/user-app/user:user_id', function(req, res) {
User.remove({
_id : req.params.user_id
}, function(err, user) {
if (err)
res.send(err);
getUsers(res);
});
});
};
I'm adding this user_api route and get method to the app.js file like so
// loading some required modules above this
var app = express();
var user = require('./routes/user_api')(app);
to handle the Angular and Node connection and state sharing i'm using the following
userController.js:
(function(){
'use strict'
var userCtrl = angular.module("userController",[]);
console.log('userController init')
userCtrl.controller('UserController', ['$scope','$http','Users',function($scope,$http,Users){
$scope.users = {};
$scope.loading = true;
console.log ("user init");
Users.get()
.success(function(data){
$scope.users = data;
$scope.loading = false;
console.log(data)
})
.error(function(err){
console.log('Error: ' + err);
});
$scope.createUser = function(){
if($scope.users.user_name != false){
console.log($scope.users.user_name)
$scope.loading = true;
Users.create($scope.users)
.success(function(data){
$scope.loading=false;
$scope.users = data;
console.log(data);
})
.error(function(err){
console.log('Error: ' + err);
});
}
};
}]);
})();
Change the line where you require User to
var User = require('./node_modules/user-app/user').User;
This is because in your export statement when you define a user you have the line:
module.exports = {User:User};
So, you are exporting an object that has a User property on it.

Mongoose $addToSet return new list entrys

I have a question working with mongoose 4.0.1
I am trying to add new picture objects to an array inside a model. This is the code of my endpoint that is actually doing the job:
// Add new images
exports.pictures = function(req, res) {
Incident.findByIdAndUpdate(
req.params.id,
{$addToSet: {"pictures": {$each: req.body}}},
{new: true},
function(err, incident) {
if (err) { return handleError(res, err); }
return res.send(201).json(incident.pictures);
}
);
};
The problem: The callback object (incident) stores all information of the model which was found and updated. But I want to return only the new array entries which were created.
How can I receive the actual changes of the operation instead of the whole object that is storing the pictures array?
I solved the problem by creating a new schema for pictures and adding a reference to the incident model.
The endpoint changed as well:
Create new picture instances for a array of pictures
Find incident by id
Save the references of the picture instances to a array inside the incident
Return the id of the picture instances
var _ = require('lodash');
// Add new images
exports.pictures = function(req, res) {
Picture.create(req.body, function(err, pictures) {
if (err) { return handleError(res, err); }
Incident.findByIdAndUpdate(
req.params.id,
{$addToSet: {"pictures": {$each: pictures}}},
function(err) {
if (err) { return handleError(res, err); }
var pictureIds = _.map(pictures, '_id');
return res.status(201).json(pictureIds);
}
);
});
};

Resources