Skip to content

Instantly share code, notes, and snippets.

@bkerley
Created October 27, 2011 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bkerley/1320752 to your computer and use it in GitHub Desktop.
Save bkerley/1320752 to your computer and use it in GitHub Desktop.
irb(main):019:0> q = Qria.new
=> #<Qria:0x007fbec8c873f8 @thunks=[]>
irb(main):020:0> q.where{|x| x > 5 }
=> [#<Thunk:0x007fbec8c74d70 @name=:>, @args=[5]>]
irb(main):021:0> q.where{|x| x.match '/^text/'}
=> [#<Thunk:0x007fbec8c74d70 @name=:>, @args=[5]>, #<Thunk:0x007fbec8c67698 @name=:match, @args=["/^text/"]>]
irb(main):022:0> puts q.to_js
function(t) {
var i = Riak.mapValuesJson(t)[0];
var c = true;
c &&= i > 5;c &&= i.match(/^text/);
if(c) {return [i];}
return [];
}
irb(main):008:0> puts q.to_erl
fun(Value, KeyData, Arg) ->
Data = riak_object:get_value(Value),
Comparison = (Data > 5),
case Comparison of
true ->
[Data]
_ ->
[]
end
end.
=> nil
master > bundle exec ruby qria-demo.rb
Full-bucket MapReduce, including key filters, invokes list-keys which is an expensive operation that should not be used in production.
qria-demo.rb:23:in `<main>'
function(t) {
var i = Riak.mapValuesJson(t)[0];
var c = true;
c = c && (i['speed'] > 50);c = c && (i['word'].match(/5/));
if(c) {return [i];};
return [];
}
[{"measured_at"=>"2011-11-08T02:47:24Z",
"speed"=>99,
"word"=>"28yecx9t45",
"_type"=>"Weather"},
{"measured_at"=>"2011-11-08T02:47:24Z",
"speed"=>85,
"word"=>"6y454gcsc5",
"_type"=>"Weather"},
{"measured_at"=>"2011-11-08T02:47:24Z",
"speed"=>70,
"word"=>"83prerg3v5",
"_type"=>"Weather"},
{"measured_at"=>"2011-11-08T02:47:24Z",
"speed"=>92,
"word"=>"btu2unish5",
"_type"=>"Weather"},
{"measured_at"=>"2011-11-08T02:47:24Z",
"speed"=>77,
"word"=>"1o4t1i352g",
"_type"=>"Weather"},
{"measured_at"=>"2011-11-08T02:47:24Z",
"speed"=>94,
"word"=>"7y08c5jk5x",
"_type"=>"Weather"}]
bkerley@basho-bryce ★ 1.9.2-p290 ~/Documents/qria
master >
source :rubygems
path '/Users/bkerley/Documents/ripple' do
gem 'riak-client'
gem 'ripple'
end
PATH
remote: /Users/bkerley/Documents/ripple
specs:
riak-client (1.0.0.beta)
beefcake (~> 0.3.7)
builder (>= 2.1.2)
i18n (>= 0.4.0)
multi_json (~> 1.0.0)
ripple (1.0.0.beta)
activemodel (>= 3.0.0, < 3.2.0)
activesupport (>= 3.0.0, < 3.2.0)
riak-client (~> 1.0.0.beta)
tzinfo
GEM
remote: http://rubygems.org/
specs:
activemodel (3.1.1)
activesupport (= 3.1.1)
builder (~> 3.0.0)
i18n (~> 0.6)
activesupport (3.1.1)
multi_json (~> 1.0)
beefcake (0.3.7)
builder (3.0.0)
i18n (0.6.0)
multi_json (1.0.3)
tzinfo (0.3.30)
PLATFORMS
ruby
DEPENDENCIES
riak-client!
ripple!
function(t) {
var i = Riak.mapValuesJson(t)[0];
var c = true;
c = c && (i['speed'] > 50);
c = c && (i['word'].match(/5/));
if(c) {
return [i];
};
return [];
}
require 'ripple'
require 'pp'
require './qria'
Thread.current[:ripple_client] = Riak::Client.new http_port: 8091
class Weather
include Ripple::Document
property :measured_at, Time, index: true
property :speed, Integer, index: true
property :word, String
end
if ARGV[0] == '--seed'
100.times do |i|
Weather.create measured_at: Time.now, speed: i, word: rand(36**10).to_s(36)
end
end
r = Riak::MapReduce.new Thread.current[:ripple_client]
r.add Weather.bucket
q = Qria.new
q.where{ |x| x['speed'] > 50 }.where{ |x| x['word'].match('/5/') }
puts q.to_js
# puts q.to_erl
r.map q.to_js, keep: true
pp r.run
require 'blankslate'
class Recorder < BlankSlate
def initialize(parent)
@parent = parent
@fieldname = nil
end
def [](fieldname)
@fieldname = fieldname
self
end
def method_missing(name, *args, &block)
t = Thunk.new(name, @fieldname, args)
@parent.thunks << t
end
end
class Thunk
attr_accessor :name, :fieldname, :args
def initialize(name, fieldname, args=[])
self.name = name
self.fieldname = fieldname
self.args = args
end
def inspect
"<Thunk #{name.inspect} #{fieldname} #{args.inspect}>"
end
def to_js
if %w{ > < >= <= == === }.include? self.name.to_s
return comparison_to_js
end
"#{js_fieldname}.#{name}(#{args.join ', '})"
end
def comparison_to_js
"#{js_fieldname} #{name} #{args.first}"
end
def js_fieldname
return '' if self.fieldname.blank?
"['#{self.fieldname}']"
end
def to_erl
raise "I don't know that much Erlang :(" unless %w{ > < >= <= == }.include? self.name.to_s
"#{name} #{args.first}"
end
end
class Qria
attr_accessor :thunks
def initialize
self.thunks = []
end
def where
yield Recorder.new self
self
end
def to_erl
thunked_methods = thunks.map(&:to_erl)
thunked_comparisons = thunked_methods.map do |m|
"(Data #{m})"
end.join(' && ')
<<-EOF
fun(Value, KeyData, Arg) ->
Data = riak_object:get_value(Value),
Comparison = #{thunked_comparisons},
case Comparison of
true ->
[Data]
_ ->
[]
end
end.
EOF
end
def to_js
thunked_methods = thunks.map(&:to_js)
thunked_comparisons = thunked_methods.map do |m|
"c = c && (i#{m})"
end.join(';')
<<-EOF
function(t) {
var i = Riak.mapValuesJson(t)[0];
var c = true;
#{thunked_comparisons};
if(c) {return [i];};
return [];
}
EOF
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment