Why aren't these MongoDB document changes saved? - node.js

This code is intended to make changes in bulk to all the documents in a MongoDB collection. However there is no change at all to the documents in the collection after running this code. What is wrong with it?
var mongoose = require('mongoose'),
async = require('async'),
Person = require('../../model/Person');
mongoose.connect('mongodb://localhost/people-questions');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
Person.find(function (err, people) {
if (err) return console.error(err);
//download bio info
async.each(people, function(person, callback) {
person.birthdateYear = '01';
person.save();
callback();
});
mongoose.connection.close();
});
I have verified that there are no changes made by leaving a mongo cli instance open in Terminal and running db.people.find(); to see the field is not updated at all, and also queries such as db.people.find({ "_id" : ObjectId("5379e6e21fe1e8e2fc364d17")});, referencing specific IDs to verify that my Javascript code is indeed connected to the right database and is using the right collection (that ID came from a previous script using identical connection details to print out document IDs).
Also, I am using Mongoose. The Mongoose Schema was updated to include extra fields like birthdateYear after the original documents were created, but from the googling and Mongo Docs reading that I've done already it appears as though Schema changes shouldn't require any special work - you can set attributes against documents with the updated schema right away (should be able to anyway).

The reason the updates are not persisted is that the connection to MongoDB is closed before the save() callbacks have a chance to complete. By ensuring all the save() callbacks complete before closing the connection, the data is saved.

person.save is an async function
try something like
person.save (function(err){
if(err) console.log(err);
callback();
});

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

Why mongoose opens two connections?

It's a simple file from mongoose quick guide
mongoose.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/Chat');
var userSchema = mongoose.Schema({
name: String
});
var User = mongoose.model('User', userSchema);
var user = new User({name: 'Andy'});
user.save(); // if i comment it mongoose will keep one connection
User.find({}, function(err, data) { console.log(data); }); // the same if i comment it
I tried to use db.once method, but effect the same.
Why mongoose opens the second connection in this case?
Mongoose uses native mongo driver underneath, and it in turn uses connection pooling - I believe the default is 5 connections (Check here).
So your mongoose connection will use up to 5 simultaneous connections when it has simultaneous requests.
And since both user.save and User.find are asynchronous, those will be done simultaneously. So what your "program" tells node:
1. Ok, you need to shoot a `save` request for this user.
2. Also, you need to fire this `find` request.
The node runtime then reads these, runs through the whole of your function (until a return). Then it looks at it's notes:
I was supposed to call this save
I also need to call this find
Hey, mongo native driver (which is written in C++) - here are two tasks for you!
and then the mongo driver fires the first request. And it sees it is allowed to open more connections then one, so it does, and fires the second request too, without waiting for the first to finish.
If you called the find within a callback to save, it would be sequential, and the driver would probably reuse the connection it already had.
Example:
// open the first connection
user.save(function(err) {
if (err) {
console.log('I always do this super boring error check:', err);
return;
}
// Now that the first request is done, we fire the second one, and
// we probably end up reusing the connection.
User.find(/*...*/);
});
Or similar with promises:
user.save().exec().then(function(){
return User.find(query);
})
.then(function(users) {
console.log(users);
})
.catch(function(err) {
// if either fails, the error ends up here.
console.log(err);
});
By the way, you can tell mongoose to use only one connection if you need to, for some reason:
let connection = mongoose.createConnection(dbUrl, {server: {poolSize: 1}});
That would be the gist of it.
Read more on MongoLab blog and Mongoose website.

MongoDB created collection shows in NodeJS but not in CLI?

I am trying to create a capped collection in MongoDB using NodeJS driver.
db.createCollection(req.body.name,options,function onCreateCollection(mongoErr,mongoCollection){
if(mongoErr){
...
}else{
console.log( mongoCollection.collectionName );
...
}
});
The collection name prints on the console but show collections does not list it. I tried a hyphenated name this-is-a-collection.
Why is that?
Also, what are the limitations in naming a collection?
I don't know why your code doesn't work. But I just tried to create a collection with the hyphenated name this-is-a-collection with this simple script, it worked.
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/db';
MongoClient.connect(url, function(err, db) {
console.log("Connected correctly to server");
db.createCollection('this-is-a-collection', { capped : true, size : 10000 } ,function onCreateCollection(err,mongoCollection){
if(err){
console.log(err);
} else {
console.log(mongoCollection.collectionName);
}
db.close();
});
});
And in the CLI :
MBP:mongo sapher$ mongo
MongoDB shell version: 3.0.5
connecting to: test
....
> use db
switched to db db
> show collections
system.indexes
this-is-a-collection
You can follow this link to get more info on MongoDB naming restrictions.
For naming convention, I personnaly use snake case like remote_users. I think this is the most elegant way to name a collection. Naming isn't that important as long as you stay consistent.
As it turns out, on older version of the driver 1.4.x, creating a capped collection without specifying the size option doesn't result in an error. It even returns a success response. On the newer version, 2.0.x, it does result in an error.
For a capped collection, size is needed while max is optional. The docs are slightly ambiguous as they do not state that you need a size to create a capped collection.

`TypeError: pool.getAll is not a function` when connecting to MongoDB

I am writing an API with Node and Express, and use MongoDB as the database.
It has worked for a long time now, but today when I wrote some changes to a model, the server won't start anymore. I originally thought that a recent code change caused it, but even if I stash my changes and reset to a working state, the error occurs.
This is the error:
TypeError: pool.getAll is not a function
at MongoCR.auth (/location/of/project/node_modules/mongodb/node_modules/mongodb-core/lib/auth/mongocr.js:56:26)
at Server.auth (/location/of/project/node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:1019:40)
at ReplSet.auth (/location/of/project/node_modules/mongodb/node_modules/mongodb-core/lib/topologies/replset.js:572:17)
at ReplSet.auth (/location/of/project/node_modules/mongodb/lib/replset.js:438:23)
at authenticate (/location/of/project/node_modules/mongodb/lib/db.js:1319:21)
at Db.authenticate (/location/of/project/node_modules/mongodb/lib/db.js:1356:44)
at /location/of/project/node_modules/mongodb/lib/mongo_client.js:414:25
at /location/of/project/node_modules/mongodb/lib/db.js:221:5
at connectHandler (/location/of/project/node_modules/mongodb/lib/replset.js:335:7)
at g (events.js:260:16)
If I comment out all database connections the app runs. I've tried changing database, but it does not work either. I found this and this question and answer, and double checked versions and that all db-calls have callback-methods. I've used the last argument as the callback for calls that affect one entry, and toArray(function(err, result){}) when there are multiple entries returned.
Mongo version is 2.6.3, and I use the Node-mongodb driver.
I connect with
var mongo = require('mongodb').MongoClient;
var url = process.env.MONGODB || 'mongodb://localhost:27017/test';
var myCollection;
mongo.connect(url, function(err, db) {
if(err) console.log(err);
myCollection = db.collection('myCollection');
});
Then I have methods for e.g. find:
myCollection.find({}).toArray(function(err, result){
// work with result
});
I'm lost - thanks in advance.

Update not working-NodeJs and MongoDB using MongoClient

I was going through the mongodb and nodejs course on MongoDBUniversity and one of the task involves finding the documents which has the highest recorded temperature for any state and then add a field "month_high" to it.I am able to find the documents for the state with the highest temperature but am unable to update it. The code is as below.
Can someone tell me what might I be doing wrong?
var MongoClient=require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/course',function(err,db){
var cursor=db.collection("weather").find();
cursor.sort({"State":1,"Temperature":-1});
var oldState,newState;
cursor.each(function(err,doc){
if(err)throw err;
if(doc==null){
return db.close();
}
newState=doc.State;
if(newState!=oldState){
var operator={'$set':{"month_high":true}};
var query={"_id":doc._id};
console.log(doc._id+" has temp "+doc.Temperature+" "+doc.State);
db.collection("weather").update(doc,operator,function(err,updated){
console.log("hi");//---->Never Logs
if(err)throw err;
// console.log(JSON.stringify(updated));
})
}
oldState=newState;
});
});
I'm not 100% sure, but given the syntax reported on the docs you might have to specify the options parameter even if not using it:
db.collection("weather").update(doc,operator, options, function(err,updated)
Also, the connection might get closed before the callbacks are called. Does it change anything if you remove the db.close() call?
Collection name is 'data'. In this homework 'weather' is database name.
See
https://education.mongodb.com/courses/10gen/M101JS/2013_October/courseware/CRUD/Homework_2.2/
> use weather
switched to db weather
> db.data.findOne()

Resources