This project is an attempt to implement a fast MongoDB <-> Scala case class mapping mechanism. It is in fact my third stab at this problem; this time, I'm focusing on speed more than flexibility, compatibility, and functionality.
More information is availabe on the wiki. Salat-related discussion and questions belong on the mailing list.
-
Convert an instance of any Scala case class to a
DBObject
suitable for insertion into a MongoDB database. -
Given a
DBObject
(which may have come from MongoDB, or elsewhere), instantiate an instance of the corresponding case class. -
Achieve goals 1 and 2 without sacrificing performance. This more or less rules out use of reflection.
-
Achieve goals 1, 2, and 3 while adhering as much as feasible to core tenets of functional programming.
Considering above goals (especially 3), I have decided to make particular sacrifices and not look back.
Scala case classes are essentially products, and as such provide certain features which can be used to improve object serialization. These features include:
-
A simple and accessible constructor. Can be retrieved either by reflecting on the class itself, or through generated companion object.
-
Provided
productIterator
: a non-reflective way to retrieve programmatically values of the case class' data members. -
Data members can have default values; information missing in
DBObject
instance during re-inflation can be subbed in using default args defined at compile time.
I hereby thank EPFL for the wonderfully undocumented ScalaSig. Fortunately, its source code reads like a work of art and isn't hard to comprehend. Obviously, if the previous section hasn't ruled out Java support, this certainly does.
ScalaSig does not appear to digest very well classes written in pure Java. Not a big deal, because we only support case classes anyway.
NB: it turns out that ScalaSig is incapable of "parsing" classes
defined in the REPL, since there really is no .class
file to
parse. None of this code will work with classes that have no
corresponding .class
file.
There's currently no way to alter default behavior of Salat's critical internal components. For example, it's impossible to tell it to exclude particular data members from (de)serialization. Similarly, the code is also not set up to even know anything about fields that aren't part of the case class constructor.
"Salat" is a transliteration of the Russian word "салат", for "salad". I picked this name because salad is great for your health and will not slow you down through use of runtime reflection.