marbu 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +13 -0
- data/Readme.md +58 -0
- data/bin/marbu-web +20 -0
- data/bin/marbu-web-mongo-config.rb +8 -0
- data/lib/core_ext/array.rb +7 -0
- data/lib/core_ext/enumerable.rb +25 -0
- data/lib/core_ext/hash.rb +35 -0
- data/lib/core_ext/indifferent_access.rb +11 -0
- data/lib/core_ext/object.rb +25 -0
- data/lib/core_ext/open_struct.rb +3 -0
- data/lib/core_ext/string.rb +25 -0
- data/lib/marbu/builder.rb +48 -0
- data/lib/marbu/builders/mongodb.rb +106 -0
- data/lib/marbu/exceptions.rb +7 -0
- data/lib/marbu/formatters/base.rb +6 -0
- data/lib/marbu/formatters/dummy.rb +9 -0
- data/lib/marbu/formatters/formatters.rb +3 -0
- data/lib/marbu/formatters/one_line.rb +9 -0
- data/lib/marbu/models/db/db.rb +3 -0
- data/lib/marbu/models/db/mongodb/exceptions.rb +59 -0
- data/lib/marbu/models/db/mongodb/mongodb.rb +54 -0
- data/lib/marbu/models/db/mongodb/structure.rb +40 -0
- data/lib/marbu/models/exception_link.rb +11 -0
- data/lib/marbu/models/models.rb +3 -0
- data/lib/marbu/models/mrf/base.rb +133 -0
- data/lib/marbu/models/mrf/code.rb +32 -0
- data/lib/marbu/models/mrf/finalize.rb +9 -0
- data/lib/marbu/models/mrf/map.rb +7 -0
- data/lib/marbu/models/mrf/map_reduce_finalize.rb +107 -0
- data/lib/marbu/models/mrf/misc.rb +65 -0
- data/lib/marbu/models/mrf/mrf.rb +8 -0
- data/lib/marbu/models/mrf/query.rb +39 -0
- data/lib/marbu/models/mrf/reduce.rb +7 -0
- data/lib/marbu/server/public/css/style.css +149 -0
- data/lib/marbu/server/public/images/remove.png +0 -0
- data/lib/marbu/server/public/js/builder.js +200 -0
- data/lib/marbu/server/views/_builder_col_code.haml +8 -0
- data/lib/marbu/server/views/_builder_col_emit_keys.haml +13 -0
- data/lib/marbu/server/views/_builder_col_emit_values.haml +12 -0
- data/lib/marbu/server/views/_builder_data_samples.haml +8 -0
- data/lib/marbu/server/views/_builder_misc.haml +20 -0
- data/lib/marbu/server/views/_collection_nested_list.haml +0 -0
- data/lib/marbu/server/views/_footer.haml +2 -0
- data/lib/marbu/server/views/_header.haml +3 -0
- data/lib/marbu/server/views/_header_col.haml +6 -0
- data/lib/marbu/server/views/builder.haml +37 -0
- data/lib/marbu/server/views/layout.haml +19 -0
- data/lib/marbu/server/views/mapreduce.haml +9 -0
- data/lib/marbu/server/views/root.haml +11 -0
- data/lib/marbu/server/views/sample_data.haml +17 -0
- data/lib/marbu/server.rb +199 -0
- data/lib/marbu/server_sinatra.rb +168 -0
- data/lib/marbu/version.rb +3 -0
- data/lib/marbu.rb +65 -0
- data/spec/constants.rb +149 -0
- data/spec/rubymine-server.rb +0 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/unit/builders/builder_spec.rb +5 -0
- data/spec/unit/builders/mongodb_spec.rb +52 -0
- data/spec/unit/models/base_spec.rb +33 -0
- data/spec/unit/models/map_reduce_finalize_spec.rb +28 -0
- data/spec/unit/models/map_spec.rb +22 -0
- data/spec/unit/models/query_spec.rb +23 -0
- metadata +209 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require 'sinatra'
|
|
4
|
+
require 'marbu'
|
|
5
|
+
Marbu.port = '27017'
|
|
6
|
+
Marbu.uri = '127.0.0.1'
|
|
7
|
+
|
|
8
|
+
Mongoid.configure do |config|
|
|
9
|
+
config.master = Mongo::Connection.new.db('marbu')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
configure :development do
|
|
13
|
+
require 'ruby-debug'
|
|
14
|
+
enable :logging, :dump_errors, :raise_errors,
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
enable :method_override
|
|
18
|
+
|
|
19
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
|
20
|
+
set :views, "#{dir}/server/views"
|
|
21
|
+
set :public_folder, "#{dir}/server/public"
|
|
22
|
+
set :static, true
|
|
23
|
+
|
|
24
|
+
helpers do
|
|
25
|
+
def url_path(*path_parts)
|
|
26
|
+
[ path_prefix, path_parts ].join("/").squeeze('/')
|
|
27
|
+
end
|
|
28
|
+
alias_method :u, :url_path
|
|
29
|
+
|
|
30
|
+
def path_prefix
|
|
31
|
+
request.env['SCRIPT_NAME']
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
get "/" do
|
|
36
|
+
@mrms = Marbu::Models::Db::MongoDb.all
|
|
37
|
+
show 'root'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
get "/builder/new" do
|
|
41
|
+
@mrm = Marbu::Models::Db::MongoDb.new
|
|
42
|
+
@mrf = @mrm.map_reduce_finalize
|
|
43
|
+
show 'builder'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
post "/builder" do
|
|
47
|
+
@mrm = build_mrm_from_params(params.merge({:logger => logger}))
|
|
48
|
+
@mrm.save!
|
|
49
|
+
redirect "/builder/#{@mrm.uuid}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
get "/builder/:uuid" do
|
|
53
|
+
@mrm = Marbu::Models::Db::MongoDb.first(conditions: {uuid: params['uuid']})
|
|
54
|
+
@mrf = @mrm.map_reduce_finalize
|
|
55
|
+
show 'builder'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
put "/builder/:uuid" do
|
|
59
|
+
@mrm = build_mrm_from_params(params.merge({:logger => logger}))
|
|
60
|
+
@mrm.save!
|
|
61
|
+
redirect "/builder/#{@mrm.uuid}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
delete "/builder/:uuid" do
|
|
65
|
+
@mrm = Marbu::Models::Db::MongoDb.first(conditions: {uuid: params['uuid']})
|
|
66
|
+
@mrm.destroy if @mrm.present?
|
|
67
|
+
redirect "/"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
get "/mapreduce/:uuid" do
|
|
71
|
+
@mrm = Marbu::Models::Db::MongoDb.first(conditions: {uuid: params['uuid']})
|
|
72
|
+
@mrf = @mrm.map_reduce_finalize
|
|
73
|
+
@builder = Marbu::Builder.new(@mrf)
|
|
74
|
+
@error = nil
|
|
75
|
+
|
|
76
|
+
begin
|
|
77
|
+
# TODO: naturally this has to take the DATABASE and COLLECTION from the mapreducefilter object
|
|
78
|
+
# TODO: don;t take the parameters from the mapreducefilter object if DATABASE or DATABASE and COLLECTION are
|
|
79
|
+
# TODo: defined in the configuration (security)
|
|
80
|
+
@res = @mrf.misc.collection.map_reduce( @builder.map(:mongodb), @builder.reduce(:mongodb),
|
|
81
|
+
{
|
|
82
|
+
:query => @builder.query,
|
|
83
|
+
:out => {:replace => "tmp."+@mrm.map_reduce_finalize.misc.output_collection},
|
|
84
|
+
:finalize => @builder.finalize(:mongodb)
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
rescue Mongo::OperationFailure => e
|
|
88
|
+
@parsed_error = Marbu::Models::Db::MongoDb::Exception.explain(e, @mrf)
|
|
89
|
+
@error = @parsed_error[:message]
|
|
90
|
+
@fix_link = Marbu::Models::ExceptionLink.get_exception_fix_link(@parsed_error[:id], params['uuid'])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
show 'mapreduce'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def build_mrm_from_params(params)
|
|
97
|
+
name = 'name'
|
|
98
|
+
function = 'function'
|
|
99
|
+
|
|
100
|
+
if (uuid = params['uuid'])
|
|
101
|
+
mrm = Marbu::Models::Db::MongoDb.find_or_create_by(uuid: uuid)
|
|
102
|
+
else
|
|
103
|
+
mrm = Marbu::Models::Db::MongoDb.new
|
|
104
|
+
end
|
|
105
|
+
mrm.name = params['name']
|
|
106
|
+
mrf = mrm.map_reduce_finalize
|
|
107
|
+
|
|
108
|
+
mrf.map = Marbu::Models::Map.new(
|
|
109
|
+
:code => {:text => params['map_code']}
|
|
110
|
+
)
|
|
111
|
+
mrf.reduce = Marbu::Models::Reduce.new(
|
|
112
|
+
:code => {:text => params['reduce_code']}
|
|
113
|
+
)
|
|
114
|
+
mrf.finalize = Marbu::Models::Finalize.new(
|
|
115
|
+
:code => {:text => params['finalize_code']}
|
|
116
|
+
)
|
|
117
|
+
mrf.query = Marbu::Models::Query.new(
|
|
118
|
+
:condition => params['query_condition'],
|
|
119
|
+
:force_query => params['query_force_query']
|
|
120
|
+
)
|
|
121
|
+
mrf.misc = Marbu::Models::Misc.new(
|
|
122
|
+
:database => params['database'],
|
|
123
|
+
:input_collection => params['input_collection'],
|
|
124
|
+
:output_collection => params['output_collection']
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# add params to map_new, reduce_new, finalize_new
|
|
128
|
+
['map', 'reduce', 'finalize'].each do |stage|
|
|
129
|
+
['key', 'value'].each do |type|
|
|
130
|
+
stage_type_name = params["#{stage}_#{type}_#{name}"]
|
|
131
|
+
stage_type_function = params["#{stage}_#{type}_#{function}"]
|
|
132
|
+
|
|
133
|
+
if( stage_type_name.present?)
|
|
134
|
+
stage_type_name.each_with_index do |n, i|
|
|
135
|
+
case stage
|
|
136
|
+
when 'map' then add(mrf.map, type, n, stage_type_function[i])
|
|
137
|
+
when 'reduce' then add(mrf.reduce, type, n, stage_type_function[i])
|
|
138
|
+
when 'finalize' then add(mrf.finalize, type, n, stage_type_function[i])
|
|
139
|
+
else raise Exception.new("#{stage} in #{k} is unknown")
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# TODO:
|
|
147
|
+
# copy keys and values from map to reduce block
|
|
148
|
+
# copy keys from map to finalize block
|
|
149
|
+
# reduce_new.keys = mrf.map.keys
|
|
150
|
+
# reduce_new.values = mrf.map.values
|
|
151
|
+
# finalize_new.keys = mrf.map.keys
|
|
152
|
+
|
|
153
|
+
mrm.map_reduce_finalize = mrf
|
|
154
|
+
return mrm
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def add(model, type, name, function)
|
|
158
|
+
case type
|
|
159
|
+
when 'key' then model.add_key(name, function)
|
|
160
|
+
when 'value' then model.add_value(name, function)
|
|
161
|
+
else raise Exception.new("#{type} is unknown")
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def show(page)
|
|
166
|
+
haml page.to_sym
|
|
167
|
+
end
|
|
168
|
+
|
data/lib/marbu.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'mongo'
|
|
2
|
+
require 'mongoid'
|
|
3
|
+
require 'core_ext/enumerable'
|
|
4
|
+
|
|
5
|
+
require 'marbu/exceptions'
|
|
6
|
+
require 'marbu/formatters/formatters'
|
|
7
|
+
require 'marbu/builders/mongodb'
|
|
8
|
+
require 'marbu/builder'
|
|
9
|
+
require 'marbu/models/models'
|
|
10
|
+
|
|
11
|
+
module Marbu
|
|
12
|
+
# Your code goes here...
|
|
13
|
+
extend self
|
|
14
|
+
|
|
15
|
+
attr_reader :port, :uri
|
|
16
|
+
attr_accessor :storage
|
|
17
|
+
|
|
18
|
+
def database=(database)
|
|
19
|
+
@database = database
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def collection=(collection)
|
|
23
|
+
@collection = collection
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def port=(port)
|
|
27
|
+
@port = port
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def uri=(uri)
|
|
31
|
+
@uri = uri
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def connection
|
|
35
|
+
if( @uri and @port )
|
|
36
|
+
@connection ||= Mongo::Connection.new(@uri, @port)
|
|
37
|
+
else
|
|
38
|
+
@connection = nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
@connection
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def database
|
|
45
|
+
if connection and @database
|
|
46
|
+
connection.db(@database)
|
|
47
|
+
else
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def collection
|
|
53
|
+
if database and @collection
|
|
54
|
+
database.collection(@collection)
|
|
55
|
+
else
|
|
56
|
+
nil
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def storage_collection
|
|
61
|
+
Mongo::Connection.new(storage[:uri],storage[:port]).db(storage[:database]).collection(storage[:collection])
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
data/spec/constants.rb
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
MR_WWB_LOC_DIM0 = {
|
|
2
|
+
:map => {
|
|
3
|
+
:keys => [
|
|
4
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"}
|
|
5
|
+
],
|
|
6
|
+
:values => [
|
|
7
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
8
|
+
{:name => "count"}
|
|
9
|
+
],
|
|
10
|
+
:code => {
|
|
11
|
+
:text => 'count = 1;',
|
|
12
|
+
:type => "JS"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
:reduce => {
|
|
17
|
+
:values => [
|
|
18
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
19
|
+
{:name => "count"}
|
|
20
|
+
],
|
|
21
|
+
:code => {
|
|
22
|
+
:type => "JS",
|
|
23
|
+
:text => <<-JS
|
|
24
|
+
var count = 0;
|
|
25
|
+
values.forEach(function(v){
|
|
26
|
+
count += v.count;
|
|
27
|
+
});
|
|
28
|
+
JS
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
:finalize => {
|
|
33
|
+
:values => [
|
|
34
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
35
|
+
{:name => "count", :function => "value.count"}
|
|
36
|
+
],
|
|
37
|
+
:code => {
|
|
38
|
+
:text => 'count = (count/100)*100.0;',
|
|
39
|
+
:type => "JS"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
:misc => {
|
|
44
|
+
:database => "qed_test",
|
|
45
|
+
:input_collection => 'world_wide_business',
|
|
46
|
+
:output_collection => 'world_wide_business_mr_dim0',
|
|
47
|
+
:output_operation => 'replace',
|
|
48
|
+
:filter_data => true,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
:query => {
|
|
52
|
+
:datetime_fields => [:created_at]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
MR_WWB_LOC_DIM0_NO_MAP_EMIT_KEYS = {
|
|
57
|
+
:map => {
|
|
58
|
+
:values => [
|
|
59
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
60
|
+
{:name => "count"}
|
|
61
|
+
],
|
|
62
|
+
:code => {
|
|
63
|
+
:text => 'count = 1;',
|
|
64
|
+
:type => "JSS"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
:reduce => {
|
|
69
|
+
:code => {
|
|
70
|
+
:text => <<-JS
|
|
71
|
+
var count = 0;
|
|
72
|
+
values.forEach(function(v){
|
|
73
|
+
count += v.count;
|
|
74
|
+
});
|
|
75
|
+
JS
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
:finalize => {
|
|
80
|
+
:values => [
|
|
81
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
82
|
+
{:name => "count", :function => "value.count"}
|
|
83
|
+
],
|
|
84
|
+
:code => {
|
|
85
|
+
:type => "JS",
|
|
86
|
+
:text => 'count = (count/100)*100.0;',
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
:misc => {
|
|
91
|
+
:database => "qed_test",
|
|
92
|
+
:input_collection => 'world_wide_business',
|
|
93
|
+
:output_collection => 'world_wide_business_mr_dim0',
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
:query => {
|
|
97
|
+
:datetime_fields => [:created_at]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
MR_WWB_LOC_DIM0_TWO_MAP_EMIT_KEYS = {
|
|
102
|
+
:map => {
|
|
103
|
+
:keys => [
|
|
104
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
105
|
+
{:name => "DIM_LOC_1", :function => "value.DIM_LOC_1"}
|
|
106
|
+
],
|
|
107
|
+
:values => [
|
|
108
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
109
|
+
{:name => "count"}
|
|
110
|
+
],
|
|
111
|
+
:code => {
|
|
112
|
+
:text => 'count = 1;',
|
|
113
|
+
:type => "JS"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
:reduce => {
|
|
118
|
+
:code => {
|
|
119
|
+
:type => "JS",
|
|
120
|
+
:text => <<-JS
|
|
121
|
+
var count = 0;
|
|
122
|
+
values.forEach(function(v){
|
|
123
|
+
count += v.count;
|
|
124
|
+
});
|
|
125
|
+
JS
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
:finalize => {
|
|
130
|
+
:values => [
|
|
131
|
+
{:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
|
|
132
|
+
{:name => "count", :function => "value.count"}
|
|
133
|
+
],
|
|
134
|
+
:code => {
|
|
135
|
+
:text => 'count = (count/100)*100.0;',
|
|
136
|
+
:type => "JS"
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
:misc => {
|
|
141
|
+
:database => "qed_test",
|
|
142
|
+
:input_collection => 'world_wide_business',
|
|
143
|
+
:output_collection => 'world_wide_business_mr_dim0',
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
:query => {
|
|
147
|
+
:datetime_fields => [:created_at]
|
|
148
|
+
}
|
|
149
|
+
}
|
|
File without changes
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
SimpleCov.start do
|
|
3
|
+
add_filter "/spec/"
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require 'rubygems'
|
|
7
|
+
require 'spork'
|
|
8
|
+
|
|
9
|
+
Spork.prefork do
|
|
10
|
+
# Loading more in this block will cause your tests to run faster. However,
|
|
11
|
+
# if you change any configuration or code from libraries loaded here, you'll
|
|
12
|
+
# need to restart spork for it take effect.
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
Spork.each_run do
|
|
17
|
+
# This code will be run each time you run your specs.
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# --- Instructions ---
|
|
22
|
+
# Sort the contents of this file into a Spork.prefork and a Spork.each_run
|
|
23
|
+
# block.
|
|
24
|
+
#
|
|
25
|
+
# The Spork.prefork block is run only once when the spork server is started.
|
|
26
|
+
# You typically want to place most of your (slow) initializer code in here, in
|
|
27
|
+
# particular, require'ing any 3rd-party gems that you don't normally modify
|
|
28
|
+
# during development.
|
|
29
|
+
#
|
|
30
|
+
# The Spork.each_run block is run each time you run your specs. In case you
|
|
31
|
+
# need to load files that tend to change during development, require them here.
|
|
32
|
+
# With Rails, your application modules are loaded automatically, so sometimes
|
|
33
|
+
# this block can remain empty.
|
|
34
|
+
#
|
|
35
|
+
# Note: You can modify files loaded *from* the Spork.each_run block without
|
|
36
|
+
# restarting the spork server. However, this file itself will not be reloaded,
|
|
37
|
+
# so if you change any of the code inside the each_run block, you still need to
|
|
38
|
+
# restart the server. In general, if you have non-trivial code in this file,
|
|
39
|
+
# it's advisable to move it into a separate file so you can easily edit it
|
|
40
|
+
# without restarting spork. (For example, with RSpec, you could move
|
|
41
|
+
# non-trivial code into a file spec/support/my_helper.rb, making sure that the
|
|
42
|
+
# spec/support/* files are require'd from inside the each_run block.)
|
|
43
|
+
#
|
|
44
|
+
# Any code that is left outside the two blocks will be run during preforking
|
|
45
|
+
# *and* during each_run -- that's probably not what you want.
|
|
46
|
+
#
|
|
47
|
+
# These instructions should self-destruct in 10 seconds. If they don't, feel
|
|
48
|
+
# free to delete them.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
52
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
53
|
+
|
|
54
|
+
require 'marbu'
|
|
55
|
+
require 'rspec'
|
|
56
|
+
require 'factory_girl'
|
|
57
|
+
require 'constants'
|
|
58
|
+
require 'mongodb-testdata-factory'
|
|
59
|
+
FactoryGirl.find_definitions
|
|
60
|
+
|
|
61
|
+
RSpec.configure do |config|
|
|
62
|
+
config.include Factory::Syntax::Methods
|
|
63
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
MONGODB_MAP_FUNCTION_ONE_LINE =
|
|
4
|
+
"function(){value=this.value;count=1;emit({DIM_LOC_0:value.DIM_LOC_0},{DIM_LOC_0:value.DIM_LOC_0,count:count});}"
|
|
5
|
+
MONGODB_MAP_FUNCTION_TWO_EMIT_KEYS_ONE_LINE =
|
|
6
|
+
"function(){value=this.value;count=1;emit({DIM_LOC_0:value.DIM_LOC_0,DIM_LOC_1:value.DIM_LOC_1},{DIM_LOC_0:value.DIM_LOC_0,count:count});}"
|
|
7
|
+
MONGODB_REDUCE_FUNCTION_ONE_LINE =
|
|
8
|
+
"function(key,values){value=values[0];varcount=0;values.forEach(function(v){count+=v.count;});return{DIM_LOC_0:value.DIM_LOC_0,count:count};}"
|
|
9
|
+
MONGODB_FINALIZE_FUNCTION_ONE_LINE =
|
|
10
|
+
"function(key,value){count=(count/100)*100.0;return{DIM_LOC_0:value.DIM_LOC_0,count:value.count};}"
|
|
11
|
+
|
|
12
|
+
describe Marbu::Builder::Mongodb do
|
|
13
|
+
context "for a mapreduce with one emit key" do
|
|
14
|
+
let(:mrf) { Marbu::Models::MapReduceFinalize.new(MR_WWB_LOC_DIM0) }
|
|
15
|
+
|
|
16
|
+
it "creates a map query" do
|
|
17
|
+
Marbu::Builder::Mongodb.map(mrf.map).should_not be_empty
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'creates the correct map query' do
|
|
21
|
+
Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.map(mrf.map)).should == MONGODB_MAP_FUNCTION_ONE_LINE
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "creates a reduce query" do
|
|
25
|
+
Marbu::Builder::Mongodb.reduce(mrf.reduce).should_not be_empty
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'creates the correct reduce query' do
|
|
29
|
+
Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.reduce(mrf.reduce)).should == MONGODB_REDUCE_FUNCTION_ONE_LINE
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "creates a finalize query" do
|
|
33
|
+
Marbu::Builder::Mongodb.finalize(mrf.finalize).should_not be_empty
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'create the correct finalize query' do
|
|
37
|
+
Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.finalize(mrf.finalize)).should == MONGODB_FINALIZE_FUNCTION_ONE_LINE
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "for a mapreduce with at least two emit keys" do
|
|
42
|
+
let(:mrf) { Marbu::Models::MapReduceFinalize.new(MR_WWB_LOC_DIM0_TWO_MAP_EMIT_KEYS) }
|
|
43
|
+
|
|
44
|
+
it "creates a map query" do
|
|
45
|
+
Marbu::Builder::Mongodb.map(mrf.map).should_not be_empty
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'creates the correct map query' do
|
|
49
|
+
Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.map(mrf.map)).should == MONGODB_MAP_FUNCTION_TWO_EMIT_KEYS_ONE_LINE
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Marbu::Models::Base do
|
|
4
|
+
context "a new Base instace" do
|
|
5
|
+
let(:base) { Marbu::Models::Base.new }
|
|
6
|
+
let(:modified_key_in_function) { 'value.key' }
|
|
7
|
+
|
|
8
|
+
it "can be added a key without a function" do
|
|
9
|
+
base.add_key('some_key')
|
|
10
|
+
|
|
11
|
+
base.keys.first.name.should == 'some_key'
|
|
12
|
+
base.keys.first.function.should == 'value.some_key'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "can be added an emit key with a function" do
|
|
16
|
+
base.add_key('some_key', 'some_function')
|
|
17
|
+
|
|
18
|
+
base.keys.size.should == 1
|
|
19
|
+
key = base.keys.first
|
|
20
|
+
key.name.should == 'some_key'
|
|
21
|
+
key.function.should == 'some_function'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# it "adds an emit_key with add_key(key)" do
|
|
25
|
+
# # base.add_key(@key)
|
|
26
|
+
# #
|
|
27
|
+
# # base.keys.size.should == 1
|
|
28
|
+
# # key = base.keys.first
|
|
29
|
+
# # key.name.should == @key
|
|
30
|
+
# # key.function.should == @modified_key_in_function
|
|
31
|
+
# end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Marbu::Models::MapReduceFinalize do
|
|
4
|
+
|
|
5
|
+
context "when instantiated with no params" do
|
|
6
|
+
let(:mrf) { Marbu::Models::MapReduceFinalize.new }
|
|
7
|
+
|
|
8
|
+
it "has a map" do
|
|
9
|
+
mrf.map.should be_an_instance_of(Marbu::Models::Map)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "has a reduce" do
|
|
13
|
+
mrf.reduce.should be_an_instance_of(Marbu::Models::Reduce)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "has a finalize" do
|
|
17
|
+
mrf.finalize.should be_an_instance_of(Marbu::Models::Finalize)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "when instantiated with a valid params hash" do
|
|
22
|
+
let(:mrf) { Marbu::Models::MapReduceFinalize.new(MR_WWB_LOC_DIM0) }
|
|
23
|
+
|
|
24
|
+
it "return the serializable hash" do
|
|
25
|
+
mrf.serializable_hash.should == MR_WWB_LOC_DIM0
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Marbu::Models::Map do
|
|
4
|
+
context "when instantiated with empty parameters" do
|
|
5
|
+
let(:map) do
|
|
6
|
+
Marbu::Models::Map.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should have no keys" do
|
|
10
|
+
map.keys.should be_empty
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should have no values" do
|
|
14
|
+
map.values.should be_empty
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should have no code" do
|
|
18
|
+
map.code.present?.should be_false
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Marbu::Models::Query do
|
|
4
|
+
context "a new Query instace" do
|
|
5
|
+
let(:query) { Marbu::Models::Query.new }
|
|
6
|
+
|
|
7
|
+
it "returns false for present?" do
|
|
8
|
+
query.present?.should be_false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "with at least one attribute set" do
|
|
12
|
+
it "returns true for present? with attribute condition set" do
|
|
13
|
+
query.condition = 'abc'
|
|
14
|
+
query.present?.should be_true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns true for present? with attribute datetime_fields set" do
|
|
18
|
+
query.datetime_fields = ['abc']
|
|
19
|
+
query.present?.should be_true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|