April 12th, 2011

MySQL + NoSQL = joy + happiness

On Friday we released a shiny new Symfony plugin for those who need to store a little extra data without making a big ol' database schema change every single bingle time. Maybe you're tempted to jump ship to NoDB solutions like MongoDB... maybe you're reluctant to throw all of MySQL's benefits out with the bathwater. Now you don't have to.

sfDoctrineActAsKeyValueStorePlugin provides you with a simple key-value attribute store associated with any Doctrine object that has the KeyValueStore behavior. Think of it as a mini-MongoDB for those times when SQL is a little too much:

 

# in schema.yml sfGuardUser: actAs: [KeyValueStore]

$user = // fetch your user with a normal Doctrine query // Stash some extra data $user->aSet('seen_welcome', true); $user->save(); $user = // Later, fetch the object again // Get our attribute back, with a default $user->aGet('seen_welcome', false);

All of your extra data goes into a serialized blob column. In English, that means it is very fast and light and can contain full-blown PHP data structures. It also means that the key-value store is not suitable for things you'll need to query for across all users later. So just promise me you won't use it to store the user's age, height, dating preference or anything else you're going to weep about when it comes time to write a query that compares users with each other.

sfDoctrineActAsKeyValueStorePlugin is unit-tested and mother-approved. Use it in good health!

P.S. We've learned of a similar plugin by Ryan Weaver, sfDoctrineSlotPlugin. As it turns out they have different pros and cons and you might even want both in some projects. Our KeyValueStore behavior is extremely fast and efficient, provided your extra data isn't huge, and has relaxed semantics similar to working with session attributes. Also, since all of your extra data serializes into a single blog column in the original table, cleanup is automatic when objects are deleted. Ryan's slots, on the other hand, can potentially be queried for across many users. And if you have lots and lots of attributes you don't always want to fetch they may be more efficient in that case.

I've used users here as an example, you can attach these behaviors to any table in your database.