Faceted search with MongoDB and KnockoutJS
Almost two years ago I took my first look at MongoDB as my first exploration into the NoSQL. Today I still find it to be one of the most interesting NoSQL tools – rivaled mainly by RavenDB, for most what I would call common scenarios. Recently I finally had the chance to use MongoDB in a real project, when we were talking over our options for doing faceted search, where the main design criteria was speed.
To get a good smooth user experience, the performance of the faceted search is critical. One if the limitations of a traditional SQL database is that everything is modelled as rows and columns. So when you need to have complex structured objects, you rely on joining tabels together and mapping them into objects. This is all fine and well in most cases, but when you aim to get the very best performance and the objects are well defined we can do better with tools like MongoDB. Not having to deal with schema reduces development time, when building something that should be denormalized, and avoiding mapping and multiple joins cuts the cost of a query runtime.
Takes two to perform
Just as it takes two to tango, it also takes good performance both backend and frontend, to provide the experience of good performance. To facilitate this I chose to use KnockoutJS – another tool I have blogged about earlier. knockout was used to handle two-way binding of the model and elements on the page, and Ajax for requesting the search results from the server, and updating the model.
Snapping together the logo pieces
As Scott Hanselman often describes it, modern tools should fit together well, giving the same feeling as lego pieces that snap together. This really was the feeling I had when I implemented the faceted search. Defining the model serverside, passing objects on through a service, and then having them serialized to JSon which in turn was made into KnockoutJS observables just felt smooth and painless.
The only thing I had to reconsider was using the LINQ implementation in NoRM, which isn’t quite good enough yet. This was however a small hickup, as the more native API that NoRM provides worked fine and was easy to use.
Looking back the actual implementation including doing indexes did not take long, and the performance just rocks. So this is without a doubt one if the more fun challanges I have had lately, and a solution that I feel proud of.