red_grape 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ext/array_ext.rb CHANGED
@@ -1,12 +1,18 @@
1
1
  class Array
2
+ attr_accessor :should_pass_through_whole #TODO
3
+
2
4
  def pass_through(pipe, context)
3
- loops = context.loops
4
- map! do |e|
5
+ if @should_pass_through_whole
6
+ super
7
+ else
8
+ loops = context.loops
9
+ map! do |e|
10
+ context.loops = loops
11
+ pipe.pass e, context
12
+ end
5
13
  context.loops = loops
6
- pipe.pass e, context
14
+ normalize_for_graph
7
15
  end
8
- context.loops = loops
9
- normalize_for_graph
10
16
  end
11
17
 
12
18
  def normalize_for_graph
@@ -61,6 +61,8 @@ module RedGrape
61
61
  context.resume_from_aggregating
62
62
  elsif context.grouping?
63
63
  context.resume_from_grouping
64
+ elsif context.gathering?
65
+ context.resume_from_gathering
64
66
  else
65
67
  val
66
68
  end
@@ -5,9 +5,9 @@ module RedGrape
5
5
  class CapPipe < Pipe::Base
6
6
  def pass(obj, context)
7
7
  ret = {}
8
- context.grouping_items.each do |e|
9
- ret[e.first] ||= 0
10
- ret[e.first] += 1
8
+ context.grouping_items.each do |k, v|
9
+ v = v.map &:first
10
+ ret[k] = self.pipe_eval(it:v, &self.prev.reduce_function)
11
11
  end
12
12
  ret
13
13
  end
@@ -9,7 +9,8 @@ module RedGrape
9
9
  @marks = {}
10
10
  @aggregating_items = {}
11
11
  @aggregated_items = {}
12
- @grouping_items = []
12
+ @grouping_items = {}
13
+ @gathering_items = []
13
14
  @loops = 1
14
15
  end
15
16
 
@@ -66,8 +67,8 @@ module RedGrape
66
67
  ret.normalize_for_graph
67
68
  end
68
69
 
69
- def group(val, next_pipe)
70
- @grouping_items << [val, next_pipe]
70
+ def group(next_pipe, key, val=key)
71
+ (@grouping_items[key] ||= []) << [val, next_pipe]
71
72
  val
72
73
  end
73
74
 
@@ -76,16 +77,42 @@ module RedGrape
76
77
  end
77
78
 
78
79
  def resume_from_grouping
79
- obj, pipe = *@grouping_items.first # TODO: '.first' is used to get next_pipe.
80
+ obj, pipe = *@grouping_items.values.first.first # TODO: '.first' is used to get next_pipe.
80
81
  if pipe
81
82
  push_history obj do |ctx|
82
- obj.pass_through(pipe, ctx)
83
+ obj.pass_through pipe, ctx
83
84
  end
84
85
  else
85
86
  obj
86
87
  end
87
88
  end
88
89
 
90
+ def gather(obj, next_pipe)
91
+ @gathering_items << [obj, next_pipe]
92
+ end
93
+
94
+ def gathering?
95
+ not @gathering_items.empty?
96
+ end
97
+
98
+ def clear_gathering
99
+ @gathering_items.clear
100
+ end
101
+
102
+ def resume_from_gathering
103
+ obj, pipe = *@gathering_items.first
104
+ objs = @gathering_items.map &:first
105
+ objs.should_pass_through_whole = true
106
+ if pipe
107
+ push_history objs do |ctx|
108
+ pipe.prev = objs
109
+ pipe.take ctx
110
+ end
111
+ else
112
+ objs
113
+ end
114
+ end
115
+
89
116
  def eval(args={}, &block)
90
117
  args.each {|k, v| self.send "#{k}=", v}
91
118
  instance_eval(&block)
@@ -0,0 +1,12 @@
1
+ require 'red_grape/pipe/base'
2
+
3
+ module RedGrape
4
+ module Pipe
5
+ class GatherPipe < Pipe::Base
6
+ def pass(obj, context)
7
+ context.gather obj, self.next
8
+ obj
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ require 'red_grape/pipe/base'
2
+
3
+ module RedGrape
4
+ module Pipe
5
+ class GroupByPipe < Pipe::Base
6
+ attr_accessor :reduce_function
7
+
8
+ def pass(obj, context)
9
+ key_function, value_function, @reduce_function = *self.opts
10
+ value_function ||= proc{it}
11
+ @reduce_function ||= proc{it}
12
+ if self.opts.empty?
13
+ context.group self.next, obj
14
+ elsif self.opts.first.is_a? Proc
15
+ context.group(
16
+ self.next,
17
+ pipe_eval(it:obj, &key_function),
18
+ pipe_eval(it:obj, &value_function)
19
+ )
20
+ else
21
+ self.opts.first[obj] ||= []
22
+ self.opts.first[obj] << obj
23
+ end
24
+ obj
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -3,13 +3,13 @@ require 'red_grape/pipe/base'
3
3
  module RedGrape
4
4
  module Pipe
5
5
  class GroupCountPipe < Pipe::Base
6
+ attr_accessor :reduce_function
6
7
  def pass(obj, context)
8
+ @reduce_function = proc{it.size}
7
9
  if self.opts.empty?
8
- #context.group({obj => 1}, self.next)
9
- context.group obj, self.next
10
+ context.group self.next, obj
10
11
  elsif self.opts.first.is_a? Proc
11
- #context.group({pipe_eval(it:obj, &self.opts.first) => 1}, self.next)
12
- context.group pipe_eval(it:obj, &self.opts.first), self.next
12
+ context.group self.next, pipe_eval(it:obj, &self.opts.first)
13
13
  else
14
14
  self.opts.first[obj] ||= 0
15
15
  self.opts.first[obj] += 1
@@ -0,0 +1,19 @@
1
+ require 'red_grape/pipe/base'
2
+
3
+ module RedGrape
4
+ module Pipe
5
+ class HasNotPipe < Pipe::Base
6
+ def pass(obj, context)
7
+ prop, val = *self.opts
8
+ filter = proc{it[prop] == val}
9
+
10
+ # TODO: same as filter_pipe (has_pipe)
11
+ unless context.eval :it => obj, &filter
12
+ pass_next context, obj
13
+ else
14
+ nil
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ require 'red_grape/pipe/base'
2
+
3
+ module RedGrape
4
+ module Pipe
5
+ class ScatterPipe < Pipe::Base
6
+ def pass(obj, context)
7
+ obj.should_pass_through_whole = false
8
+ context.clear_gathering
9
+ pass_next context, obj
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,8 +3,12 @@ require 'red_grape/pipe/base'
3
3
  module RedGrape
4
4
  module Pipe
5
5
  module Underscore
6
- def _(*opts)
7
- UnderscorePipe.new self.dup, *opts#
6
+ def _(*opts, &block)
7
+ if block
8
+ Proc.new &block
9
+ else
10
+ UnderscorePipe.new self.dup, *opts#
11
+ end
8
12
  end
9
13
  end
10
14
 
data/lib/red_grape.rb CHANGED
@@ -1,7 +1,10 @@
1
+ module RedGrape
2
+ VERSION = '0.0.10'
3
+ end
4
+
1
5
  require 'ext/nil_class_ext'
2
6
  require 'ext/object_ext'
3
7
  require 'ext/array_ext'
4
- require 'red_grape/version'
5
8
  require 'red_grape/pipe/aggregate_pipe'
6
9
  require 'red_grape/pipe/as_pipe'
7
10
  require 'red_grape/pipe/back_pipe'
@@ -11,6 +14,7 @@ require 'red_grape/pipe/except_pipe'
11
14
  require 'red_grape/pipe/exhaust_merge_pipe'
12
15
  require 'red_grape/pipe/fill_pipe'
13
16
  require 'red_grape/pipe/filter_pipe'
17
+ require 'red_grape/pipe/gather_pipe'
14
18
  require 'red_grape/pipe/group_by_pipe'
15
19
  require 'red_grape/pipe/group_count_pipe'
16
20
  require 'red_grape/pipe/has_pipe'
@@ -26,6 +30,7 @@ require 'red_grape/pipe/out_v_pipe'
26
30
  require 'red_grape/pipe/property_pipe'
27
31
  require 'red_grape/pipe/paths_pipe'
28
32
  require 'red_grape/pipe/retain_pipe'
33
+ require 'red_grape/pipe/scatter_pipe'
29
34
  require 'red_grape/pipe/side_effect_pipe'
30
35
  require 'red_grape/pipe/transform_pipe'
31
36
  require 'red_grape/pipe/v_pipe'
@@ -33,8 +38,6 @@ require 'red_grape/pipe/e_pipe'
33
38
  require 'red_grape/graph'
34
39
 
35
40
  module RedGrape
36
- VERSION = "0.0.9"
37
-
38
41
  module_function
39
42
  def set_auto_take(val=true)
40
43
  Pipe.set_auto_take val
@@ -117,17 +117,47 @@ class TraversalPatternsTest < Test::Unit::TestCase
117
117
  )
118
118
  end
119
119
 
120
+ # https://github.com/tinkerpop/gremlin/wiki/MapReduce-Pattern
120
121
  def test_map_reduce_pattern
121
122
  @g2 ||= RedGrape.load_graph 'data/graph-example-2.xml'
122
123
  assert_equal(
123
124
  {'cover'=>313, 'original'=>184},
124
125
  @g2.V.has_not('song_type', nil).group_count(proc{it.song_type}).cap.take
125
126
  )
126
- =begin
127
- assert_equal(
128
- {},
129
- @g2.V.has_not('song_type', nil).group_by(proc{it.song_type}, proc{it}).cap.take
130
- )
131
- =end
127
+
128
+ ret = @g2.V.has_not('song_type', nil).group_by(proc{it.song_type}, proc{it}).cap.take
129
+ assert_equal 2, ret.keys.size
130
+ assert_equal 313, ret.values[0].size
131
+ assert ret.values[0].all?{|e| e.is_a? RedGrape::Vertex}
132
+ assert_equal 184, ret.values[1].size
133
+ assert ret.values[1].all?{|e| e.is_a? RedGrape::Vertex}
134
+
135
+ ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it.name}).cap.take
136
+ assert_equal 2, ret.keys.size
137
+ assert_equal 313, ret.values[0].size
138
+ assert ret.values[0].all?{|e| e.is_a? String}
139
+ assert_equal 184, ret.values[1].size
140
+ assert ret.values[1].all?{|e| e.is_a? String}
141
+ assert_equal 'HEY BO DIDDLEY', ret.values[0][0]
142
+ assert_equal 'BERTHA', ret.values[1][0]
143
+
144
+ ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{1}).cap.take
145
+ assert_equal 2, ret.keys.size
146
+ assert ret.values[0].all?{|e| e == 1}
147
+ assert ret.values[1].all?{|e| e == 1}
148
+
149
+ ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{1}, _{it.size}).cap.take
150
+ assert_equal 313, ret.values[0]
151
+ assert_equal 184, ret.values[1]
152
+
153
+ ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it.out('sung_by').take}, _{it._.name.group_count.cap.take}).cap.take
154
+ assert_equal 66, ret[0]['cover']['Weir']
155
+ assert_equal 33, ret[0]['original']['Weir']
156
+ end
157
+
158
+ # https://github.com/tinkerpop/gremlin/wiki/Depth-First-vs.-Breadth-First
159
+ def test_depth_first_vs_bredth_first
160
+ assert_equal %w(1 4 6), @g1.v(1).out_e('created').in_v.in_e('created').out_v.take.map(&:id)
161
+ assert_equal %w(1 4 6), @g1.v(1).out_e('created').gather.scatter.in_v.gather.scatter.in_e('created').gather.scatter.out_v.gather.scatter.take.map(&:id)
132
162
  end
133
163
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: red_grape
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-15 00:00:00.000000000 Z
12
+ date: 2012-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &70205221723480 !ruby/object:Gem::Requirement
16
+ requirement: &70324009053140 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70205221723480
24
+ version_requirements: *70324009053140
25
25
  description: RedGrape is an in-memory graph database written in ruby. I made this
26
26
  in order to learn how graph databases work so that please do not use this for any
27
27
  serious purpose.
@@ -61,7 +61,10 @@ files:
61
61
  - lib/red_grape/pipe/exhaust_merge_pipe.rb
62
62
  - lib/red_grape/pipe/fill_pipe.rb
63
63
  - lib/red_grape/pipe/filter_pipe.rb
64
+ - lib/red_grape/pipe/gather_pipe.rb
65
+ - lib/red_grape/pipe/group_by_pipe.rb
64
66
  - lib/red_grape/pipe/group_count_pipe.rb
67
+ - lib/red_grape/pipe/has_not_pipe.rb
65
68
  - lib/red_grape/pipe/has_pipe.rb
66
69
  - lib/red_grape/pipe/if_then_else_pipe.rb
67
70
  - lib/red_grape/pipe/in_e_pipe.rb
@@ -74,6 +77,7 @@ files:
74
77
  - lib/red_grape/pipe/paths_pipe.rb
75
78
  - lib/red_grape/pipe/property_pipe.rb
76
79
  - lib/red_grape/pipe/retain_pipe.rb
80
+ - lib/red_grape/pipe/scatter_pipe.rb
77
81
  - lib/red_grape/pipe/side_effect_pipe.rb
78
82
  - lib/red_grape/pipe/transform_pipe.rb
79
83
  - lib/red_grape/pipe/underscore_pipe.rb
@@ -82,7 +86,6 @@ files:
82
86
  - lib/red_grape/serializer/graphml_serializer.rb
83
87
  - lib/red_grape/tools/graph_store.rb
84
88
  - lib/red_grape/tools/irg.rb
85
- - lib/red_grape/version.rb
86
89
  - lib/red_grape/vertex.rb
87
90
  - red_grape.gemspec
88
91
  - test/all.rb
@@ -1,3 +0,0 @@
1
- module RedGrape
2
- VERSION = "0.0.8"
3
- end