public
Description: Schemaless data in a traditional rdbms. Inspired by friendfeed
Homepage: http://brianthecoder.com/datamapper-is-schemaless-or-can-be
Clone URL: git://github.com/BrianTheCoder/dm-is-schemaless.git
name age message
file LICENSE Fri Sep 18 13:19:31 -0700 2009 moving to dm-next [BrianTheCoder]
file README.rdoc Mon Oct 26 14:02:28 -0700 2009 updated readme and created gem [BrianTheCoder]
file Rakefile Mon Oct 26 14:02:28 -0700 2009 updated readme and created gem [BrianTheCoder]
file TODO Fri Sep 18 13:19:31 -0700 2009 moving to dm-next [BrianTheCoder]
file VERSION Mon Oct 26 14:02:28 -0700 2009 updated readme and created gem [BrianTheCoder]
directory benchmarks/ Fri Oct 30 02:07:06 -0700 2009 tweaked query transform to only iterate over in... [BrianTheCoder]
file dm-is-schemaless.gemspec Mon Oct 26 14:02:28 -0700 2009 updated readme and created gem [BrianTheCoder]
directory lib/ Fri Oct 30 02:44:54 -0700 2009 removed assignment in transform query [BrianTheCoder]
directory spec/ Fri Oct 30 02:07:06 -0700 2009 tweaked query transform to only iterate over in... [BrianTheCoder]
directory tasks/ Fri Sep 18 13:19:31 -0700 2009 moving to dm-next [BrianTheCoder]
README.rdoc

dm-is-schemaless

Inspired by bret.appspot.com/entry/how-friendfeed-uses-mysql I wanted to build a way to do that seamless. Hence this plugin.

Basics

It’s pretty straight forward. The bare minimum to use it is:

  class Message
    include DataMapper::Resource

    is :schemaless

    # The following properties will be defined automatically
    # property :added_id, DataMapper::Types::Serial, :key => false
    # property :id, DataMapper::Types::UUID, :unique => true, :nullable => false, :index => true
    # property :updated, DataMapper::Types::EpochTime, :key => true, :index => true
    # property :body, DataMapper::Types::Json
  end

Away you go! By default it creates keys and a few other fields. It adds a bit of method missing magic so any property you want automatically has name, name=, and name?. You should use these instead of accessing the body hash directly in order to keep nil indexes from being setup.

Indexes

Declaring indexes. Just use the class level index_on method and supply a symbol. This will create the association and a table called <property>Index. It also creates an update hook to monitor the record when its save and handle creating/updating/destroying the index record.

  class Message
    include DataMapper::Resource

    is :schemaless

    index_on :email
  end

Querying

This is handled for you automatically. After you create an index on a property whenever you use that in a query it will transform the query to look it up on the index table instead. So internally here’s what happens.

  # original query
  Message.all(:email => 'test@gmail.com')
  # transformed query
  Message.all('email_index.email' => 'test@gmail.com')

This will also still support all of DM’s query operators.

Props to Dan Kubb for all his awesome work on DM and helping fix/refine this code.

File all bugs as issues on the project github.com/BrianTheCoder/dm-is-schemaless