Presenting Mondocks

Angel Daniel Munoz Gonzalez - Nov 29 '20 - - Dev Community

I'm a person that tries to ease other people's lives, if not at least my own. One of the things I found hard to do when I started moving to F# was the "lack of MongoDB support" which is up to some point is false, MongoDB provides it's own Driver which for all intends and purposes it's focused in C#'s OOP style it is quite similar to an ODM (Object Document Mapper) and while it's use is quite idiomatic for C#, using it from F# sometimes can be quite clunky, what I wanted when I was learning was to focus on learning F# and not focus on database schemas, or how to make the driver work in a foreign language... sadly there was not a lot I could do for it, so I moved on to SQL solutions like Zaid's Npgsql.FSharp library which is an amazing piece of tech if you include the Npgsql.FSharp.Analyzers 100% recommended. Today I finally feel able to contribute back something that can be useful for those node developers who are looking to learn F# next

GitHub logo AngelMunoz / Mondocks

An alternative way to interact with MongoDB databases from F# that allows you to use mongo-idiomatic constructs

Mondocks

nuget Binder

dotnet add package Mondocks.Net
# or for fable/nodejs
dotnet add package Mondocks.Fable

This library is based on the mongodb extended json spec and mongodb manual reference

https://docs.mongodb.com/manual/reference/mongodb-extended-json/ > https://docs.mongodb.com/manual/reference/command/

This library provides a set of familiar tools if you work with mongo databases and can be a step into more F# goodies, it doesn't prevent you from using the usual MongoDB/.NET driver so you can use them side by side. It also can help you if you have a lot of flexible data inside your database as oposed to the usual strict schemas that F#/C# are used to from SQL tools, this provides a DSL that allow you to create MongoDB Commands (raw queries) leveraging the dynamism of anonymous records since they behave almost like javascript objects Writing commands should be almost painless these commands produce a JSON string that can be utilized directly on your application or even…

Mondocks is a Mongo Command builder library (like a SQL builder library but for MongoDB) which focuses on producing JSON that is compatible with MongoDB's Extended Json Spec, it provides a set of helpers called Computation Expressions that create a Domain Specific Language that you can use to keep using the queries and objects that you may know how to handle already.
But enough text, let's see some code (don't forget to check the samples as well).

Installing this library is quite simple
dotnet install Mondocks

NOTE: you can run that with F# Interactive, download the file with the name find.fsx and run dotnet fsi ./find.fsx
NOTE: you also need to use the MongoDB.Driver library to execute these commands since Mondocks only produces JSON

  new MongoClient(URL)
        .GetDatabase(dbname)
        .RunCommand(JsonCommand(mycommand))

Which also means you can use it side by side with the usual MongoDB.Driver's API so it's a win-win you're not sacrificing anything 😁

In the sample above we're leveraging anonymous records from F# to create MongoDB queries since they behave pretty much like Javascript Objects we can even create new definitions from existing anonymous records similar to Object Spread in javascript (check filterbyNameAndId).

Let's move up to the update, updates are quite simple as well

NOTE: there are certain BSON types that have to be represented in some specific ways to conform to the MongoDB JSON extended spec in this example you can see

{|``$date``: .... |}

for more info check here

I think that shows a little bit of how this library works and what you can expect from it.

You can check the samples to see how you can do things like count, distinct, delete, find, index creation, findAndModify, etc, etc. and also here's a small F# Restful API which uses this library

Frest

This is a sample API built with Falco, it uses mongodb as the database via Mondocks

Routes

let endpoints =
    [ post Urls.``/auth/login`` Value.Controller.login
      post Urls.``/auth/signup`` Value.Controller.signup
      get Urls.``/api/me`` Value.Controller.me
      get Urls.``/api/places`` Value.Controller.getPlaces
      post Urls.``/api/places`` Value.Controller.addPlaces
      put Urls.``/api/places/id`` Value.Controller.updatePlaces
      delete Urls.``/api/places/id`` Value.Controller.deletePlaces ]
Enter fullscreen mode Exit fullscreen mode

Organization

While names are almost meaningless to me I followed the Falco templates's rest default structure with a slight change of names.

  • Domain

    includes most of the base types there is to work with

  • Provider

    includes database access

  • Common

    utility functions that can be used accross models/controllers

  • Value

    Includes models and controllers along with its behaviors

  • Program

    definition of routes and the server's configuration

Basically as the nature of F# this is a top-down project which includes a Restful API with some protected routes…

If you know a MEAN Stack developer who could use a new language like F# I encourage you to show this library to them, perhaps that sparks interest. If you tried mongo in F# before but you didn't like it perhaps this is the time to give it a check again.

If you find a bug or have suggestions, feel free to raise a couple of issues or ping me on Twitter.

As always I hope you're having a great day and feel free to drop some comments below

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .