Understanding MongoDB Object Modeling in Grails and GORM

May 28, 2013

One of the newer, and extremely powerful and cool, features of Grails is the support for NoSQL dialects in GORM. If you are not familiar with GORM, it refers to the Grails Object Relational Model, and was initially developed alongside Hibernate primarily. It basically took ORM solutions like Hibernate, and Groovified them. The result is extreme simplicity in not only defining object models but also in querying data via dynamic finders and a custom DSL for criteria queries. In the 2.x releases of Grails, GORM was extended to support other options other than Hibernate. The first of these was NoSQL and in the newer releases since it is beginning to include support for REST as well. Grails now supports a variety of NoSQL dialects including Redis and MongoDB. The dialect I am interested in and will be demonstrating is MongoDB.

Grails and GORM support for MongoDB is very straightforward. In fact, I was able to convert my existing data model in GORM from Hibernate/MySQL to MongoDB with relatively few changes. The biggest change was deciding which associations should be relational and which should be embedded. MongoDB supports embedded collections, maps, and objects. For objects that are fully contained in an object and follows the same lifecycle (i.e.: one-to-one associations), embedded data makes most sense. To mark an association as embedded, simply use the ‘embedded’ property in the object model.

class User {
    static embedded = [ 'address' ]
 
    String name
    Address address
}

If an embedded association is used, then the address association instance will be included in the MongoDB user object.

User(1)

{
    _id : 1,
    name : 'John Doe',
    address : {
        street: '1234 Main St',
        city : 'Somewhere'
    }
}

Otherwise, an address table will be created in MongoDB and the user table will contain an association to it.

Address(1)

{
    _id : 1,
    street: '1234 Main St',
    city : 'Somewhere'
}

User(1)

{
    _id : 1,
    name : 'John Doe',
    address : 1
}

There are actually two supported models for relational data in MongoDB. One is a pure reference which contains a reference to the database collection and id. This is sometimes used by MongoDB drivers to automatically lookup the reference. The other is a manual reference which is purely an id (as in the example above). The association is left to the user or tool. In the case of GORM, the association is automatically done as Grails knows the relation from the object model. Further, Grails supports both lazy and eager fetching such that it can limit the association lookups until they are needed (or if they are needed). The default is a manual association and is the recommended approach in MongoDB. For more information, consult the GORM MongoDB plugin documentation.

The rest of the work is mostly about object modeling. Although Grails supports the notion of automatic relational associations, it is important to think about the uses of the data and optimize to MongoDB’s architecture. Despite the fact that a data model in MySQL will work in MongoDB, the performance will be vastly different. The power of NoSQL is often in big data and the non-relational aspect of data. For example, each time you include an external reference (non-embedded), you are forcing a roundtrip lookup in MongoDB. Within MySQL, the same is true, but the reference is done directly on the server, so there is no negative multi-roundtrip network latency impact. In reality, it is best to start thinking non-relational and only utilize relational associations when the duplication and management of data becomes a bigger maintainability issue than the performance improvement. It is also best to think in terms of data embedding where it makes most sense. Not only does embedding data result in no relational association, it also provides more query benefits as Grails does not allow querying a relational association. However, if the data within the embedded data is constantly changing or growing, it may become a performance bottleneck on updates and inserts where embedding the data no longer makes sense. The important thing to remember is design to your use cases. MongoDB does not fit every use case, nor does MySQL. The beauty of GORM is that it can be used to fit almost any use case and adapts to a variety of technologies to do it.

All in all, MongoDB within Grails is an incredibly powerful feature with pure simplicity. There are several more features I did not touch on including dynamic properties for schema less design. In my next post I will show how to sniff the MongoDB traffic and understand how Grails maps dynamic queries into actual MongoDB queries.

One Response to “Understanding MongoDB Object Modeling in Grails and GORM”

  1. [...] out the entire object model. If you are unfamiliar with MongoDB within Grails and GORM, read my previous post. One of the nice features of Hibernate is that it can log all SQL generated queries to the log or [...]