node-mongolian
node-mongolian copied to clipboard
automatic collection initializing [enhancement]
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?
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.
So in summary. I agree that would be great, but I don't know how to do it.
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.
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
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 :)
Agreed. It'd be nice, but unfortunately impossible without changing how node works. :-(
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() {
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.
You could support this now that node/v8 support Proxies via --harmony
. Just detect if the Proxy object is available and use it