Node.js mongodb update over ObjectID - node.js

I want to update my Document but it's not working 100% .
// Initialize connection once
MongoClient.connect("mongodb://localhost:27017/testDB", function(err, database) { //"mongodb://localhost:27017/test"
if(err) throw err;
db = database;
});
My collection row looks like:
{ "_id" : ObjectId("53f9379ce9575bbe9ec29581"), "name:paco",
"status:student" }
Now if I want to update the row over the Document as follows:
db.collection('user', function(err, collection){
collection.update({'_id':ObjectID(req.session.loggedIn)}, {image : filename}, {w:1}, function(err, result){
console.log(result);
I am getting just:
{ "_id" : ObjectId("53f9379ce9575bbe9ec29581"), "image:filename" }
How can I make an update to get my data like this??:
{ "_id" : ObjectId("53f9379ce9575bbe9ec29581"), "name:paco",
"status:student" , "image:filename"}

Doing an update the way you did it is going to retrieve the document in your collection with the specified _id, then it is going to replace the content of this document with what you specified as your second parameter. In your case, it will retrieve the document with _id 53f9379ce9575bbe9ec29581, and replace the existing fields with the field you passed, image:filename (that means the existing fields will be removed, as you noticed).
What you want to do is use the $set operator. This operator will not touch the document retrieved, but only modify the field that you specified, or add it if it does not exist.
So your update command should look something like this:
db.collection('user').update({'_id':ObjectID(req.session.loggedIn)}, {$set: {image : filename}}, {w:1}, function(err, result){
console.log(result);

to update record by _id
var ObjectID = require('mongodb').ObjectID;
exports.updateUser = function(req, res) {
var collection = db.collection('users');
collection.update(where, $set:req.body, function(err, result) {
if (err) {
console.log('Error updating user: ' + err);
res.send({'error':'An error has occurred'});
} else {
console.log('' + result + ' document(s) updated');
res.send(user);
}
});
}

Related

mongoose findOne data does not exit not working

user_id 2 does not exist in mongodb but console log does not print 'does not exist'
var query = PostData.findOne({ 'user_id': '2'});
query.exec(function (err, doc) {
if(doc) {
console.log('ok');
} else {
console.log('does not exist');
}
});
Without mongoose it works:
connection.db.collection("PostData", function(err, collection){
collection.find({ 'user_id': '2'}).toArray(function(err, data){
console.log(data); // it will print your collection data
})
});
prints []
No matter an object exists or not , MongoDB is going to return an array anyway. If the object exists, they array will be filled with it otherwise it's just an empty array. So if you want to check if the user exists or not you must check for doc.length , if it's 0 then it means the user doesn't exist.

Unable to delete a document with passed "email" and "_id" anyhow

I wanted to delete a document with concerned _id and email when I click on "Remove task" in the HTML file.
Following is the code which removes that task:
I've passed value of email and _id(only hexadcemial string value) to the code:
collection.findOneAndDelete({email:email,_id:taskid},function (err, result) {
if (err) {
console.log(err);
} else {
console.log("Removed!");
console.log(result);
callback(result);
}
db.close();
});
But, the function is not recognizing _id that I've passed. The value of "taskid" variable is 566836bd8db43d3d56e23a4a i.e. only strings value from _id:
ObjectId("566836bd8db43d3d56e23a4a")
var taskid=566836bd8db43d3d56e23a4a;
I've tried every possible declaration of taskid to convert it so that the function could recognize the value of _id and match it:
var taskid= "ObjectId("+'"'+req.param('taskid')+'"'+")";
But till now, I am not able to match the _id with the taskid. Any fix?
if you are going to compare with ObjectId then
var ObjectId = require('mongoose').Types.ObjectId
collection.findOneAndDelete({email:email,_id:new ObjectId(taskid)},function (err, result) {
if (err) {
console.log(err);
} else {
console.log("Removed!");
console.log(result);
callback(result);
}
db.close();
});
Should work for you.
If you feel the job too hard for each and every query then you can create an new method.
String.prototype.toObjectId = function() {
var ObjectId = (require('mongoose').Types.ObjectId);
return new ObjectId(this.toString());
};
// Every String can be casted in ObjectId now
console.log('545f489dea12346454ae793b'.toObjectId());

Cannot applying find() method with Native MongoDB becaus of ID type

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);
});

How to check if Mongo's $addToSet was a duplicate or not

I am using Mongoskin + NodeJS to add new keywords to MongoDB. I want to notify the user that the entry was a duplicate but not sure how to do this.
/*
* POST to addkeyword.
*/
router.post('/addkeyword', function(req, res) {
var db = req.db;
db.collection('users').update({email:"useremail#gmail.com"}, {'$addToSet': req.body }, function(err, result) {
if (err) throw err;
if (!err) console.log('addToSet Keyword.' );
});
});
The result does not seem to be of any use since it doesn't state if the keyword was added or not.
At least in the shell you can differentiate if the document was modified or not (see nModified).
> db.test4.update({_id:2}, {$addToSet: {tags: "xyz" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test4.update({_id:2}, {$addToSet: {tags: "xyz" }})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Update for Node
When you use collection.update(criteria, update[[, options], callback]); you can retrieve the count of records that were modified.
From the node docs
callback is the callback to be run after the records are updated. Has
two parameters, the first is an error object (if error occured), the
second is the count of records that were modified.
Another Update
It seems at least in version 1.4.3 the native Mongo Node driver is not behaving as documented. It is possible to work around using the bulk API (introduced in Mongo 2.6):
var col = db.collection('test');
// Initialize the Ordered Batch
var batch = col.initializeOrderedBulkOp();
batch.find({a: 2}).upsert().updateOne({"$addToSet": {"tags": "newTag"}});
// Execute the operations
batch.execute(function(err, result) {
if (err) throw err;
console.log("nUpserted: ", result.nUpserted);
console.log("nInserted: ", result.nInserted);
console.log("nModified: ", result.nModified); // <- will tell if a value was added or not
db.close();
});
You could use db.users.findAndModify({email:"useremail#gmail.com"},[],{'$addToSet': { bodies: req.body }},{'new':false}). Pay attention to new:false switcher, it allows you to get document before update and you could check whether array contained item before update. However, it could be problematic approach if your documents are big, because you analyze it on client side.
P.S. Your original query with $addToSet is wrong: field name is missing.
Edit: I tried to use count returned by update, but it returns 1 for me in all cases. Here is the code I used for test with MongoDB 2.6:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/mtest', function(err, db) {
if(err) throw err;
db.collection('test').insert({_id:1,bodies:["test"]},function(err,item){
db.collection('test').update({_id:1},{$addToSet:{bodies:"test"}}, function(err,affected){
if(err) throw err;
console.log(affected); //1 in console
});
});
});
i am update a array from Collection with this JSON:
{
"<arrayname>":"<value>"
}
route.js
routes.post("/api/:id", Controller.addOne);
Controller.js
async addOne(req, res) {
//juryman id to list add
if (Object.keys(req.body).length === 1) {
console.log("Size 1");
}
await Session.findOneAndUpdate(
{ _id: req.params.id },
{ $addToSet: req.body }
)
.then(function(success) {
res.send("Successfully saved.");
})
.catch(function(error) {
res.status(404).send(error);
});
},
I have five arrays in my Collection and this changes the JSON array name-value and updates correctly, the respectively Collection array. This works only for one item.

MongoDB node native driver creating duplicate documents

I'm getting a duplicate document when using the mongodb-native-driver to save an update to a document. My first call to save() correctly creates the document and adds a _id with an ObjectID value. A second call creates a new document with a text _id of the original ObjectID. For example I end up with:
> db.people.find()
{ "firstname" : "Fred", "lastname" : "Flintstone", "_id" : ObjectId("52e55737ae49620000fd894e") }
{ "firstname" : "Fred", "lastname" : "Flintstone with a change", "_id" : "52e55737ae49620000fd894e" }
My first call correctly created Fred Flinstone. A second call that added " with a change" to the lastname, created a second document.
I'm using MongoDB 2.4.8 and mongo-native-driver 1.3.23.
Here is my NodeJS/Express endpoint:
app.post("/contacts", function (req, res) {
console.log("POST /contacts, req.body: " + JSON.stringify(req.body));
db.collection("people").save(req.body, function (err, inserted) {
if (err) {
throw err;
} else {
console.dir("Successfully inserted/updated: " + JSON.stringify(inserted));
res.send(inserted);
}
});
});
Here is the runtime log messages:
POST /contacts, req.body: {"firstname":"Fred","lastname":"Flintstone"}
'Successfully inserted/updated: {"firstname":"Fred","lastname":"Flintstone","_id":"52e55737ae49620000fd894e"}'
POST /contacts, req.body: {"firstname":"Fred","lastname":"Flintstone with a change","_id":"52e55737ae49620000fd894e"}
'Successfully inserted/updated: 1'
Why doesn't my second update the existing record? Does the driver not cast the _id value to an ObjectID?
What you are posting back the 2nd time contains a field named "_id", and it's a string. That is the problem.
Look at the document, what the save method does is a "Simple full document replacement function". I don't use this function quit often so here's what I guess. The function use the _id field to find the document and then replace the full document with what you provided. However, what you provided is a string _id. Apparently it doesn't equal to the ObjectId. I think you should wrap it to an ObjectId before passing to the function.
Besides, the save method is not recommended according to the document. you should use update (maybe with upsert option) instead
I don't exactly know why a second document is created, but why don't you use the update function (maybe with the upsert operator)?
An example for the update operation:
var query = { '_id': '52e55737ae49620000fd894e' };
db.collection('people').findOne(query, function (err, doc) {
if (err) throw err;
if (!doc) {
return db.close();
}
doc['lastname'] = 'Flintstone with a change';
db.collection('people').update(query, doc, function (err, updated) {
if (err) throw err;
console.dir('Successfully updated ' + updated + ' document!');
return db.close();
});
});
And now with the upsert operator:
var query = { '_id': '52e55737ae49620000fd894e' };
var operator = { '$set': { 'lastname': 'Flintstone with a change' } };
var options = { 'upsert': true };
db.collection('people').update(query, operator, options, function (err, upserted) {
if (err) throw err;
console.dir('Successfully upserted ' + upserted + ' document!');
return db.close();
});
The difference is that the upsert operator will update the document if it exist, otherwise it will create a new one. When using the upsert operator you should keep in mind that this operation can be underspecified. That means if your query does not contain enough information to identify a single document, a new document will be inserted.

Resources