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
});
Related
I have developed a mean stack application. I am trying to update a record with a null value for the Date field. This is working fine on my localhost but not on my server (Aws Ec2). It contains the previous value before the update.
I have also tried 'undefined' but still same issue.
Visit mongodb set null in update
router.put('/editAssign/:id',(req,res)=>{
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No record with given id : $(req.params.id)');
var assignment = {
name: req.body.name,
code: req.body.code,
appointmentTime: req.body.appointmentTime,
scheduledTime:req.body.scheduledTime,
countEndTime: null
};
Assignment.findOneAndUpdate(req.params.id,{$set:assignment},{new:true},(err,doc)=>{
if(!err)
res.send(doc);
else
console.log('Error in Assignment Update: '+JSON.stringify(err,undefined,2));
});
});
I expect it to work on my server too.
I have done a similar thing with updating the last login date of a user when they log in using Mongoose.
const authUser: any = await new Promise((res, rej) => {
User.findOneAndUpdate({ _id: user[0]._id }, { last_login: date }, {new: true}, (err: any, user:any) => {
if (err) rej(err);
res(user);
});
});
As you can see I wrapped it in a promise so i can wait for the response for sending back.
From looking at yours I would it looks like you are not telling it to look for using findByIdAndUpdate and not findOneAndUpdate because you are only passing in the ID. So the updated should look like this.
Assignment.findByIdAndUpdate(req.params.id, assignment, {new:true}, (err,doc)=>{
if(err) console.log('Error in Assignment Update: '+JSON.stringify(err,undefined,2));
return res.send(doc);
});
So in the one above, we are passing over the ID for findByIdAnyUpdate and we are just passing in the assignment. which if it includes all the same fields as the schema it will just update with the latest fields.
EDIT:
One other method you could try is:
Assignment.findByIdAndUpdate(req.params.id, assignment, {new: true}, (err: any, result: any) => {
if(err) console.log('Error in Assignment Update: '+JSON.stringify(err,undefined,2));
// Reasign with new assignment and save
result = assignment;
result.save();
return res.send(result);
});
So, what I'm doing should be really simple, and maybe it is and I'm just doing something wrong. I want to update an existing document in my database but I'm having some issues, can someone please advise?
Nano's Documentation states the following for insert:
db.insert(doc, [params], [callback])
Therefore, I should surely be able to do the following:
var user = {
'firstname' : 'my',
'secondname' : 'name'
};
db.insert(user, {_rev: '2-cc5825485a9b2f66d79b8a849e162g2f'}, function(err, body) {});
However, whenever I try this, it creates an entirely new document. If I do the following then it will indeed update my document, but of course, with nothing in this document other than the _rev:
db.insert({_rev: '2-cc5825485a9b2f66d79b8a849e162g2f'}, function(err, body) {});
So the question is, how do I pass in my object and get it to update, rather than creating a new record?
var user = {
'firstname' : 'my',
'secondname' : 'name',
'_id': <id from prev object>,
'_rev': <rev from prev object>
};
db.insert(user, function(err, body) {});
the _id and _rev are both required in order for the update to work.
they should be in the object that you are sending also.
The first argument in the db.insert(...) command is the document which you want to create/update. If you pass in a doc with a ._rev attribute, then it will replace the document with that same _rev in Cloudant with the doc passed in as the first argument of your db.insert(...). If the doc does not include a ._rev attribute, then Cloudant will create an entirely new document.
This explains the behavior you were experiencing in both the scenarios you tried. In order to make an update to your doc, make sure to include ._id and ._rev attributes, along with the rest of your doc's attributes when you use it as the first argument to your db.insert(...) function.
Got it! Here's the solution:
db.get('user', { revs_info: true }, function(err, doc) {
if (!err) {
console.log(doc);
doc.firstname = 'my';
doc.secondname = 'name';
db.insert(doc, doc.id, function(err, doc) {
if(err) {
console.log('Error inserting data\n'+err);
return 500;
}
return 200;
});
}
});
First get the record id and rev id (_id,_rev)
const newData={email:"aftabfalak956#gmail.com",name:"Aftab Falak"}
cloudant.use("user").find({selector:{_id:"user_id"}}, (err, documents) => {
var revision = documents.docs[0]._rev;
const data={...documents.docs[0],...newData};
cloudant.use("user").insert(data,{_rev:revision},function(err){
if (!err) {
console.log('success', 'The record was updated successfully');
}
else {
console.log('failure', err);
}
});
});
I'm pretty new to Mongoose/Mongo and node.js, so I suspect this is just a misunderstanding on my side, but...
The code sample below is the smallest failing example, not specifically my use case.
var User = app.db.model('User');
User.find({email: 'm8#test.com'}, function (err, models) {
models[0].update(function(err, mod) {
console.log(err.message)
});
});
This results in the following error: After applying the update to the document {_id: ObjectId('54647402cb955748153ea782') , ...}, the (immutable) field '_id' was found to have been altered to _id: ObjectId('546d9e0e539ed9ec102348f9')
Why is this happening? I would have thought calling update on the model returned from the initial find would have been fine.
Please note: in my use case there are things happening in between the find and the update. Specifically, I'm doing something similar to:
model.property.push(objectId)
Which I then want to commit via the update.
I'm sure this is a straight-forward issue, but I can't see anywhere in the docs I may be getting it wrong.
All help appreciated.
UPDATE:
What I actually needed to do was:
var User = app.db.model('User');
User.find({email: 'm8#test.com'}, function (err, models) {
models[0].save(function(err, mod) {
console.log(err.message)
});
});
Using 'save' rather than 'update'
I don't know if I understood
Find and Update ( for example using express )
var email = req.params.email;
User.find({email:email}, req.body, function(err,user){
if(err){
throw err;
}
//you do stuff like this
var obj = {
password:'new pass',
username:'username'
}
//use save if you want validate
User.update(user[0],obj,function(err, mod) {
console.log(err)
});
});
Only Update: ( for example using express )
User.update({email:email}, req.body, {}, function(err,user){
if(err){
throw err;
}
res.send(200, {
message : 'User updated ' + user
});
});
Remember that:
A model is a compiled version of the schema.
I hope this can help you
I have a function that is needed to get results.
When I give 1 as _id filter everything is OK.
collectionPersonnel
.find({ '_id' : 1 })
.toArray(function (err, personnel) {
console.log(personnel);
});
If I give filter another way for instance user[0]['personnel_id'] -that is store 1- then I get only [] result;
collectionPersonnel
.find({ '_id' : user[0]['personnel_id'] })
.toArray(function (err, personnel) {
console.log(personnel);
});
And then I've tried another way. But it doesn't work because I used a string(user[0]['personnel_id']) instead of an ObjectID.
var ObjectID = require('mongodb').ObjectID;
var personnelPK_Hex = (user[0]['personnel_id']).toHexString();
var personnelPK = ObjectID.createFromHexString(personnelPK_Hex);
What should I do?
Edit
All of my codes are below;
module.exports = {
show: function(req, res) {
User.native(function(err, collectionUser) {
if(err) {
console.log("There is no exist a User by current_id");
};
collectionUser
.find({'_id' : req.param('id')})
.toArray(function (err, user) {
Personnel.native(function(err, collectionPersonnel) {
if(err) {
// handle error getting mongo collection
console.log("There is no exist a Personel by current _id");
};
if(!collectionPersonnel) {
console.log("There is no exist a Personel by current _id");
};
// var ObjectID = require('mongodb').ObjectID;
// var personnelPK_Hex = (user[0]['personnel_id']).toHexString();
// var personnelPK = ObjectID.createFromHexString(personnelPK_Hex);
collectionPersonnel
.find({ '_id' : user[0].personnel_id })
.toArray(function (err, personnel) {
console.log(personnel);
});
});
});
});
}
};
And console's output is;
[]
Solved
Just like apsillers's said. I had given a numeric _id to collection, incorrectly.
I've fixed _id value and everything is OK.
Thank you all...
user[0]['personnel_id'] might be a string. For Mongo, "1" is different from 1, which is why your literal number 1 worked, but your variable (which holds a string) does not.
Instead, try using a unary plus to convert the string to a number: +user[0]['personnel_id'].
try to use like user[0].personal_id instead of user[0]['personnel_id'] please provide your schema design that would be better to figure out what exactly you are missing.
i tried like this
collectionPersonnel
.find({ '_id' : user[0].personnel_id })
.toArray(function (err, personnel) {
console.log(personnel);
});
I'm trying to update an existing document by increment a counter and pushing an object to an array.
Here's the schema for User:
var UserSchema = new Schema({
[...]
posts: {
totalWords: { type: Number, min: 0, default: 0 },
_entries: [
{
words: { type: Number, min: 0 },
body: { type: String },
date: Date
}
]
},
});
And here's the update code:
var newPost = {
words: req.body.words,
body: req.body.entry,
date: new Date()
};
User.findOne(req.user._id, function (err, user) {
var previous = user.posts.totalWords;
user.posts.totalWords = previous + newPost.words;
user.posts._entries.push(newPost);
user.save(function (err) {
if (err) return res.send(400, err);
return res.json(newPost);
});
});
I get the following error:
[TypeError: Object.keys called on non-object]
Any ideas on how to solve this?
Answering my own question
I was able to solve the problem by changing:
User.findOne(req.user._id, function (err, user) { [...] });
Into this:
User.findById(req.user._id, function (err, user) { [...] });
I think, if you would like to use findOne you need follow syntax:
User.findOne({'_id': req.user._id}, {}, function (err, user) {
...
});
Not sure about findById() vs. findOne(), but I've had problems with Mongoose objects returning Object.keys called on non-object while saving or updating with mal-formed data or data corresponding to an older schema. While initializing the document, Mongoose was expecting a subdocument of some kind, but the data in the database didn't match that.
For me it usually happens when I change schemas from a simple object (String, Number, etc.) to a more complex subdocument of some kind. The schema types are mixed up and the object won't load, not even to fix the problem. I had to go into my database using the native driver, search for mal-formed documents using the $type operator, and update them individually.