0

I want to make sure some database does not yet exist in mongodb but anytime I access db object an empty database is created.

Using node-mongodb-native driver:

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect("mongodb://localhost:27017/nonexistingdb", function(err, db) {
    db.eval('db.getMongo().getDBNames();',function(err, dbnames) {
        console.log(dbnames);
        db.close();
    });
});

+

$ mongo --eval "db.getMongo().getDBNames();"
MongoDB shell version: 2.4.9
connecting to: test
local

It does not act like that when using mongo shell:

$ cat > byshell.js
server = new Mongo();
db = server.getDB("nonexistentdb");
dbnames = server.getDBNames();
print(dbnames);

+

$ mongo --nodb byshell.js 
MongoDB shell version: 2.4.9
local

+

$ mongo --eval "db.getMongo().getDBNames();"
MongoDB shell version: 2.4.9
connecting to: test
local

What can I do to avoid that?

1 Answers1

0

Since calling MongoClient.connect with a database name is analogous to typing use dbname in the mongo CLI, such that the act of connecting will create the database if it does not exist, I'd imagine the only way to assure that a specific database didn't exist after connecting would be to call db.dropDatabase after connecting to it, but would really defeat the purpose of the connect call.

Update

After digging into the code, it seems that one of the last things MongoClient.connect does is to open the database named in its connection URI, which clearly has the side-effect of creating the database if it doesn't exist. (See line 371 or so in node_modules/mongodb/lib/mongodb/mongo_client.js)

So it's interesting to note that by using MongoClient.connect, you have no choice but to accept this behavior, since it requires that you include a dbname as part of the Mongo Connection String URI you must provide, which is counter to the official definition of such things.

So it would appear that if you don't wish to automagically create non-existent databases when connecting to Mongo, you shouldn't rely on the official mongodb.js driver and its MongoClient API.

You might try mongojs which wraps the mongodb.js driver with an API that supports more of a Mongo Shell metaphor, as in:

var util=require('util'),
    mongojs=require('mongojs'),
    connectionUriWithoutDb='localhost/', // *see note below.
    db=mongojs(connectionUriWithoutDb);

db.runCommand({ping:1},function(err,res){
    if(err) throw err;
    console.log('result: %s', util.inspect(res));
    db.close();
});

which prints to the console:

result: { ok: 1 }

and doesn't create a database.

  • Note that if you choose to connect this way, you must remember to end your Connection String URI with a slash to inform the underlying mongodb.js driver that you're specifying a hostname rather than a database name which happens to contain periods.

Without the slash, mongodb.js throws an exception (per validateDatabaseName at line 216 of node_modules/mongojs/node_modules/mongodb/lib/mongodb/db.js) since database names must not contain spaces, periods, dollar-signs, and either forward or backward slashes.

Oddly enough, this test is of the Array.prototype.indexOf variety on a list of those five characters, rather than using a RegExp which would have forbade the use of any character other than those allowed.

My next database name surely must contain several newlines, at least one bell, and a tab or two. ;)

Rob Raisch
  • 17,040
  • 4
  • 48
  • 58
  • Well `use dbname` does not leave it behind unless you do insert, update or other write operation. It is created when you use/connect to it but only for this session unless you write to it. I do realize that this is not uscase found to often but if they considered it in shell I'd expect it to be the same in api. – Green Hell Jan 29 '14 at 09:12