mdquery

<img src=“https://secure.travis-ci.org/mccraigmccraig/mdquery.png” />

Defines a DSL for specifying and executing segmented multi-dimensional queries on your ActiveRecord-3 models

Installation

gem install mdquery

Usage

A Dataset consists of some Measures over some Dimensions of a Source

  • Measures are SQL aggregate functions to be computed, e.g. “count(*)” or “avg(age)”

  • Each Dimension consists of 1 or more Segments, and each Segment either fixes a value for the Dimension or extracts values from the Source. Each Segment may narrow the Source scope according to the Dimension value or value-range for the Segment

  • A Source is an ActiveRecord-3 Scope

Given the definition of the Dataset, it will query the Sources to extract data points, each of which will have a value for each Dimension and a value for each Measure

require 'mdquery'

Q = MDQuery.dataset do
  source Foo

  measure :count, "count(*)", :int

  dimension :time do
    label "Time"

    segment(:all) do
      fix_dimension :all
    end

    segment(:five_years) do
      narrow{|scope| scope.where("foos.created_at > now() - interval '5 years'")}
      extract_dimension "extract(year from foos.created_at)"
      values{|scope| (Date.today.year-4..Date.today.year).to_a.map(&:to_s)}
      label{|value| "Year: #{value}"}
    end
  end

  dimension :users do
    label "Users"

    segment(:all) do
      fix_dimension :all
    end

    segment(:by_type) do
      extract_dimension "user_types.name"
      narrow{|scope| scope.joins(:user_types)}
    end
  end
end

# run queries, collect data. returns an MDQuery::Dataset::Dataset
dataset = Q.collect

# retrieve dimension values, segment values and labels
dataset.dimensions[:time][:five_years].values # => ["2008", "2009", "2010", "2011", "2012"]
dataset.dimensions[:time].label_for("2008") #=> "Year: 2008"
dataset.datapoint({:time=>'2008', :users=>'all'}, :count) # => 100 # 100 users in 2008

Contributing to mdquery

  • Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet.

  • Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it.

  • Fork the project.

  • Start a feature/bugfix branch.

  • Commit and push until you are happy with your contribution.

  • Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright © 2012 mccraigmccraig. See LICENSE.txt for further details.