I decided to take the opportunity offered by Jacek Laskowski (in Polish) and take a closer look at interaction with MongoDB in Clojure. It has a nice, challenging learning curve as I haven’t done much practical work in Clojure and I’ve never actually dealt with Mongo before. Double win – learning two interesting things at a time.
The obvious choice for the integration is CongoMongo. It’s really easy to get it all set up and working. The official docs encourage you to simply do this:
(def conn (make-connection "mydb") (set-connection! conn) (insert! :robots {:name "robby"}) (fetch-one :robots) ; ... and so on
Easy. Too easy and comfortable. Coming from the old good and heavy JDBC/SQL I felt uneasy with the connection management. How does it work? Does it just open a connection and leave it dangling in the air the whole time? Might be good for a quick spike in REPL, but not for a real application which needs concurrency, is supposed to be running for days and weeks, and so on. How do you maintain it properly?
clojure.contrib.sql
has with-connection
. That opens the connection, runs something with it and then eventually closes it. CongoMongo has with-mongo
, but all it does is bind the argument to *mongo-config*
and execute body. Nothing is ever opened or closed.
That seemed insane and broken, until I took a step back and compared source of CongoMongo to documentation of underlying Java driver for MongoDB. The light dawned.
What make-connection
really does is create an instance of Mongo
and DB
(if database name was provided). The result of this function is plain map: {:mongo #<Mongo>, :db #<DB>}
.
Javadoc for Mongo
say it’s a database connection with internal pooling. For most application, you should have 1 Mongo instance for the entire JVM. A page dedicated to Java Driver Concurrency explains it in more detail: The Mongo object maintains an internal pool of connections to the database. For every request to the DB (find, insert, etc) the java thread will obtain a connection from the pool, execute the operation, and release the connection..
At first I thought CongoMongo docs were misleading. The truth is, it’s just a wrapper for the Java driver. It’s fair for it to assume you know the basic principles of the underlying driver.
So what is called a “connection” here (the Mongo
class) is in fact a much more sophisticated object. It maintains a connection pool and creates nice little DB
objects for all the data handling, which in turn are smart enough to maintain the actual low-level connections for you. No ceremony, just gets out of the way as quickly as possible and lets you get the job done.
This is amazingly simple and elegant compared to JDBC / JEE / SQL. I guess I soon will be scratching my head over ACID, but at the moment I’m pleasantly surprised with the look of things.
Yeah! I like MongoDB I used in in couple of project which I work in. Clojure is in my interest right now. Now I can merge pleasant (MondoDB) with useful (Clojure) thanks to CongoMongo. CongoMongo what a nice name! I can’t wait when I say to my teammates: “Lets do some CongoMongo!”. :)