F# 3 and Raven DB

Ok so I have blogged about these to before. Previously, F# didn’t have brilliant support for Linq. F# Expressions couldn’t `easily` be converted to the Linq expression trees that the RavenDB API required. This caused somewhat of a mis-match between the two which made Raven difficult but not impossible to use from F#. My previous blog introduced a library which is available for Raven clients prior to version 2.0, to bridge this gap, and tried to make Raven more natural to use from F#. However as of Raven 2.0 this library has been removed. The reasons are explained here. I don’t disagree with the reasons ayende cut the support
I wouldn’t want to support something I had little knowledge of either. However things have changed…. 🙂

The advent F# 3 and query expressions

So we are now in the era of F# 3.0 and things have changed somewhat. F# is now truly in the data era… Information Rich programming is an awesome feature of F# manifested in the
form of `Type Providers` and `Query Expressions`. If you haven’t read about or don’t know what type providers are then I encourage you to check them out here. Type providers are not really applicable for use with RavenDB see it is schemaless so for the rest of thispost we will focus on `Query Expressions`. It is this feature that means the gap between Linq and F# no longer exists. If you are familiar with

var result = (from x in xs do
	      where x.Published >= someDate
	      select x.Name).ToArray()

then the query expression syntax shouldn’t feel that different,

let result =
     query {
            for x in xs do
	        where (x.Published >= someDate)
	        select x.Name
	   } |> Seq.toArray

So What about RavenDB???

Using RavenDB from C# is well documented and things are not that different when using it from F#. The in’s and out’s are well known and lets face it the API is your safety net. It doesn’t let you kill yourself, in fact you have to try very hard to actually do anything really bad in RavenDB. This is I think the best feature of RavenDB.

So, what are the things that we need to be aware of when using RavenDB from F#? First things first, initializing the document store. This can be done pretty much the same as in C#

let store = new DocumentStore(Url = "http://localhost:8080")

and this is all well and good if we just use straight forward POCO objects. But what if we want to use F# record or Union types? We need to make a few simple changes.
Lets first consider F# record types, all we need to do here is declare the `Id` property as mutable.

type BlogPost = {
	mutable Id : string
	Body : string
	....//other members
}

Simple eh?, but what about Union types, Maps, F# lists? These are a little more complex as Json.NET doesn’t do the correct thing to serialize these out of the box. However Json.NET and the
internalised Raven counterpart does have an extension point and a UnionTypeConverter or MapTypeConverter as Json.NET implementations can be found here. To use this we need to modify our
document store setup a little to include the converter.

let store =
        let customiseSerialiser (s : JsonSerializer) =
            s.Converters.Add(new MapTypeConverter())
            s.Converters.Add(new UnionTypeConverter())

        let store = new DocumentStore(Url="http://localhost:8080")
        store.Conventions.CustomizeJsonSerializer <- (fun s -> (customiseSerialiser s))
        store.Initialize()

Querying raven

With the document store setup we can now start querying Raven. As with any Raven query we need to create a session from our document store, then we need to create the query.

let getPostsAsOf store asOfDate = 
    use session = store.OpenSession()
    query {
	for post in session.Query() do
	where (post.Published >= asOfDate)
	select post
    }

The above creates a query that is pending execution. To execute this we can run,

let posts = 
    getPostsAsOf store (DateTime.Now.AddDays(-2.).Date) 
    |> Seq.toArray

this will give us an array of BlogPosts published from 2 days ago. Notice we had to enumerate to an array for the query to actually be executed. This is the same execution semantics
as C#; and it is important to realise that there isn’t really any magic going on in the world of F#, it is still just a .NET lanuguage it still compiles to CIL and is fully
interoperable with any other .NET library.

Indexes

OK so things haven’t got much better here in terms of static indexes. Basically you still need to define them in C# and then you can extend the document initialization process by
including the assembly that contains the index definitions. However in Raven 2.0, dynamic indexes and promotion to permanent indexes have been massively improved, which reduces the need to create static indexes.

Advertisements
This entry was posted in Development and tagged , . Bookmark the permalink.

2 Responses to F# 3 and Raven DB

  1. Pingback: F# Weekly #21 2013 | Sergey Tihon's Blog

  2. Consultator says:

    Reblogged this on Disparate Opinions and commented:
    Wow, this was pretty interesting. I am definitely trying this right now. I didn’t realize F# was Raven hostile, and also this unintended benefit of TypeProviders need to be announced off of the roof-tops.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s