node-mongolian icon indicating copy to clipboard operation
node-mongolian copied to clipboard

automatic collection initializing [enhancement]

Open ippa opened this issue 13 years ago • 9 comments

Hey, great lib! Been searching for exaclty this... looked through tons of mongo node libs. It just makes sense mimicking the shell, why learn 2 different syntaxes?

Anyhow, had a suggestion, couldn't this code:

var db = server.db("awesome_blog")

var posts = db.collection("posts")

var comments = db.collection("comments")

Be replaced with just: var db = server.db("awesome_blog")

... and the collections are automatically detected / initialized, basically that the following would happen behind the scenes:

db.posts = db.collection("posts")

db.comments = db.collection("comments")

... then we access the finders etc with db.posts.find() .. just as in the shell. Wouldn't this mimick the shell even more?

ippa avatar Apr 01 '11 21:04 ippa

The problem with this approach is that V8 doesn't support Proxies, so there's no way to dynamically make db.posts act like db.collection("posts").

While I could get a list of collections on the server and automatically make collections for them, that won't let you create new ones, and it would require you to have an asynchronous callback.

I did a little exploring into the possibility of making server and db functions rather than objects, so you can do server("db")("collections"), but I'm worried that's too clever.

marcello3d avatar Apr 01 '11 22:04 marcello3d

So in summary. I agree that would be great, but I don't know how to do it.

marcello3d avatar Apr 02 '11 17:04 marcello3d

A super simple:

var db = server.db("pixelholm")
db.screens = db.collection("screens")

works all good here, but I imagine the problem is a bit more complex on your side.

ippa avatar Apr 03 '11 23:04 ippa

While I don't want to make mongolian deadbeef dependent on native code (nor do I really want two different ways of doing the same thing), this could probably be implemented with Proxies: https://github.com/samshull/node-proxy

marcello3d avatar Apr 17 '11 15:04 marcello3d

The only reason I suggested this is cause node-mongolian does seem to have a goal to be as close to the mongoconsole as possible.

And in the mongoshell I do this:

db.screens.find();

I don't do:

db.collection("screens").find()

Other then that it doesn't matter much to me :)

ippa avatar Apr 17 '11 16:04 ippa

Agreed. It'd be nice, but unfortunately impossible without changing how node works. :-(

marcello3d avatar Apr 17 '11 16:04 marcello3d

I wrote a small patch, which semi-accomplishes this, however you need to pass the collection names to the db constructor. ex : db = new (require('mongolian'))().db('test-db', ['session', 'cache'])

The patch :


diff --git a/lib/db.js b/lib/db.js
index 2502d90..5fce804 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -6,11 +6,25 @@ var safetyNet = require('./util').safetyNet,
     MongolianCollection = require('./collection'),
     MongolianGridFS = require('./gridfs')

-var MongolianDB = module.exports = function(server, name) {
+var MongolianDB = module.exports = function(server, name, collections) {
     this.server = server
     this.name = name
     this._collections = {}
     this._gridfss = {}
+    if(collections){
+        for(var i in collections) {
+            var n = collections[i];
+            console.log(n, n in this);
+            if(!this[n]){ //so we wouldn't accidently delete a function or something
+                this.__defineGetter__(n, function() {
+                    return this.collection(n);
+                });
+            } else {
+                server.warn('The collection "' + n + '" couldn\'t be set as a direct getter.');
+            }
+
+        }
+    }
 }

 /**
diff --git a/lib/server.js b/lib/server.js
index 0efd88e..cfef952 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -164,9 +164,9 @@ Mongolian.prototype.dbNames = function(callback) {
 /**
  * Get a database
  */
-Mongolian.prototype.db = function(name) {
+Mongolian.prototype.db = function(name, collections) {
     return this._dbs[name] ||
-          (this._dbs[name] = new MongolianDB(this, name))
+          (this._dbs[name] = new MongolianDB(this, name, collections))
 }

 Mongolian.prototype.toString = function() {

OneOfOne avatar Sep 26 '11 12:09 OneOfOne

That's needlessly complex. If you want to use db.collectionName just do something like:

var db = server.db("database");
['session', 'cache'].forEach(function(n){ db[n]=db[n]||db.collection(n); });

In any event I don't think this is functionality that could make its way into mongolian.

awwright avatar Dec 01 '12 01:12 awwright

You could support this now that node/v8 support Proxies via --harmony. Just detect if the Proxy object is available and use it

tarqd avatar Jul 16 '13 13:07 tarqd