How can I update a child object in an Array in mongodb - angularjs

I have the following problem, I edit patient info and want to update this patients info. What is the best way to do this?
var department = mongoose.model('department', {
departmentName: String,
rooms: [{
roomNumber: String,
width: Number,
height: Number,
posX: Number,
posY: Number,
sanitary: Boolean,
childcareArea: Boolean,
lounge: Boolean,
patient: {
patientnr: Number,
firstname: String,
lastname: String,
reasonOfHospitalization: String,
dateOfHospitalization: String,
expectedDateOfDischarge: String,
vegetarian: Boolean,
needsHelp: Boolean,
comments: String,
department: String,
roomNumber: String,
nextTreatment: {
type: String,
shortDescription: String,
timestamp: String
}
}
}]
});
I will probably need something like this...
app.post('/api/departments/patients/:id', function(req, res) {
department.update({..})
});

You'll need something along the lines of
app.post('/api/departments/patients/:id', function(req, res) {
//first, find the document
department.findById(req.params.id, function(err, dept){
//make changes accordingly
dept.patient.firstname = 'Changed'
dept.save(function(err){
res.send ('Saved');
})
});
});

Since I see you are using angular js also so you can just pass the elements that you want to update .
so your req.body can contain variables you want to update .
Remember its $set for update of object and $push for update of array
Now
app.post('/api/departments/patients/:id', function(req, res) {
department.findByIdAndUpdate({id : req.params.id},
{
$push:
{
rooms.roomnumber: req.body.departmentName
}}, {new : true}), function(err,doc){
console.log(doc);
})
});

Related

How to properly do nested schema with mongoose in React?

I have a Class schema that looks like this:
const ClassSchema = new mongoose.Schema({
title: {
type: String,
...
},
classImageURL: {
type: String,
...
},
imageWidth: {
type: String,
...
},
imageHeight: {
type: String,
...
}
});
module.exports = mongoose.models.Class || mongoose.model("Class", ClassSchema);
And a Subject schema that looks like this:
const SubjectSchema = new mongoose.Schema({
subjectTitle: {
type: String,
...
},
subjectImageURL: {
type: String,
...
},
imageWidth: {
type: String,
...
},
imageHeight: {
type: String,
...
},
});
module.exports =
mongoose.models.Subject || mongoose.model("Subject", SubjectSchema);
On a dynamic page named [className], I am getting the data of the particular className from the database and destructured it. Now, on the class page, I want to send a post request to the database using all the fields titled in the Subject schema. But, I also want to add the class data that I got and add it to the Subject schema.
I used a state to hold all the data:
setForm({
subjectTitle: enteredSubjectTitle,
subjectImageURL: response.data.url,
imageWidth: response.data.width,
imageHeight: response.data.height,
classDetail: classDetail // this is the data I have on the particular class data
}); // I want to add
And I tried to make changes in the Subject schema like this:
classDetail: { Class }, // I added this in the last part of the schema
It results in a post error.
How can I achieve what I want to?

fetch values from a loop inside .then in nodejs out in allemails array

// importing required builtin modules
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mydb');
// schema for email
var emailSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
html: String,
text: String,
headers: {},
subject: String,
references: [String],
messageId: String,
inReplyTo: [String],
priority: String,
from: [],
replyto: [String],
to: [],
date: Date,
receivedDate: Date,
attachments: [],
read: { type: Boolean, default: 0 },
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
active: { type: Boolean, default: 1 },
labels: [String]
});
// schema for thread
var threadSchema = mongoose.Schema({
threadedEmails: [{ type: String, ref: 'Email' }],
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }
});
// defining models
var Email = mongoose.model('Email', emailSchema);
var Thread = mongoose.model('Thread', threadSchema);
module.exports = Email;
module.exports = Thread;
// function to return an array which contains yet anohter array of emails each representing a thread
function doCalls() {
threads = [];
// a promise that always resolves
return new Promise(function (resolve, reject) {
resolve(1);
})
// this returns the threads as expected
.then(function (result) {
return Promise.resolve(
Thread.find({}, { threadedEmails: 1, _id: 0 }).then(
(_threads) => { return _threads }, //resolve
(err) => { reject(err); } //reject
)
)
})
// this does not returns the emails array as i expect
.then(function (threads) {
allEmails = [];
threads.forEach(thread => {
// Start off with a promise that always resolves
var sequence = Promise.resolve();
sequence = sequence.then(function (result) {
console.log('then of first foreach');
//query to make a database call to get all the emails whoes messageId's matchs
query = Email.find({ messageId: { "$in": thread.threadedEmails } });
query.exec((err, result) => {
if (err) throw err;
allEmails.push(result); //but this does not works because the code execution moves ahead
console.log(result); //this console log returns the value
});
})
})
//----------------- this is the problematic code here this array returns empty ----------------//
console.log(allEmails);
})
}
doCalls()
.then(function (allEmails) {
// console.log(allEmails);
});
I have written comments where ever i feel is required in the code, even though let me explain that context of what I am trying
I am fetching from a collection named threads all the threads which goes successfully
after that I am trying to fetch all the emails from a collection named email using a database query the output of which i am trying to store inside an array called allEmails
if i console.log() it in .then() just after the database call it does gives me the output,
my question is how do I get this out ?
I want an array which contains yet another array each having a collection of emails(each representing a thread) from emails collection
hope I made it clear, if there is anything else I require to provide please be my guide and tell me.
The forEach block finishes before any of the async operations inside it return. Thus , your allEmails array will still be empty when you console.log it.
What you need to do is build an array of promises that resolve with the "result" and then feed this array into Promise.all(arrayOfPromises) which will resolve when all your promises are resolved.
Promise.all is kind enough to resolve with the array of results for you.
Your last then would look something like:
.then(function (threads) {
const promiseArray = [];
threads.forEach(thread => promiseArray.push(
Promise.resolve(Email.find({ messageId: { "$in": thread.threadedEmails } }))
)
);
return Promise.all(promiseArray);
}
That being said, for what you're trying to achieve, Model.aggregate() would be a much more elegant solution.
Hope this helps

NodeJS/MongoDB - Match Value in Array with a Value from a Logged In User

I want Users to be able to Report a File/Video only once. By pushing the users ID to a Array, then check if the user has already reported the file.
So far I am able to find the current user, then the VideoID, increment by 1 and then push it to the reportedBy array. But I am pretty lost, when it comes to checking if the current user has already reported the file. Any tips/help will be much appreciated! :-)
MY ROUTE
router.get('/report/:videoLink', function(req, res, next){
async.waterfall([
function(callback){
User.findOne({_id: req.user._id}, function(err, foundUser){
if(err) return next(err)
callback(err, foundUser)
})
},
function(foundUser, callback){
Video.findOne({videoLink: req.params.videoLink}, function(err, reportVideo){
reportVideo.reports++;
reportVideo.reportedBy.push(foundUser);
if (reportVideo.reports > 4) {
reportVideo.remove();
}
reportVideo.save(function(err){
if(err) return next();
});
res.redirect('/');
});
}
]);
});
MY SCHEMA
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var random = require('mongoose-simple-random');
var fragSchema = new Schema({
title: String,
videoLink: {type: String, unique: true, required: true},
category: String,
upVotes: {type: Number, default: 0},
downVotes: {type: Number, default: 0},
voted: {type: Boolean, default: false},
reports: {type: Number, default: 0},
reportedBy: [{ type: Schema.Types.ObjectId, ref: 'User'}],
ownByUser: {type: Schema.Types.ObjectId, ref: 'User'},
date: { type: Date, default: Date.now }
});
fragSchema.plugin(random);
module.exports = mongoose.model('Frag', fragSchema);
This should find the video only if it was reported by that user before:
Video.findOne({
videoLink: req.params.videoLink,
reportedBy: foundUser._id,
}, ...
and this should find the video only if it was not reported before:
Video.findOne({
videoLink: req.params.videoLink,
reportedBy: {$nin: [foundUser._id]},
}, ...
There are many ways to achieve that but you get the idea.
If you want to find the video anyway an then test if it was already reported by that user then something like this inside of your Video.findOne callback:
if (reportVideo.reportedBy.indexOf(foundUser._id) < 0) {
// not reported by that user yet
} else {
// already reported by that user
}
If you're using lodash then you can use:
if (_.includes(reportVideo.reportedBy, foundUser._id)) {
// already reported by that user
} else {
// not reported by that user yet
}
Make sure that you have the IDs as strings, maybe you will need to use .toString() or something like that before the comparisons.

How can I push element to array in http.put in angularjs?

I have the following schema:
var UserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
projects: [{type: Schema.ObjectId, ref:'Project'}],
//....
}
How can I add projectId by using http.put?
This is among the things that I have tried:
$http.put('/api/users/'+User._id, {'projects': project._id});
Solved it using:
$http.put('/api/users/'+User._id, {'projects': User.projects});
and in my update method:
_.extend(user, req.body);
instead of
_.merge(user, req.body);

mongoose update with push operations on array and set operation on object

I have this mongoose schema
var ContactSchema = module.exports = new mongoose.Schema({
name: {
type: String,
required: true
},
phone: {
type: Number,
required: true,
},
messages: [
{
title: {type: String, required: true},
msg: {type: String, required: true}
}],
address:{ city:String,
state:String
}
});
I have initially the collection set with name and phone field. I need to update the collection with new messages into messages array and new address into address object. the function must also need to handle any single operation, ie in some case i have only update to messages array or updates to both name and address. so how i can i do all operations in a single function.
var messages= {
title: req.body.title,
msg: req.body.msg
}
Model.findOneAndUpdate({'_id': req.body.id,},{$push: {messages:message}},{upsert: true}, function (err, data) {
if (err) {
return res.status(500).send(err);
}
if (!data) {
return res.status(404).end();
}
return res.status(200).send(data);
});
You could try use both the $set and $push operators in your update object. Suppose, for example, you want to update both name and address fields in one single operation, use the $set on the name field and a $push operation to the address array:
var messages= {
title: req.body.title,
msg: req.body.msg
},
query = {'_id': req.body.id},
update = {
$set: {name: req.body.name},
$push: {messages: message}
},
options = {upsert: true};
Model.findOneAndUpdate(query, update, options, function (err, data) {
if (err) {
return res.status(500).send(err);
}
if (!data) {
return res.status(404).end();
}
return res.status(200).send(data);
});

Resources