collection.save() not persisting data to mongodb - javascript

I'm totally new to Nodejs, and I've been trying to update a field in my collection to no avail. Here's my code for pushing into an array on the model.
update array field in model
Then here's my schema.
course schema
Any reason why the changes are not saved to my database ? Thanks .
NB: I've tried using markModified('enrolled_courses.completed_lesson'), but it didn't make any difference.

router.route('/yourRoute').post((req, res) => {
Schema.findOneAndUpdate({
username: newName
}, {
$set: {
enrolled_courses: [
{
key: newValue
}
]
}
}, {
upsert: true
}, function(err, user) {
if (err) {
res.json(err);
} else {
res.send({message: "Successfully updated"});
}
})
});

Related

How do I add new field in existing JSON

I have JSON with 10000 unique records and I need to add another field with a unique value to every record. How do I add that?
[
{
_id: "5fffd08e62575323d40fca6f",
wardName: "CIC",
region: "ABC",
location: "AAA",
specialism: "CSR",
__v: 0
},
.
.
.
]
The JSON is stored in variable showWard. How do I add an action field in my JSON with value = './wardName' where wardName is already a field in my JSON?
This is my current code:
app.get('/wards', function (req, res) {
Ward.find({}, function (err, showWard) {
if (err) { console.log(err); return; }
return res.send(showWard);
});
});
Using a .map()? I don't know the logic for determinate the gender, but in Ward.find() callback you can add a thing like that:
app.get('/wards', function (req, res) {
Ward.find({}, function (err, showWard) {
if (err) { console.log(err); return; }
const newShowWard = showWard.map(ward => {
ward.gender = "BOH";
return ward;
})
return res.send(newShowWard);
});
});

Mongoose update function is giving null and not actually updating information

My .findOneAndUpdate method is returning user as null and isn't ending up updating the information. Everything seems to be in order, I'm not getting any erros.
EDIT: I have made progress, I was able to finally update the GroupID, but its setting it as null. Instead of the passed in string.
router.put("/update", (req, res) => {
Users.findOneAndUpdate(
{ _id: req.body.id },
{
$set: { GroupID: req.body.GroupID }
},
{ new: true },
(err, user) => {
if (err) res.send(err);
else res.send("Account GroupID Updated" + user);
}
);
});
You have to convert req.body.id to objectId as follows:
var mongoose = require('mongoose');
var id = mongoose.Types.ObjectId(req.body.id);
Users.findOneAndUpdate(
{ _id: id }

Using Multiple FindOne in Mongodb

I am trying to extend the amount of fields that our API is returning. Right now the API is returning the student info by using find, as well as adding some information of the projects by getting the student info and using findOne to get the info about the project that the student is currently registered to.
I am trying to add some information about the course by using the same logic that I used to get the project information.
So I used the same findOne function that I was using for Projects and my logic is the following.
I created a variable where I can save the courseID and then I will put the contents of that variable in the temp object that sending in a json file.
If I comment out the what I added, the code works perfectly and it returns all the students that I require. However, when I make the additional findOne to get information about the course, it stops returning anything but "{}"
I am going to put a comment on the lines of code that I added, to make it easier to find.
Any sort of help will be highly appreciated!
User.find({
isEnrolled: true,
course: {
$ne: null
}
},
'email pantherID firstName lastName project course',
function(err, users) {
console.log("err, users", err, users);
if (err) {
return res.send(err);
} else if (users) {
var userPromises = [];
users.map(function(user) {
userPromises.push(new Promise(function(resolve, reject) {
///////// Added Code START///////
var courseID;
Course.findOne({
fullName: user.course
}, function(err, course) {
console.log("err, course", err, course);
if (err) {
reject('')
}
courseID = course ? course._id : null
//console.log(tempObj)
resolve(tempObj)
}),
///// ADDED CODE END //////
Project.findOne({
title: user.project
}, function(err, proj) {
console.log("err, proj", err, proj);
if (err) {
reject('')
}
//Course ID, Semester, Semester ID
//map to custom object for MJ
var tempObj = {
email: user.email,
id: user.pantherID,
firstName: user.firstName,
lastName: user.lastName,
middle: null,
valid: true,
projectTitle: user.project,
projectId: proj ? proj._id : null,
course: user.course,
courseId: courseID
}
//console.log(tempObj)
resolve(tempObj)
})
}))
})
//async wait and set
Promise.all(userPromises).then(function(results) {
res.json(results)
}).catch(function(err) {
res.send(err)
})
}
})
using promise could be bit tedious, try using async, this is how i would have done it.
// Make sure User, Course & Project models are required.
const async = require('async');
let getUsers = (cb) => {
Users.find({
isEnrolled: true,
course: {
$ne: null
}
}, 'email pantherID firstName lastName project course', (err, users) => {
if (!err) {
cb(null, users);
} else {
cb(err);
}
});
};
let findCourse = (users, cb) => {
async.each(users, (user, ecb) => {
Project.findOne({title: user.project})
.exec((err, project) => {
if (!err) {
users[users.indexOf(user)].projectId = project._id;
ecb();
} else {
ecb(err);
}
});
}, (err) => {
if (!err) {
cb(null, users);
} else {
cb(err);
}
});
};
let findProject = (users, cb) => {
async.each(users, (user, ecb) => {
Course.findOne({fullName: user.course})
.exec((err, course) => {
if (!err) {
users[users.indexOf(user)].courseId = course._id;
ecb();
} else {
ecb(err);
}
});
}, (err) => {
if (!err) {
cb(null, users);
} else {
cb(err);
}
});
};
// This part of the code belongs at the route scope
async.waterfall([
getUsers,
findCourse,
findProject
], (err, result) => {
if (!err) {
res.send(result);
} else {
return res.send(err);
}
});
Hope this gives better insight on how you could go about with multiple IO transactions on the same request.

Prevent Duplicate Documents in MongoDB?

I'm trying to figure out the best way to prevent duplicate documents from being saved in MongoDB.
Right now my form takes the user_url from the user. The logic is:
Check if the user_url is valid. (dns.lookup)
If user_url is new, save it to the database and return url_ID.
If user_url is old, just return the url_ID.
I think my 2 options are:
var findOneURL = function(user_url, done) {
URL.findOne({
orig_url: user_url
}, (err, data) => {
if (err) {
done(err);
}
done(null, data);
})
}
or
var findEditThenSave = function(user_url, done) {
URL.findById(user_url, (err, data) => {
if (err) {
done(err);
}
data.save((err, data) => {
if (err) {
done(err);
}
done(null, data);
});
})
};
It's not working terribly well at the moment but this is the live version:
https://kindly-fisherman.glitch.me/
EDIT2: I think I got it working properly now. Here's my logic:
Saving to database: dns.lookup -> findByURL -> (If it doesn't exist) -> countURLs -> findAndUpdateURL -> Return what was saved to database.
OR -> (If it exists) -> Return the record.
Retrieving from database: findByID
The best choice is findOneAndUpdate query with upsert and returnNewDocument options
db.collection.findOneAndUpdate({ orig_url: user_url }, { $set: { orig_url: user_url }}, { upsert: true, returnNewDocument: true })
In mongoose
URL.findOneAndUpdate({orig_url: user_url }, { $set: { orig_url: user_url }}, { upsert: true, new: true }, (err, data) => {
if (err) {
done(err);
}
// data will contain your document
done(null, data);
});
upsert option specifies whether to insert document if not found, new (returnNewDocument in mongo's console) - whether to return old or updated document - if false (default is false) you will have null for inserted documents.
Instead of using
db.insert()
you should use
db.update()
and specify
$upsert: true
[here]

Mongoose - remove array element in update

I have a JSON in this format:
{
_id:5522ff94a1863450179abd33,
userName:'bill',
__v:3,
friends:[
{
_id:55156119ec0b97ec217d8197,
firstName:'John',
lastName:'Doe',
username:'johnDoe'
},
{
_id:5515ce05207842d412c07e03,
lastName:'Adam',
firstName:'Foo',
username:'adamFoo'
}
]
}
And I would like to remove whole corresponding subarray. For example I want to remove user John Doe with ID 55156119ec0b97ec217d8197 so the result will be:
{
_id:5522ff94a1863450179abd33,
userName:'bill',
__v:3,
friends:[
{
_id:5515ce05207842d412c07e03,
lastName:'Adam',
firstName:'Foo',
username:'adamFoo'
}
]
}
So far I have this:
exports.delete = function (req, res) {
var friends = req.friends[0];
friends.update(
{'_id': req.body.friendsId},
{$pull: {'friends.friends': {_id: req.body.friendId}}}, function (err) {
if (err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
res.json(friends);
}
});
};
But without result and also I'm not getting any error, it will stay just same as before. req.body.friendsId is ID of main array and req.body.friendId is ID of specific user which I want to pull.
Change your update query to this:
exports.delete = function (req, res) {
var friends = req.friends[0]; // assuming the friends object is your mongodb collection
friends.update(
{ '_id': req.body.friendsId },
{ $pull: {'friends': { _id: req.body.friendId } } }, function (err) {
if (err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
res.json(friends);
}
});
};
This will search for documents which have the friends array element _id value = req.body.friendsId and removes the specific array element from that array using the $pull operator.

Categories

Resources