MongoDB updating empty field after initial insert - angularjs

In the Mongoose schema there is an empty field for objectId of another table. I want to fill that field after the User object is created, as the school object is made after user object is.
User:
name
age
dob
company (this is object id from company table)
Initially I thought using the FindOneandUpdate() function would do this but I have had no luck.
Anyone any idea's?
company.component.ts
joinCompany(i){
console.log(this.companyArr[i]._id);
this.authService.addmoreUser(this.companyArr[i]._id).subscribe(data =>{
if(data.success){
this.router.navigate(['dashboard']);
}
else{
this.flashMessages.show(data.msg,{cssClass: 'alert-
danger',timeout:3000});
}
})
}
auth.service.js
addmoreUser(id){
id = {companyid:id};
console.log(id);
let headers = new Headers();
headers.append('Authorization', this.authToken);
headers.append('Content-Type','application/json');
return this.http.put('http://localhost:3000/users/pushCompanyintoUser',id,{headers:headers})
.map(res => res.json());
}
companies.js - CRUD file
router.put('/pushCompanyintoUser', passport.authenticate('jwt', {session:false}), (req, res, next) => {
console.log(req.body);
User.findByIdAndUpdate(req.user._id,{companyid:req.body} , function(err,user) {
if (err) throw res.json({success:false, msg:'Failed to Update user!'});
else res.json({success: true, msg:'User Updated!!'})
});
});
That is from the angular frontend being passed to server and then trying to insert to db.
DB Schema
const UserSchema = mongoose.Schema({
fullname:{ type: String},
email:{ type:String, required:true},
username:{ type:String, unique:true,required:true },
companyid:{ type:mongoose.Schema.Types.ObjectId, ref: 'Company', required:false}, <== (This is the where I am trying to submit to, in an object thats already made)
dob:{ type:String, required:true },
addressline:{ type:String, required:true },
town:{ type:String,required:true },
county:{ type:String,required:true},
country:{ type:String, required:true},
phone:{ type:Number, required:true },
password:{ type:String, required:true }
});
The User object is inserted already just without a companyid, how do I go about adding the companyid after.

Related

How to insert an array of ids with create function in node

I Have defined this mongoose schema in node
`const bookingSchema = new mongoose.Schema({
tour: [
{
type: mongoose.Schema.ObjectId,
ref: 'Tour',
required: [true, 'Booking must belong to Tours!'],
},
],
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [true, 'Booking must belong to User!'],
},
price: {
type: Number,
required: [true, 'Booking must have a price'],
},
createdAt: {
type: Date,
default: Date.now(),
},
paid: {
type: Boolean,
default: true,
},
});
bookingSchema.pre(/^find/, function (next) {
this.populate('user').populate({
path: 'tour',
select: 'name',
});`your text`
});
Then when i try to create a booking i use the create function
await Booking.create({ tour, user, price });`
the tour param is an array of ids
but i get this error
"Booking validation failed: tour.0: Cast to [ObjectId] failed for value "["5c88fa8cf4afda39709c295a,5c88fa8cf4afda39709c2951"]" (type string) at path "tour.0"
I can do it with only one tour if the tour property wasnt an array of objects. My main issue is that a booking can be related to many tour objects in my database
*edit after some modifications the error become
"Unexpected token u in JSON at position 0"
My front end code(angular) is this. I am making a get request to my backend(node)
createBookingCheckout(params: any): Observable<any> {
console.log('serv');
return this.http.get<any>(`${CREATE_BOOKING_CHECKOUT}`, {
params,
withCredentials: true,
});
}
So i pass the ids as query param
And this is the backend where i am trying to create the booking
exports.createBookingCheckout = catchAsync(async (req, res, next) => {
const { order, tour: strTour } = req.query;
const user = req.user._id;
const parsedOrder = JSON.parse(order);
const tour = JSON.parse(strTour);
console.log(tour);
// const tours = await tour.forEach((id) => {
// Tour.find({ id });
// });
// console.log(tours);
let price = 0;
parsedOrder.forEach(
(obj) => (price = price + obj.price_data.unit_amount * obj.quantity)
);
if (!parsedOrder && !user) return next();
await Booking.create({ tour, user, price });
res.redirect(req.originalUrl.split('?')[0]);
res.status(200).json({
status: 'success',
});
});
I think the quick solution to this is that whenever you are going to add more than a tour you should create an array push all tours IDs to the array and then add the tourArray to the new Booking that you are going to create, and when you are going to update an existing Booking, you should repeat the process.
When you are going to create a new Booking document.
Scenario 1 : with one Tour
You just pass the id of the tour {always check if the tour exist}, that's obvious and simple, at the same time mongo is going to create a table referring to the model as Tour is defined as many within your Booking model
Scenario 2 : with more than one Tour
You need to define all the Tour's IDs in an array within the body
{
"tour": [ "id-1", "id-2", ...]
}
Updating a Booking
say that you are going to add a new Tour to an existing Booking,
Booking.findByIdAndUpdate(
{_id: id},
{
// ! here all your other data
$push: {tour: new_tour}
},
// this is just to return the updated booking
{new: true, runValidators: true}
}
=> the operator $push in mongoose is what you need to push into the existing array or tour that's already in your existing Booking
The new_tour is coming from your req.body
as for sure in some cases you are going to delete a Tour ID from a Booking,
=> in that case you are going to use the operator $pull

mongodb sending userid's in an array as a query and return the json object of the users present in collection

I have a collection of online users here goes its model
var SessionDetailSchema = mongoose.Schema({
providerID: {
type: String
},
firstName: {
type: String
},
email: {
type: String
},
status: {
type: String
}
},{ timestamps: true });
var sessionDetail = module.exports = mongoose.model('OnlineUser', SessionDetailSchema);
I am trying to send an array of providerID's so that I wanted to check the collection which all providerId's are present and return me those providerID details.
and this is what I tried
router.post('/sessiondetails:find', function (req, res, next) {
console.log(req.body.providerID)
sessionDetail.find({ "providerID": { $in: req.body.providerID} }, function (err, users) {
if (users) {
console.log(users)
} else {
console.log("not there")
}
})
})
unfortunately, I am getting the only first providerid response for multiple times.
i am sending the array from the postman it looks like this
{
"providerID":["1090867867720278", "104761648907225164100", "114316680403119099502", "103668441331122956874"]
}
can some help me? thanks in advance.

Populating data from referenced models in different modules in MEAN.JS

I am absolutely new to the MEAN stack, and I am using the MEAN.js(ver 0.4.2) generator for my project.
I am using the default users module and created a new module 'Topics' using the module generator. I have a basic role based login system using the users module where users can sign up and see/edit their profiles. In the profile, there is a reference to the topics module's mongoose model called 'Topics'.
topic.server.model.js looks like this(this is the schema for the topics) :
//Topic Schema
var TopicSchema = new Schema({
.......
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Topic', TopicSchema);
The content from this model can access the data from the users model. But the i cant get the items to show from the topics model, when i am referencing them from the users module.
My users model has this in the schema :
var UserSchema = new Schema({
......
interest: [{
type: Schema.Types.ObjectId,
ref: 'Topic'
}],
skills: [{
type: Schema.Types.ObjectId,
ref: 'Topic'
}]
});
mongoose.model('User', UserSchema);
I am trying to populate the data from topics using the following middleware :
exports.userByID = function (req, res, next, id) {
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).send({
message: 'User is invalid'
});
}
User.findById(id, '-salt -password').populate('interest', 'name').populate('skills', 'name').exec(function (err, user) {
if (err) {
return next(err);
} else if (!user) {
return next(new Error('Failed to load user ' + id));
}
req.model = user;
next();
});
};
I would need a little guidance as to how do i get the data in front end to show, something like {{user.interest.name}}.
Edit
In the users.profile.server.controller, the json is not getting created from this :
exports.me = function (req, res, next) {
var id = req.user._id;
User.findOne({
_id: id
}).populate('interest', 'name').populate('skills', 'name').exec(function(err, userData) {
if (err) return next(err);
if (!userData) return next(new Error('Failed to load User ' + id));
res.json(userData || null);
next();
});
};
Getting the following error in the terminal :
GET /api/users/me 400 22.173 ms - -
Error: Can't set headers after they are sent.

"User is not authorized" on meanjs

I would like to ask if there is anyone getting the same response on JSON format:
Objectdata: "User is not authorized"headers: (name) {status: 403statusText: "Forbidden"
Scenario:
User A post a product and add comment on the product.
Result: Successful.
User B comment on the same product:
Result: User is not authorized.
The code I'm using to update the product comment is here:
applicationname/`
// Add comment to Product
$scope.comment = function(){
// console.log("name: ",$scope.user);
// console.log("textarea: ",this.commentarea);
var comment = {
name: $scope.product.user.displayName,
text: this.commentarea
};
$scope.product.comments.push(comment);
$scope.product.$update(function() {
console.log('success update');
}, function(errorResponse) {
console.log('success error', errorResponse);
});
};
This is the server side.
'use strict';
/**
* Module dependencies.
*/
var init = require('./config/init')(),
config = require('./config/config'),
mongoose = require('mongoose'),
chalk = require('chalk');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
if (err) {
console.error(chalk.red('Could not connect to MongoDB!'));
console.log(chalk.red(err));
}
});
// Init the express application
var app = require('./config/express')(db);
// Bootstrap passport config
require('./config/passport')();
// Start the app by listening on <port>
app.listen(config.port);
// Expose app
exports = module.exports = app;
// Logging initialization
console.log('MEAN.JS application started on port ' + config.port);
If your Products schema looks like this:
var ProductSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
comments: [{
type: String,
default: '',
trim: true
}]
});
And you have restricted your products route in your app/routes/products.server.routes.js file like so:
app.route('/products/:productId')
.get(products.read)
.put(users.requiresLogin, products.hasAuthorization, products.update)
.delete(users.requiresLogin, products.hasAuthorization, products.delete);
Then a non-authorized user cannot add a comment because they can't update the Product record.
You probably want to create a separate CommentsSchema and use the Mongoose ObjectId type to create a one-to-many relationship with the product:
var CommentSchema = new Schema({
product: ObjectId,
content: {
type: String,
default: '',
trim: true,
required: 'Content cannot be blank'
},
})
That will preserve the security of your product and allow non-authorized users to comment, but would require you to do slightly more complex queries to get your comments in your product view.

Mongoose deep populate with self-referencing children

This is working code to populate my Locations collection, which can have self-referencing child Locations. It uses mongoose-deep-populate. But I need to add another ".childLocations" to my path variable for every extra level of depth that I want to handle. Is there a better way to accomplish unknown depths of self-references?
I have this node.js code.
var path = 'childLocations.childLocations.childLocations.childLocations.childLocations.childLocations';
exports.list = function(req, res) {
Location.find().sort('-created').populate('user', 'displayName').deepPopulate(path).exec(function(err, locations) {
console.log(locations);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(locations);
}
});
};
Here is the schema:
var LocationSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Location name',
trim: true
},
projectsExecutedHere: Boolean,
childLocations: [{
type: Schema.ObjectId,
ref: 'Location'
}],
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Location', LocationSchema);
var deepPopulate = require('mongoose-deep-populate');
LocationSchema.plugin(deepPopulate);
----------
Before trying mongoose-deep-populate, I had seen that mongoose 3.6 had support for deep population, but I could only make it go one level deep. This is what I tried:
Location.find().sort('-created').populate('user', 'displayName').populate('childLocations').exec(function (err, locations) {
Location.populate(locations, {path: 'childLocations.childLocations'},
function (err, data) {
console.log(err);
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(locations);
}
}
);
For the path I also tried 'childLocations.childLocations.childLocations' but it didn't populate it at all.

Resources