Node.js and MongoDB using Mongoose. Using findByIdAndUpdate vs Manual - node.js

are there any drawbacks to using findByIdAndUpdate and doing it manually. I noticed that findByIdAndUpdate drops my mongo connection, and read that you should try to keep connection open, only close when you close your app. Is this the case, and if so, is there a config setting that I am not seeing for findByIdAndUpdate, that keep the connection on?
updateItemById: function(id, updateObj, options, callback){
//OPTION 1
Badge.findById(id, null , function(err, doc){
doc.update(updateObj, function(err, numberAffected, raw){
if (err) return handleError(err);
Badge.findById(id, null , function(err, doc){
callback(doc);
});
});
});
//OPTION 2
Badge.findByIdAndUpdate(id, updateObj, options, function(err, data){
callback(doc);
});
}

findByIdAndUpdate should be faster (as long as the driver and mongoose are correctly programmed), because:
With Option 1:
Fetch the object by ID
Transform it into JavaScript object
Update object in client
Send back to DB
Calculate and save changes
Send it back
Transform into JavaScript object
With Option 2:
Find document in Database
Calculate and apply changes as atomic operation
Send object back
Transform into JavaScript object
As you can see, the second options does require less steps and therefore should be faster.
Bonus: The code is more readable.

Related

Where need it call dropCollection using nodejs with mongodb?

I was doing a server using nodejs, it need get data from mongodb. I retrieve data after require(../db.js). Somebody said the mongodb needn't be close in nodejs,because nodejs is a single process.....
My question: Need I call dropCollection to close the collection after invoked the db function many times;and How to do?Where to do that? Please,Thanks.
You dont need to drop the collection after invoking db functions,simply call db.close() though it is not needed. But if you want to do it , you can do it as follows:
var dropRestaurants = function(db, callback) {
db.collection('restaurants').drop( function(err, response) {
console.log(response)
callback();
});
};

Saving reference to a mongoose document, after findOneAndUpdate

I feel like I'm encountering something completely simple, yet can not figure it out, will be glad, if you can help me.
I'm using mongoose + socket.io as CRUD between client and server. As I'm using sockets, there is a private scope individual for each client's socket, in which, for future use without making db find calls, I would like to store a reference of mongoose document, that I once found for this user.
One client is creanting a Room:
var currentroom;
client.on('roomcreate', function (data) {
currentroom = new Room({
Roomid: id,
UsersMeta: [UserMeta],
///other stuff///
})
currentroom.save(function (err, room) {
if (err) console.log(err);
else console.log('success');
});
});
Then, whenewer I want, on another creator's call I can just simply
currentroom.Roomnaid = data;
curretroom.save()
And it's working fine, the problem is - I do not understand how I can get the same reference on not creating, but Room search, for the moment i'm using this for search:
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);
})
The thing is, that in one call I want to:
1: find a doc in db,
3: send it to user (in pre-updated state),
4: update found document,
2: save a reference (of the current updated doc)
With findOneAndUpdate I can do all, but not saving a current reference.
So, how I need to approach it then?
Like this;
Room.findOne({ Roomid: roomid }, function (err, oldRoom) {
//make changes to oldRoom
//then save it like this
oldRoom.save(function(err,newRoom) {
//newRoom is updated document
//now you have reference to both old and new docs
});
})
In the end of the road i found out that i was trying to make it wrong. The idea of storing reference (instance) of doc, accessed by different users is obviously bad, as it leads to data conflicts between those instances. Also, approach with separate find and save can cause racing conditions and conflics as being non atomic operation, its far better to use findOneAnd*** to make mongoose\mongoDB handle db requests querieng by itself and make sure that no conflicts will occure.

mongodb async issue NodeJS

I'm using mongodb for a while and had countered this same issue many times.. like so:
XCollection.find({})
.each(function (err, x) {
if (err) throw err;
branchCollection.findOne(
{_id: new ObjectID(x.branchId)}
, function(err, doc){
console.log(x.branchId);
});
.....
and I see sometimes that findOne not working very well, x document changes because of the upper each, and that's affecting my code! I recognize that the problem is because those requests (db requests) is async. but what the recommended method to deal with this issue?
Thanks,
Best Regards
You do not need to use new ObjectID to query the ID field. A string will suffice.
branchCollection.findOne(
{_id: x.branchId}
, function(err, doc){
console.log(doc._id);
});
On another note, you should not be using the x variable in your async call. You should use:
console.log(doc._id)
Other than that, I'm not sure I understand what your question is? Are you receiving an error?

how insert csv data to mongodb with nodejs

Hi im developing an app with nodeJS, express and a mongoDB, i need to take users data from a csv file and upload it to my database this db has a schema designed with mongoose.
but i don know how to do this, what is the best approach to read the csv file check for duplicates against the db and if the user (one column in the csv) is not here insert it?
are there some module to do this? or i need to build it from scratch? im pretty new to nodeJS
i need a few advices here
Thanks
this app have an angular frontend so the user can upload the file, maybe i should read the csv in the front end and transform it into an array for node, then insert it?
Use one of the several node.js csv libraries like this one, and then you can probably just run an upsert on the user name.
An upsert is an update query with the upsert flag set to true: {upsert: true}. This will insert a new record only if the search returns zero results. So you query may look something like this:
db.collection.update({username: userName}, newDocumentObj, {upsert: true})
Where userName is the current username you're working with and newDocumentObj is the json document that may need to be inserted.
However, if the query does return a result, it performs an update on those records.
EDIT:
I've decided that an upsert is not appropriate for this but I'm going to leave the description.
You're probably going to need to do two queries here, a find and a conditional insert. For this find query I'd use the toArray() function (instead of a stream) since you are expecting 0 or 1 results. Check if you got a result on the username and if not insert the data.
Read about node's mongodb library here.
EDIT in response to your comment:
It looks like you're reading data from a local csv file, so you should be able to structure you program like:
function connect(callback) {
connStr = 'mongodb://' + host + ':' + port + '/' + schema; //command line args, may or may not be needed, hard code if not I guess
MongoClient.connect(connStr, function(err, db) {
if(err) {
callback(err, null);
} else {
colObj = db.collection(collection); //command line arg, hard code if not needed
callback(null, colObj);
}
});
}
connect(function(err, colObj) {
if(err) {
console.log('Error:', err.stack);
process.exit(0);
} else {
console.log('Connected');
doWork(colObj, function(err) {
if(err) {
console.log(err.stack);
process.exit(0);
}
});
}
});
function doWork(colObj, callback) {
csv().from('/path/to/file.csv').on('data', function(data) {
//mongo query(colObj.find) for data.username or however the data is structured
//inside callback for colObj.find, check for results, if no results insert data with colObj.insert, callback for doWork inside callback for insert or else of find query check
});
}

MongoDB on Node.js doesn't work, it returns undefined

In the following code:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/db_name', function(err, db){
if (err) throw err;
var collection = db.collection('col_name');
console.log(collection.find().toArray(function(err, items){}));
});
When I run the above, it doesn't return any results and instead returns undefined. What am I missing?
Also, in order to confirm there exist some collections on the db, which there are, I tried to add console.log(db.getCollectionNames());, but it looks like it has no such method in Node.js driver. So is it still possible to confirm the existence of collections? (Anyway I just want to use it as debug in these situations - usually I don't need the method though).
Thanks.
Don't log your entire find() function, do the checking in the callback:
collection.find().toArray(function(err, items){
console.log(items);
});
For the getCollectionNames() part, the method is actually called collectionNames() in the mongodb native driver :
db.collectionNames(function (err, list) {console.log(list)});

Resources