How to save a modified object in mongodb using Node.JS Driver - node.js

I want to find, modify and afterwards save an object in MongoDB. It looks like that:
var message = req.body;
db.collection('user', function(err, collection) {
collection.findOne({'facebook_id':req.params.facebook_id}, function(err, item) {
if(item) {
item.messages.push({'value': message.value, 'date': message.date});
//save Object
}
});
});
How can I now save the changes I made to the database?
Or should I instead use .update()? The problem here is, that I don't want to swap the whole object, but much more insert something into an array of that object.
Thanks & Best,
Marc

collection.update({'facebook_id':req.params.facebook_id},
{$push: { messages: {'value': message.value, 'date': message.date} } }, function(err) {
});
Use the $push operator to add a value to an array directly in the database.
http://docs.mongodb.org/manual/reference/operator/update/push/
Note that this is much more efficient than updating the entire object, especially for large objects.

db.collection.update ({'facebook_id':req.params.facebook_id}, item, function (err) {
if (err) return next (err);
});

Related

Express / MongoDb find all objects by ID and save them to an array

My monongodb schema looks like this:
let statSchema = new mongoose.Schema({
title: String,
statId: String,
stats: {
likeCount: Number,
commentCount: Number
}
});
let MyStat = mongoose.model("MyStat", statSchema);
I am looking for a way where I can get all the statId elements from the database and put them in an array.
Later on I want to go through that array with request (npm request) that will take the statId and request JSON from API that will update all stats(likeCount and commentCount) for each corresponding statId.
If I use this code below:
MyStat.find({}, function(err, foundStats){
if (err) throw err;
console.log(foundStats);
});
it will log all the elements in my database but I don't know how to access just 'statId'.
I was trying to use console.log(foundStats.linkId);but it returns undefined.
foundStats is an array you need to loop in them.
foundStats.forEach((element) => {
console.log(element.statId);
});
if you want to return the statId only use it like this:
MyStat.find({}, 'statId' , function(err, foundStats){
if (err) throw err;
console.log(foundStats);
});
see the docs here
Your statId is stored as '_id'. So If you do not explicitly change or set id field, the object id field will be found in '_id'.
In this case, you might use
MyStat.find({}, '_id', function(err, foundStats){
if (err) throw err;
console.log(foundStats);
});
In the 'foundStats' you will find all the id of the stats.
For more check the mongoose, mongoDB

MongoDB $push operator not working as expected in Node

So I have a fairly simple piece of code as follows
db.get().collection('bars').insert({
barID: req.body.button,
}, {
$push: {
usersfbID: req.body.profileUser[0].facebookID
}
}, function(err, doc) {
if (err) {
throw err;
}
if (doc) {
console.log('Had to create a new document for this bar');
console.log(doc);
//callback(null, doc);
}
});
So, I'm just checking to see if a document for a bar exists, and if it doesn't then I create that document. And I want to insert an array for the usersfbID field so that I can store all the users going to the bar.
However, when I run the code, I don't get an error and it says the document has inserted but when the document logs, it doesn't have the userfbID field.
So what am I doing wrong? Does the $push operator only work with the update method of db? If so, how do I insert an array for that field?
Yes, it does work with the update methods
Reference > Operators > Update Operators > Array Update Operators > $push
Inserting a new entry means feeding the fields. In that case, there's no $push operation, since the array of the entry is freshly created and can be explicitly set (usersfbID:[req.body.profileUser[0].facebookID], meaning that you expect several fbId for that bar). Updating an array in an element of a collection isn't an insertion, it's an update.
So, just to provide an answer to the question I was facing..
Yes, you can only use $push or $addToSet with an update operation on a mongoDB document
Here is the way I implemented the code.
db.get().collection('bars').update({
barID: req.body.button,
}, {
$addToSet: {
usersfbID: req.body.profileUser[0].facebookID,
usersDocID: req.body.profileUser[0]._id
}
}, {
upsert: true
}, function(err, doc) {
if (err) {
console.log('There is an error here');
throw err;
}
if (doc) {
console.log('Had to create a new document for this bar');
callback(null, doc);
}
});
The upsert: true makes sure to insert a new document if the update method couldn't find the specified document.

Mongoose Updating Certain Fields of a Document

I'm trying to implement an update method for our API and I'm kinda new to the Node so I didn't know what would be the best practice to carry out the task of updating some fields of a document. Let me elaborate, we have a user model which keeps basic info of a user like name, age, sex, school, bio, birthday etc. Our update method should work as this, the request of the method includes the new values of the fields provided such as {bio:'newBio'} or {school:'newSchool', name:'newName'} I must update the provided fields with the provided data and leave the rest as they are. I was wondering what the best approach to the problem at hand would be. Thanks in advance
The easiest approach what i can think of is to use $Set to perform the update operations.
an example would be :
var updatedUsers= function(db, callback) {
db.collection('users').updateMany(
{ "_id": "value"},
{
$set: { bio: "new bio" }
}
,
function(err, results) {
console.log(results);
callback();
});
};
and invoke your above function as :
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
updatedUsers(db, function() {
db.close();
});
});

How do I update a doc in Cloudant using Cloudant Node.js

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

MongoDB two same records

I'm doing a project which is backed by Nodejs and MongoDB. I am quite new to MongoDB and I am lacking a clue why I quite often(almost always) get two same records in collections when I do posts. The two records only differ by ID, which are for example ObjectId("53aefb0fc68a0810504d2066") and 53aefb0fc68a0810504d2066, is this normal or am I doing something wrong? Thanks for any pointers.
Here is some node code:
server.js:
app.post("/:collection", function (req, res) {
var object = req.body;
var collection = req.params.collection;
collectionDriver.save(collection, object, function (err, docs) {
if (err) {
res.send(400, [err, object]);
} else {
res.send(201, docs);
}
});
});
collectionDriver:
save: function(collectionName, obj, callback) {
this.getCollection(collectionName, function(error, the_collection) {
if( error ) callback(error);
else {
obj.created_at = new Date();
the_collection.insert(obj, function() {
callback(null, obj);
});
}
});
},
getCollection: function(collectionName, callback) {
this.db.collection(collectionName, function(error, data) {
if (error) {
callback(error);
} else {
callback(null, data);
}
});
},
Everytime you ask MongoDB to save an object without an _id field, it automatically generates a new, globally unique ObjectID for that field and saves the object under that ObjectID.
When you want to use save to update an existing document, you need to make sure that the _id field is populated with the _id of the document you want to update.
Alternatively, you can create an unique index on those fields you consider relevant for determining what's a duplicate and what isn't. However, in that case an attempt to save an already existing document will throw an error instead of replacing the document.

Resources