I have been following the docs on how to update a trip using Node.js,mongoose,express, as well as a couple of stack overflow questions here and here.
Inside of my Controller I originally had a save, which was working, but I needed to switch it to an update. When I run the code, nothing breaks and the place is properly logged to the console as I would expect, which further indicates that the code is being run, but for some reason it isn't overwriting the item that has the same placeIdentifier.
What am I doing wrong that prevents this from updating?
My controller:
var place = {
identifier: placeIdentifier,
name: placeName,
location: Location,
travelStart: startDate,
travelEnd: endDate,
}
Place.findOneAndUpdate(
{identifier:placeIdentifier},
{ $set: place },
{upsert: true},
function() {
console.log(place)
console.log("place saved...")
}
);
Oh, I got it. Or rather, this person got it: Mongoose: Find, modify, save
User.findOne({username: oldUsername}, function (err, user) {
user.username = newUser.username;
user.password = newUser.password;
user.rights = newUser.rights;
user.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
});
Related
I am trying to update one element of snippets in my mongoose schema.
My Mongoose schema.
const Schema = new mongoose.Schema({
// ...
createdAt: Date,
snippets: {} // here I push ['string..', ['array of strings..']]
})
Here's a view of snippets in Compass.
Problem with the code below is that it completely erases other elements stored, other than that it works. Unable to specify that I want to update snippets[0], not entire thing..?
User.findOneAndUpdate({ username: req.session.user.username },
{ $set: { snippets: [snippet] } }, callback)
Tried using findOne andsave but it wouldn't update the db.
const snippet = [req.body.code, [req.body.tags]]
User.findOne({ username: req.session.user.username }, function (err, fetchedUser) {
if (err) console.log(err)
fetchedUser.snippets[req.params.id] = snippet // should be set to new snippet?
fetchedUser.save(function (err, updatedUser) {
if (err) console.log(err)
console.log('edited')
// ...
})
})
Any suggestions?
I thought I tried this earlier, but apparantly not.
Using fetchedUser.markModified('snippets') solved my issue with findOne/save not actually saving to DB.
I posted this question yesterday because I didn't know how to solve my problem.
Change variable value in document after some time passes?
I was told I need to use a pre hook. I tried to do it, but "this" would refer to the query, not to the document. So I couldn't retrieve the documents to check if the 4 weeks passed. (check the question, you will get it)
Because I don't know how to make this .pre('find') to use variables from each of my document (so it checks if the 4 weeks passed) I was thinking about looping through all of them and checking if 4 weeks passed.
router.get('/judet/:id([0-9]{2})', middleware.access2, function(req, res)
{
var title = "Dashboard";
Somer.find({}, function(err, someri)
{
if(err)
{
console.log(err);
}
else
{
res.render("dashboard", {title: title, id:req.params.id, someri:someri});
}
});
}); ///get route
var someriSchema = new mongoose.Schema({
nume: {type: String, required: true},
dateOfIntroduction: {type:Date, default: Date.now, get: formatareData},
});
someriSchema.pre('find', function(next) {
console.log(this.dateOfIntroduction); <- this will return undefined, because this refers to the query, actually
next();
});///schema and the pre hook. I thought I could use it like this, and inside the body of the pre hook I can check for the date
Here's what I am talking about:
router.get('/judet/:id([0-9]{2})', middleware.access2, function(req, res)
{
var title = "Dashboard | Best DAVNIC73";
Somer.find({}, function(err, someri)
{
if(err)
{
console.log(err);
}
else
{
someri.forEach(function(somer)
{
///check if 4 weeks passed and then update the deactivate variable
})
res.render("dashboard", {title: title, id:req.params.id, someri:someri});
}
});
});
but I think this will be very bad performance-wise if I will get many entries in my DBs and I don't think this is the best way to do this.
So, if I was told correctly and I should use a pre hook for obtaining what I've said, how can I make it refer to the document?
Ok, I think I understood your requirements. this is what you could do:
/*
this will always set a documents `statusFlag` to false, if the
`dateOfIntroduction` was before Date.now()
*/
const mongoose = require('mongoose')
someriSchema.pre('find', function(next) {
mongoose.models.Somer.update(
{ datofIntroduction: { $lte: new Date() }},
{ statusFlag : false})
.exec()
.then((err, result) => {
// handle err and result
next();
});
});
The only problem I see, is that you are firing this request on every find.
in query middleware, mongoose doesn't necessarily have a reference to
the document being updated, so this refers to the query object rather
than the document being updated.
Taken straight from the documentation of mongoose
I pointed you yesterday to their documentation; but here is a more concrete answer.
someriSchema.post('find', function(res) {
// res will have all documents that were found
if (res.length > 0) {
res.forEach(function(someri){
// Do your logic of checking if 4 weeks have passed then do the following
someri.deactivated = true
someri.save()
})
}
})
What this basically do is for every found schema you would update their properties accordingly, your res can have only 1 object if you only queried 1 object. your second solution would be to do the cron
EDIT: This is what you would do to solve the async issue
const async = require('async')
someriSchema.post('find', function(res) {
async.forEach(res, function(someri, callback) {
// Do your logic of checking if 4 weeks have passed
// then do the following - or even better check if Date.now()
// is equal to expiryDate if created in the model as suggested
// by `BenSow`
// Then ONLY if the expiry is true do the following
someri.deactivated = true
someri.save(function (err) {
err ? callback(err) : callback(null)
})
}, function(err){
err ? console.log(err) : console.log('Loop Completed')
})
})
Yet another first-timer problem here. This gets data from a database and displays it in some text fields (that part is not shown in the code below) and after the user edits it the data should be updated in the database via the findAndModify() method and I think this is where the issue lies. There are no errors, it just doesn't do anything. EDIT The following error is received: MongoError: Either an update or remove=true must be specified
server.js
MongoClient.connect("mongodb://user:secretPassword#aws-us-east-1-portal.7.dblayer.com:10712,aws-us-east-1-portal.10.dblayer.com:10316/database", function(err, db) {
if (err) throw err;
var contactList = db.collection("contactList");
app.put('/contactList/:id', function(req, res) {
var id = req.params.id;
console.log("edited: " + req.body.name); //works up until here
contactList.findAndModify({
query: {_id: mongojs.ObjectId(id)},
update: {$set: {name: req.body.name, email: req.body.email, number: req.body.number}},
new: true
}, function (err, doc) {
res.json(doc);
})
});
controller.js
$scope.update = function() {
$http.put('/contactList/' + $scope.contact._id, $scope.contact).success(function(response) {
refresh();
})
};
If this were me I would first do a couple of things:
Before your call to findAndModify just do a simple find using your query. Make sure you can actually find the object using your query. If that works you know that the 'find' part of the findAndModify is probably ok.
Do some console logging inside the callback handler of the findAndModify call. As it stands you do not do anything if an err is returned from the findAndModify call. It is possible your call is returning an error that you are just ignoring and it may provide some additional insight into your problem.
I would try these two first and see if it helps.
Update:
Example using native:
collection.findAndModify(
{ field: 'some value' },
[],
{ $set: { field2: 'some new value' } },
{ new:true },
function(err, doc) {
//handle err and doc
});
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.
Say I got this lil chunk of code:
Room.findOneAndUpdate({ Roomid: roomid }, { $push: { UsersMeta: UserMeta}}, { new: false }, function (err, room) {
if (err) console.log(err);
console.log('room output:');
console.log(room);
client.emit('others', room);
})
which is searching for one document in db, updates it, and then sends this room doc in pre-updated state back to client. What I need is to make some changes to responded room, particularly remove those _id, __v, and, possibly, any other custom part of doc.
What I was trying to do:
use toObject.transform while creating schema
var RoomSchema = mongoose.Schema({
Roomid: { type: String, unique: true },
///stuff///
});
RoomSchema.options.toObject.transform = function (doc, ret, options) {
// remove the _id of every document before returning the result
delete ret._id;
}
failed: recieved cannot set property 'transform' of undefined error.
Change mentioned chunk of code to:
Room.find({ Roomid: roomid })
.update({ $push: { UsersMeta: UserMeta} })
.select({ _id: 0 })
.exec(function (err, room) {
if (err) console.log(err);
console.log('room output:');
console.log(room);
client.emit('others', room);
})
Failed: always recieve [] in room output.
Now I stopped at manually setting {_id: false} on Schema declaration, completely getting rid of _id in the first place. As I want use custom random id's for rooms, it seems that I don't need those _id anyway. Yet I'm not sure, that such a treatment will not cause some unpleasant consequences.
And, moreover, problem of possible need to leave some non _id doc properties out of response - is an unsolved mystery for me.
Thank you for attention.
you can do the following and it should work;
RoomSchema.set('toJSON', {
transform: function (doc, ret, options) {
delete ret._id;
delete ret.__v;
}
});