RDDB is a Ruby Document-oriented Database. It is inspired by CouchDB and the notion that you insert documents into the database and then define views for querying. Views are defined as blocks which are used to select the documents and the attributes in the documents that are relevant to your needs. Views are materialized to enhance performance.

Features

* Documents are simply collections of name/value pairs.
* Views can be defined with Ruby code, mapping from a document to any other data structure, such as a String, Array or Hash.
* A reduce block can be defined to reduce the initial mapped data from a view.
* Views can be materialized to improve query performance.
* Datastores are pluggable. Current implementations are RAM, partitioned files and Amazon S3.
* Viewstores are pluggable. Current implementations are RAM, file system and Amazon S3.
* Materialization stores are pluggable. Current implementations are RAM, file system and Amazon S3.
* Distributed materialization may work, but it's going to be rewritten.

Code

This first example creates three documents and then queries for the names in the documents.

  # First create an database object
  database = Rddb::Database.new
  
  # Put some documents into it
  database << {:name => 'John', :income => 35000}
  database << {:name => 'Bob', :income => 40000}
  database << {:name => 'Jim', :income => 37000}
  
  # Create a view that will return the names
  database.create_view('names') do |document, args|
    document.name
  end
  
  # The result of querying will return an array of names
  assert_equal ['John','Bob','Jim'], database.query('names')
  
In addition it is possible to specify a block to reduce the result set:

  database.create_view('total income') do |document, args|
    document.income
  end.reduce_with do |results|
    results.inject { |memo,value| memo + value }
  end
  assert_equal 112000, database.query('total income')
  
Here's another example, this time averaging the incomes:

  database.create_view('average income') do |document, args|
    document.income
  end.reduce_with do |results|
    results.inject { |memo,value| memo + value } / results.length
  end
  assert_equal 37333, database.query('average income')
  
You can also implement grouping:

  database.create_view('total income by profession') do |document, args|
    [document.profession, document.income]
  end.reduce_with do |results|
    returning Hash.new do |reduced|
      results.each do |result|
        reduced[result[0]] ||= 0
        reduced[result[0]] += result[1]
      end
    end
  end
  
  results = database.query('total income by profession')
  assert_equal 77000, results['Plumber']
  assert_equal 35000, results['Carpenter']