Sunday, April 3, 2011

Exploring MongoHQ with F#

Recently, I've been working on a Silverlight 4 project which will hopefully go live soon.
This project started off nice and light as all green field projects do, and then the unavoidable requirement came up... storage. A few customers utter'd access. After I finished  laughing I thought to myself- maybe SQL?
So I turned to my data structure and immediately realized that its not structured for SQL. I've played around with a few object databases... db4o, ravendb, etc. Then I remembered Mongodb, over the past several years this object database has received quite a bit of attention. I must admit I haven't paid much attention to it, so I decided to give it a world. Headed over to the spot, read through some of the docs and realized I need essentially two dll's.
1) MongoDB.Bson.dll
2) MongoDB.Driver.dll

So I downloaded it and ran through the introduction tutorial.
After I got the Mongod server up and running on my local box I was able to store and retrieve some mock data (using the mongo client) with ease.  Now it was finally time to write some code and see it in action.
So, I fired up FSI and produced the simple F# script.

#I @"D:\ODev Solutions\MongoDb\CSharpDriver"
#r "MongoDB.Bson.dll"
#r "MongoDB.Driver"

open MongoDB.Bson
open MongoDB.Bson.Serialization
open MongoDB.Driver
open MongoDB.Bson.IO

// helper func insert name_value in Bson document
let Bson_NameValue (name,value) =
 new BsonElement(name,BsonValue.Create value)

// helper func get all keys in a Bson document
let getkeys (document: BsonDocument) =

(* Connect to Mongo Server *)
let connectionString = "mongodb://localhost"
let server = MongoServer.Create connectionString

(* Get Database - if it does not exists then one is created. *)
let test = server.GetDatabase "test"

(* Store usernames and passwords *)
let profilescollection = test.GetCollection "mockprofiles"

(* Create the mock structure that will store a single user profile *)
type profile = {UserName : string; Password : string; }
let p = { UserName = ""; Password = "password"; }

let convert_profile_to_BsonDocument (p: profile) =
     let d = new BsonDocument()
    d.Add(Bson_NameValue("UserName",p.UserName)) |> ignore
    d.Add(Bson_NameValue("Password",p.Password)) |> ignore
let profilebson = convert_profile_to_BsonDocument p

(* Insert the mock profile into the newly created profiles collection *)
profilescollection.Insert profilebson

*Retrieve mock profile*

(* Mongodb Query Document - can think of it as a where clause *)
let qd = new QueryDocument(Bson_NameValue("UserName",""))

let mockprofile = profilescollection.FindOne(qd)
printf  "UserName: %s   Password: %s" mockprofile.UserName mockprofile.Password

Okay, all good right? Wait... if I'm going to use this as production solution how do I even go about deploying something like Mongodb? Do I look for a hosting account that knows about monogo? Do I look for a hosting account that will give me full access to the box so that I can run mongo and manage it myself? After some searching around I found MongoHQ.

The guys over at monogohq make it super simple to setup a production object database.
They charge monthly or annually based on the disk space you use. Starting at free accounts up to 16mb and then progressively goes up from there. I like this solution a lot because I don't have to think about the maintenance and they provide an admin portal so I can manage the database and get reports from their web interface. As for the code changes there was only one. the connection string. =)

example: mongodb://

If you're considering a project with an object database check out Mongodb and MongoHQ.
Really slick!


  1. Do you actually have the MongoDB drivers working in Silverlight?

    I was using NoRM (another .net Mongo driver) and I ended up having a wcf back-end because NoRM can't be compiled in SL.

  2. Do you actually have the MongoDB drivers working within Silverlight?

    I am using NoRM (another .net Mongo driver) and ended up creating a WCF back-end because I was unable to use the driver in Silverlight (TcpClient issues for starters...)

  3. Eric, I do have a very simple F# WCF service which uses code similar to the code above in my production silverlight app. The code above can also be used in FSI (fsharp interactive). Which is really nice for exploring the mongo api. When I get the code exactly how I want it in FSI then I can easily move it to a WCF service for live interaction. =)