pacer 1.3.2-java → 1.3.3-java
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.
- checksums.yaml +4 -4
- data/ideas.rb +32 -0
- data/lib/pacer/blueprints/group_vertex.rb +59 -0
- data/lib/pacer/filter/limit_section_filter.rb +57 -0
- data/lib/pacer/filter/loop_filter.rb +60 -14
- data/lib/pacer/loader.rb +3 -2
- data/lib/pacer/route_builder.rb +3 -1
- data/lib/pacer/transform/intersect_sections.rb +83 -0
- data/lib/pacer/transform/join.rb +39 -166
- data/lib/pacer/transform/parallel.rb +17 -0
- data/lib/pacer/version.rb +1 -1
- data/lib/{pacer-1.3.2-standalone.jar → pacer-1.3.3-standalone.jar} +0 -0
- data/pom.xml +1 -1
- data/spec/support/graph_runner.rb +0 -45
- metadata +8 -7
- data/lib/pacer/blueprints/multi_graph.rb +0 -109
- data/lib/pacer/blueprints/ruby_graph.rb +0 -223
- data/spec/pacer/transform/join_spec.rb +0 -139
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7e0a5a234c35970d36d359c87ba463f288153b1
|
4
|
+
data.tar.gz: 8fc9db2381222ca87e44dea2c59b41b8c41cf552
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 188528a64f6d2cb85fa57176ac500e9f9dc68b9859dc9b9fe6853025d5ce2a73812401f696654f8b5f8e5748671594dfd950088a96587a0fa2b15d285e03263d
|
7
|
+
data.tar.gz: 84608cddad663f171a8ad886f2c1f68e65ec33b9bea94a1107ec39301a2816e6fd10f69f49994145c0671effd4379ffc9c7c59819e4fd416c89cc40e65ee189c
|
data/ideas.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
g.v.parallel(threads: 8, in_buffer: 4, out_buffer: 10) { |v| v.out.out.out.out.out }
|
2
|
+
|
3
|
+
# - eagerly consume (1) input and push into a channel
|
4
|
+
# - ChannelCapPipe
|
5
|
+
# - create a cap pipe that does this. The pipe's output is the channel
|
6
|
+
# - source data may be slow. Should probably not use a go block
|
7
|
+
# - 1 thread in a loop
|
8
|
+
# - Control the construction of parallel pipes. Default 2 threads, make
|
9
|
+
# it configurable.
|
10
|
+
# - standard copy split pipe can push the channel to subchannels
|
11
|
+
# - each parallel route pulls from the channel.
|
12
|
+
# - in a go block (waits will not block go thread pool)
|
13
|
+
# - ChannelReaderPipe
|
14
|
+
# - PathChannelReaderPipe
|
15
|
+
# - parallel routes are unmodified
|
16
|
+
# - cap each route - eagerly consume input and push into a channel
|
17
|
+
# - ChannelCapPipe again
|
18
|
+
# -
|
19
|
+
# - like ExhaustMergePipe + GatherPipe
|
20
|
+
# - use alts to read from any of the channels
|
21
|
+
# - ChannelAltsReaderPipe
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
# CCP
|
26
|
+
# CSP (parallelism is 1 thread per pipe being split into)
|
27
|
+
# CRP -> Work ... -> CCP
|
28
|
+
# CRP -> Work ... -> CCP
|
29
|
+
# ...
|
30
|
+
# EMP
|
31
|
+
# GP
|
32
|
+
# CARP
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Pacer
|
2
|
+
# Created without property support, though it could easily be added if it is ever needed.
|
3
|
+
class GroupVertex
|
4
|
+
import com.tinkerpop.blueprints.util.VerticesFromEdgesIterable
|
5
|
+
IN = com.tinkerpop.blueprints.Direction::IN
|
6
|
+
OUT = com.tinkerpop.blueprints.Direction::OUT
|
7
|
+
BOTH = com.tinkerpop.blueprints.Direction::BOTH
|
8
|
+
|
9
|
+
attr_reader :components, :key
|
10
|
+
attr_reader :paths, :wrapper, :graph
|
11
|
+
|
12
|
+
# Initialize it with an empty set to force uniqueness. Non-unique by default.
|
13
|
+
def initialize(key, graph, wrapper, components = nil)
|
14
|
+
@key = key
|
15
|
+
@wrapper = wrapper
|
16
|
+
if components
|
17
|
+
@components = components
|
18
|
+
else
|
19
|
+
@components = []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_component(vertex)
|
24
|
+
components << vertex
|
25
|
+
end
|
26
|
+
|
27
|
+
include com.tinkerpop.blueprints.Element
|
28
|
+
|
29
|
+
def getId
|
30
|
+
"#{ key }:#{ components.count }"
|
31
|
+
end
|
32
|
+
|
33
|
+
def getPropertyKeys
|
34
|
+
Set[]
|
35
|
+
end
|
36
|
+
|
37
|
+
def getProperty(key)
|
38
|
+
case key
|
39
|
+
when 'components' then components.map { |c| wrapper.new graph, c }
|
40
|
+
when 'key' then key
|
41
|
+
when 'count' then components.count
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
include com.tinkerpop.blueprints.Vertex
|
46
|
+
|
47
|
+
def getRawVertex
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def getVertices(direction, *labels)
|
52
|
+
VerticesFromEdgesIterable.new self, direction, *labels
|
53
|
+
end
|
54
|
+
|
55
|
+
def getEdges(direction, *labels)
|
56
|
+
Pacer::Pipes::MultiPipe.new components.map { |v| v.getEdges(direction, *labels) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def limit_section(section = nil, max)
|
5
|
+
chain_route filter: Pacer::Filter::LimitSectionFilter, section_max: max, section: section
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Filter
|
11
|
+
module LimitSectionFilter
|
12
|
+
# VisitsSection module provides:
|
13
|
+
# section=
|
14
|
+
# section_visitor
|
15
|
+
include Pacer::Visitors::VisitsSection
|
16
|
+
|
17
|
+
attr_accessor :section_max
|
18
|
+
|
19
|
+
def attach_pipe(end_pipe)
|
20
|
+
pipe = LimitSectionPipe.new(self, section_visitor, section_max)
|
21
|
+
pipe.setStarts end_pipe if end_pipe
|
22
|
+
pipe
|
23
|
+
end
|
24
|
+
|
25
|
+
class LimitSectionPipe < Pacer::Pipes::RubyPipe
|
26
|
+
attr_reader :max, :section, :route
|
27
|
+
attr_accessor :hits
|
28
|
+
|
29
|
+
|
30
|
+
def initialize(route, section, max)
|
31
|
+
super()
|
32
|
+
@hits = 0
|
33
|
+
@max = max
|
34
|
+
@section = section
|
35
|
+
@route = route
|
36
|
+
section.visitor = self if section
|
37
|
+
end
|
38
|
+
|
39
|
+
def processNextStart
|
40
|
+
while hits == max
|
41
|
+
starts.next
|
42
|
+
end
|
43
|
+
self.hits += 1
|
44
|
+
starts.next
|
45
|
+
end
|
46
|
+
|
47
|
+
def after_element
|
48
|
+
self.hits = 0
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset
|
52
|
+
self.hits = 0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Pacer
|
2
2
|
module Routes
|
3
3
|
module RouteOperations
|
4
|
-
def loop(&block)
|
5
|
-
chain_route :filter => :loop, :looping_route => block
|
4
|
+
def loop(opts = {}, &block)
|
5
|
+
chain_route(opts.merge :filter => :loop, :looping_route => block)
|
6
6
|
end
|
7
7
|
|
8
|
-
def all(&block)
|
9
|
-
loop(&block).while do |e, depth|
|
8
|
+
def all(opts = {}, &block)
|
9
|
+
loop(opts, &block).while do |e, depth|
|
10
10
|
if depth == 0
|
11
11
|
:loop
|
12
12
|
else
|
@@ -60,6 +60,7 @@ module Pacer
|
|
60
60
|
module LoopFilter
|
61
61
|
attr_reader :looping_route
|
62
62
|
attr_accessor :while_description
|
63
|
+
attr_reader :reverse_loop_route, :reverse_emit_route
|
63
64
|
|
64
65
|
def help(section = nil)
|
65
66
|
case section
|
@@ -162,15 +163,42 @@ HELP
|
|
162
163
|
# this could have concurrency problems if multiple instances of the same
|
163
164
|
# route
|
164
165
|
def deepest!
|
165
|
-
@
|
166
|
+
@loop_when_route = @looping_route
|
167
|
+
@reverse_loop_route = false
|
168
|
+
@emit_when_route = @looping_route
|
169
|
+
@reverse_emit_route = true
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
def loop_when(&block)
|
174
|
+
@loop_when_route = Pacer::Route.block_branch(self, block)
|
175
|
+
@reverse_loop_route = false
|
176
|
+
self
|
177
|
+
end
|
178
|
+
|
179
|
+
def loop_when_not(&block)
|
180
|
+
@loop_when_route = Pacer::Route.block_branch(self, block)
|
181
|
+
@reverse_loop_route = true
|
182
|
+
self
|
183
|
+
end
|
184
|
+
|
185
|
+
def emit_when(&block)
|
186
|
+
@emit_when_route = Pacer::Route.block_branch(self, block)
|
187
|
+
@reverse_emit_route = false
|
188
|
+
self
|
189
|
+
end
|
190
|
+
|
191
|
+
def emit_when_not(&block)
|
192
|
+
@emit_when_route = Pacer::Route.block_branch(self, block)
|
193
|
+
@reverse_emit_route = true
|
166
194
|
self
|
167
195
|
end
|
168
196
|
|
169
197
|
protected
|
170
198
|
|
171
199
|
def attach_pipe(end_pipe)
|
172
|
-
if @
|
173
|
-
control_block =
|
200
|
+
if @loop_when_route or @emit_when_route
|
201
|
+
control_block = route_control_block
|
174
202
|
elsif @control_block
|
175
203
|
control_block = @control_block
|
176
204
|
else
|
@@ -181,19 +209,37 @@ HELP
|
|
181
209
|
pipe
|
182
210
|
end
|
183
211
|
|
184
|
-
def
|
212
|
+
def expandable(route = nil)
|
185
213
|
expando = Pacer::Pipes::ExpandablePipe.new
|
186
214
|
empty = java.util.ArrayList.new
|
187
215
|
expando.setStarts empty.iterator
|
188
|
-
|
216
|
+
if route
|
217
|
+
control_pipe = Pacer::Route.pipeline route
|
218
|
+
else
|
219
|
+
control_pipe = Pacer::Pipes::IdentityPipe.new
|
220
|
+
end
|
189
221
|
control_pipe.setStarts expando
|
222
|
+
[expando, control_pipe]
|
223
|
+
end
|
224
|
+
|
225
|
+
def route_control_block
|
226
|
+
loop_expando, loop_pipe = expandable @loop_when_route
|
227
|
+
emit_expando, emit_pipe = expandable @emit_when_route
|
190
228
|
proc do |el, depth|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
229
|
+
loop_pipe.reset
|
230
|
+
loop_expando.add el.element
|
231
|
+
emit_pipe.reset
|
232
|
+
emit_expando.add el.element
|
233
|
+
if loop_pipe.hasNext ^ reverse_loop_route
|
234
|
+
if emit_pipe.hasNext ^ reverse_emit_route
|
235
|
+
:loop_and_emit
|
236
|
+
else
|
237
|
+
:loop
|
238
|
+
end
|
195
239
|
elsif depth > 0
|
196
|
-
|
240
|
+
if emit_pipe.hasNext ^ reverse_emit_route
|
241
|
+
:emit
|
242
|
+
end
|
197
243
|
end
|
198
244
|
end
|
199
245
|
end
|
data/lib/pacer/loader.rb
CHANGED
@@ -49,8 +49,7 @@ require 'pacer/function_resolver'
|
|
49
49
|
require 'pacer/route'
|
50
50
|
|
51
51
|
require 'pacer/blueprints/tg'
|
52
|
-
require 'pacer/blueprints/
|
53
|
-
require 'pacer/blueprints/multi_graph'
|
52
|
+
require 'pacer/blueprints/group_vertex'
|
54
53
|
|
55
54
|
require 'pacer/blueprints/payload_elements'
|
56
55
|
|
@@ -79,6 +78,7 @@ require 'pacer/filter/loop_filter'
|
|
79
78
|
require 'pacer/filter/block_filter'
|
80
79
|
require 'pacer/filter/object_filter'
|
81
80
|
require 'pacer/filter/random_filter'
|
81
|
+
require 'pacer/filter/limit_section_filter'
|
82
82
|
|
83
83
|
require 'pacer/transform/branch'
|
84
84
|
require 'pacer/transform/cap'
|
@@ -97,6 +97,7 @@ require 'pacer/transform/wrapped_path'
|
|
97
97
|
require 'pacer/transform/scatter'
|
98
98
|
require 'pacer/transform/has_count_cap'
|
99
99
|
require 'pacer/transform/sort_section'
|
100
|
+
require 'pacer/transform/intersect_sections'
|
100
101
|
require 'pacer/transform/payload'
|
101
102
|
require 'pacer/transform/lookup_ids'
|
102
103
|
|
data/lib/pacer/route_builder.rb
CHANGED
@@ -42,6 +42,7 @@ module Pacer
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def type_def(source, args)
|
45
|
+
source = args.fetch(:based_on, source)
|
45
46
|
[
|
46
47
|
type_modules(source, args),
|
47
48
|
function_modules(source, args),
|
@@ -51,6 +52,7 @@ module Pacer
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def configuration(source, args)
|
55
|
+
source = args.fetch(:based_on, source)
|
54
56
|
{
|
55
57
|
element_type: element_type(source, args),
|
56
58
|
graph: graph(source, args),
|
@@ -62,7 +64,7 @@ module Pacer
|
|
62
64
|
|
63
65
|
def arguments(source, args)
|
64
66
|
args.reject do |key, val|
|
65
|
-
Set[:element_type, :wrapper, :extensions, :modules, :graph, :back, :filter, :side_effect, :transform, :visitor].include? key
|
67
|
+
Set[:element_type, :wrapper, :extensions, :modules, :graph, :back, :filter, :side_effect, :transform, :visitor, :based_on].include? key
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def intersect_sections(section)
|
5
|
+
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :intersection
|
6
|
+
end
|
7
|
+
|
8
|
+
def difference_sections(section)
|
9
|
+
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :difference
|
10
|
+
end
|
11
|
+
|
12
|
+
def left_difference_sections(section)
|
13
|
+
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :left_difference
|
14
|
+
end
|
15
|
+
|
16
|
+
def right_difference_sections(section)
|
17
|
+
chain_route transform: Pacer::Transform::IntersectSections, section: section, operation: :right_difference
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
module Transform
|
24
|
+
module IntersectSections
|
25
|
+
# VisitsSection module provides:
|
26
|
+
# section=
|
27
|
+
# section_visitor
|
28
|
+
include Pacer::Visitors::VisitsSection
|
29
|
+
|
30
|
+
attr_accessor :operation
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def attach_pipe(end_pipe)
|
35
|
+
pipe = IntersectSectionPipe.new(section_visitor, operation)
|
36
|
+
pipe.setStarts end_pipe if end_pipe
|
37
|
+
pipe
|
38
|
+
end
|
39
|
+
|
40
|
+
class IntersectSectionPipe < Pacer::Pipes::RubyPipe
|
41
|
+
attr_reader :section, :reduce_block
|
42
|
+
attr_accessor :to_emit, :current_set, :all_sets
|
43
|
+
|
44
|
+
def initialize(section, operation)
|
45
|
+
super()
|
46
|
+
@section = section
|
47
|
+
case operation
|
48
|
+
when :difference
|
49
|
+
@reduce_block = proc { |a, b| (a - b) + (b - a) }
|
50
|
+
when :left_difference
|
51
|
+
@reduce_block = proc { |a, b| a - b }
|
52
|
+
when :right_difference
|
53
|
+
@reduce_block = proc { |a, b| b - a }
|
54
|
+
when :intersection
|
55
|
+
@reduce_block = proc { |a, b| a.intersection b }
|
56
|
+
end
|
57
|
+
self.all_sets = []
|
58
|
+
if section
|
59
|
+
section.visitor = self
|
60
|
+
else
|
61
|
+
on_element nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def processNextStart
|
66
|
+
unless to_emit
|
67
|
+
while starts.hasNext
|
68
|
+
current_set << starts.next
|
69
|
+
end
|
70
|
+
self.to_emit = all_sets.reduce(&reduce_block).to_a
|
71
|
+
end
|
72
|
+
raise EmptyPipe.instance if to_emit.empty?
|
73
|
+
to_emit.shift
|
74
|
+
end
|
75
|
+
|
76
|
+
def on_element(x)
|
77
|
+
self.current_set = Set[]
|
78
|
+
all_sets << current_set
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/pacer/transform/join.rb
CHANGED
@@ -1,197 +1,70 @@
|
|
1
1
|
module Pacer
|
2
2
|
module Routes
|
3
3
|
module RouteOperations
|
4
|
-
def
|
5
|
-
|
4
|
+
def join(&block)
|
5
|
+
chain_route transform: Pacer::Transform::Join, block: block
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
:transform => :join,
|
11
|
-
element_type: :vertex,
|
12
|
-
graph: options.fetch(:multi_graph, Pacer::MultiGraph.blank),
|
13
|
-
from_graph: graph
|
14
|
-
}
|
15
|
-
args[:multi_graph] = options[:multi_graph] if options[:multi_graph]
|
16
|
-
route = chain_route(args)
|
17
|
-
route = route.key { |v| v } unless name == :key
|
18
|
-
if block and name == :key
|
19
|
-
route.key &block
|
20
|
-
elsif block
|
21
|
-
route.join(name || :values, &block)
|
22
|
-
else
|
23
|
-
route
|
24
|
-
end
|
8
|
+
def unjoin
|
9
|
+
map { |g| g[:components] }.scatter extensions: extensions, graph: graph, element_type: element_type
|
25
10
|
end
|
26
11
|
end
|
27
12
|
end
|
28
13
|
|
29
|
-
|
30
14
|
module Transform
|
31
15
|
module Join
|
32
|
-
|
33
|
-
import com.tinkerpop.pipes.sideeffect.SideEffectPipe
|
34
|
-
import java.util.ArrayList
|
35
|
-
import java.util.LinkedList
|
16
|
+
attr_reader :key_block, :unique
|
36
17
|
|
37
|
-
|
18
|
+
def block=(block)
|
19
|
+
@key_block = block
|
20
|
+
end
|
38
21
|
|
39
|
-
|
40
|
-
|
22
|
+
def uniq
|
23
|
+
@unique = true
|
24
|
+
self
|
25
|
+
end
|
41
26
|
|
42
|
-
|
43
|
-
super()
|
44
|
-
@from_graph = from_graph
|
45
|
-
@wrapper = Pacer::Wrappers::WrapperSelector.build from_graph
|
46
|
-
@multi_graph = multi_graph || Pacer::MultiGraph.blank
|
47
|
-
@values_pipes = []
|
48
|
-
@current_keys = []
|
49
|
-
@current_values = []
|
50
|
-
end
|
27
|
+
protected
|
51
28
|
|
52
|
-
|
53
|
-
|
54
|
-
|
29
|
+
def attach_pipe(end_pipe)
|
30
|
+
pipe = JoinPipe.new(self, key_block, unique)
|
31
|
+
pipe.setStarts end_pipe if end_pipe
|
32
|
+
pipe
|
33
|
+
end
|
55
34
|
|
56
|
-
|
57
|
-
|
58
|
-
|
35
|
+
class JoinPipe < Pacer::Pipes::RubyPipe
|
36
|
+
attr_reader :block, :groups, :unique
|
37
|
+
attr_accessor:to_emit
|
59
38
|
|
60
|
-
def
|
61
|
-
|
39
|
+
def initialize(back, key_block, unique)
|
40
|
+
super()
|
41
|
+
@unique = unique
|
42
|
+
@block = Pacer::Wrappers::WrappingPipeFunction.new back, key_block
|
62
43
|
end
|
63
44
|
|
64
|
-
protected
|
65
|
-
|
66
45
|
def processNextStart
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
key = current_keys.removeFirst
|
74
|
-
if key
|
75
|
-
combined = multi_graph.vertex(key) || multi_graph.create_vertex(key)
|
76
|
-
else
|
77
|
-
combined = multi_graph.create_vertex
|
78
|
-
end
|
79
|
-
combined.join_on join_on if join_on
|
80
|
-
combined[:key] = key
|
81
|
-
current_values.each do |key, values|
|
82
|
-
combined.element.append_property_array key, values
|
83
|
-
end
|
84
|
-
return combined
|
46
|
+
unless to_emit
|
47
|
+
coll = unique ? Set : Array
|
48
|
+
groups = Hash.new { |h, k| h[k] = Pacer::GroupVertex.new k, block.graph, block.wrapper, coll.new }
|
49
|
+
while starts.hasNext
|
50
|
+
el = starts.next
|
51
|
+
groups[block.call(el)].add_component el
|
85
52
|
end
|
53
|
+
self.to_emit = groups.values
|
86
54
|
end
|
87
|
-
|
88
|
-
|
89
|
-
def get_keys(element)
|
90
|
-
array = LinkedList.new
|
91
|
-
if key_expando
|
92
|
-
array.addAll next_results(key_expando, key_end, element)
|
55
|
+
if to_emit.empty?
|
56
|
+
raise Pacer::Pipes::EmptyPipe.instance
|
93
57
|
else
|
94
|
-
|
95
|
-
end
|
96
|
-
array
|
97
|
-
end
|
98
|
-
|
99
|
-
def get_values(element)
|
100
|
-
values_pipes.map do |name, expando, to_pipe|
|
101
|
-
[name, next_results(expando, to_pipe, element)]
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# doesn't need to be spun out because it's a capped aggregator
|
106
|
-
def next_results(expando, pipe, element)
|
107
|
-
pipe.reset
|
108
|
-
expando.add element, ArrayList.new, nil
|
109
|
-
array = pipe.next
|
110
|
-
array.map do |element|
|
111
|
-
if element.is_a? Pacer::Element
|
112
|
-
wrapper.new from_graph, element
|
113
|
-
else
|
114
|
-
element
|
115
|
-
end
|
58
|
+
to_emit.shift
|
116
59
|
end
|
117
60
|
end
|
118
61
|
|
119
|
-
def
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
agg_pipe = com.tinkerpop.pipes.sideeffect.AggregatePipe.new LinkedList.new
|
124
|
-
cap_pipe = com.tinkerpop.pipes.transform.SideEffectCapPipe.new agg_pipe
|
125
|
-
agg_pipe.setStarts to_pipe
|
126
|
-
cap_pipe.setStarts to_pipe
|
127
|
-
[expando, cap_pipe]
|
62
|
+
def reset
|
63
|
+
super
|
64
|
+
self.loaded = false
|
65
|
+
self.to_emit = nil
|
128
66
|
end
|
129
67
|
end
|
130
|
-
|
131
|
-
include Pacer::Core::SideEffect
|
132
|
-
|
133
|
-
attr_accessor :existing_multi_graph, :key_route, :values_routes, :from_graph
|
134
|
-
attr_writer :join_on
|
135
|
-
|
136
|
-
# FIXME: the pipe changes the graph. This does not fit with the idea of immutable routes.
|
137
|
-
def graph
|
138
|
-
@graph or super
|
139
|
-
end
|
140
|
-
|
141
|
-
def run!
|
142
|
-
super
|
143
|
-
@graph
|
144
|
-
end
|
145
|
-
|
146
|
-
def graph=(g)
|
147
|
-
@graph = g
|
148
|
-
end
|
149
|
-
|
150
|
-
def key(&block)
|
151
|
-
self.key_route = Pacer::Route.block_branch(self, block)
|
152
|
-
self
|
153
|
-
end
|
154
|
-
|
155
|
-
def join(name = nil, &block)
|
156
|
-
self.key_route = nil if name == :key
|
157
|
-
if block
|
158
|
-
values_routes << [(name || :values), Pacer::Route.block_branch(self, block)]
|
159
|
-
else
|
160
|
-
values_routes << [(name || :values), Pacer::Route.block_branch(self, proc { |v| v })]
|
161
|
-
end
|
162
|
-
self
|
163
|
-
end
|
164
|
-
|
165
|
-
def join_on(*keys)
|
166
|
-
@join_on = keys
|
167
|
-
self
|
168
|
-
end
|
169
|
-
|
170
|
-
def multigraph
|
171
|
-
cap.first
|
172
|
-
end
|
173
|
-
|
174
|
-
protected
|
175
|
-
|
176
|
-
def after_initialize
|
177
|
-
@values_routes = []
|
178
|
-
end
|
179
|
-
|
180
|
-
def attach_pipe(end_pipe)
|
181
|
-
pipe = CombinePipe.new(from_graph, existing_multi_graph)
|
182
|
-
self.graph = pipe.multi_graph
|
183
|
-
pipe.setKeyPipe *key_route.send(:build_pipeline) if key_route
|
184
|
-
pipe.join_on = @join_on
|
185
|
-
values_routes.each do |name, route|
|
186
|
-
pipe.addValuesPipe name, *route.send(:build_pipeline)
|
187
|
-
end
|
188
|
-
pipe.setStarts end_pipe if end_pipe
|
189
|
-
pipe
|
190
|
-
end
|
191
|
-
|
192
|
-
def inspect_string
|
193
|
-
"#{ inspect_class_name }(#{ key_route.inspect }: #{ Hash[values_routes].inspect })"
|
194
|
-
end
|
195
68
|
end
|
196
69
|
end
|
197
70
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Pacer
|
2
|
+
module Routes
|
3
|
+
module RouteOperations
|
4
|
+
def parallel(opts = {}, &block)
|
5
|
+
threads = opts.fetch(:threads, 2)
|
6
|
+
branched = (0..threads).reduce(channel_cap buffer: opts.fetch(:in_buffer, threads)) do |r, n|
|
7
|
+
r.branch do |x|
|
8
|
+
b = block.call x.channel_reader
|
9
|
+
b.channel_cap
|
10
|
+
end
|
11
|
+
end
|
12
|
+
branched.merge_exhaustive.gather.channel_fan_in(buffer: opts.fetch(:out_buffer, threads),
|
13
|
+
based_on: block.call(self))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/pacer/version.rb
CHANGED
Binary file
|
data/pom.xml
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
<!-- NOTE: the following properties are automatically updated based on the values in lib/pacer-neo4j/version.rb -->
|
9
9
|
<properties>
|
10
10
|
<blueprints.version>2.3.0</blueprints.version>
|
11
|
-
<gem.version>1.3.
|
11
|
+
<gem.version>1.3.3</gem.version>
|
12
12
|
<pipes.version>2.3.0</pipes.version>
|
13
13
|
<gremlin.version>2.3.0</gremlin.version>
|
14
14
|
</properties>
|
@@ -45,53 +45,8 @@ class RSpec::GraphRunner
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
module RubyGraph
|
49
|
-
def all(usage_style = :read_write, indices = true, &block)
|
50
|
-
super
|
51
|
-
rg(usage_style, indices, &block)
|
52
|
-
end
|
53
|
-
|
54
|
-
def rg(usage_style = :read_write, indices = true, &block)
|
55
|
-
for_graph('rg', usage_style, indices, false, ruby_graph, ruby_graph2, nil, block)
|
56
|
-
end
|
57
|
-
|
58
|
-
protected
|
59
|
-
|
60
|
-
def ruby_graph
|
61
|
-
Pacer::PacerGraph.new Pacer::SimpleEncoder, proc { Pacer::RubyGraph.new }
|
62
|
-
end
|
63
|
-
|
64
|
-
def ruby_graph2
|
65
|
-
Pacer::PacerGraph.new Pacer::SimpleEncoder, proc { Pacer::RubyGraph.new }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
module MultiGraph
|
70
|
-
def all(usage_style = :read_write, indices = true, &block)
|
71
|
-
super
|
72
|
-
multigraph(usage_style, indices, &block)
|
73
|
-
end
|
74
|
-
|
75
|
-
def multigraph(usage_style = :read_write, indices = true, &block)
|
76
|
-
for_graph('multigraph', usage_style, indices, false, multi_graph, multi_graph2, nil, block)
|
77
|
-
end
|
78
|
-
|
79
|
-
protected
|
80
|
-
|
81
|
-
def multi_graph
|
82
|
-
Pacer::MultiGraph.blank
|
83
|
-
end
|
84
|
-
|
85
|
-
def multi_graph2
|
86
|
-
Pacer::MultiGraph.blank
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
48
|
include Stubs
|
92
49
|
include Tg
|
93
|
-
#include RubyGraph
|
94
|
-
#include MultiGraph
|
95
50
|
include Neo4j if defined? Neo4j
|
96
51
|
include Dex if defined? Dex
|
97
52
|
include Orient if defined? Orient
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pacer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Darrick Wiebe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Pacer defines routes through a graph and then traverses them very quickly.
|
14
14
|
email: darrick@innatesoftware.com
|
@@ -34,10 +34,10 @@ files:
|
|
34
34
|
- bin/yard
|
35
35
|
- bin/yardoc
|
36
36
|
- blog/2012-09-18-pacer-1.0.md
|
37
|
+
- ideas.rb
|
37
38
|
- lib/pacer.rb
|
38
|
-
- lib/pacer/blueprints/
|
39
|
+
- lib/pacer/blueprints/group_vertex.rb
|
39
40
|
- lib/pacer/blueprints/payload_elements.rb
|
40
|
-
- lib/pacer/blueprints/ruby_graph.rb
|
41
41
|
- lib/pacer/blueprints/tg.rb
|
42
42
|
- lib/pacer/core/array_route.rb
|
43
43
|
- lib/pacer/core/graph.rb
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- lib/pacer/filter/empty_filter.rb
|
59
59
|
- lib/pacer/filter/future_filter.rb
|
60
60
|
- lib/pacer/filter/index_filter.rb
|
61
|
+
- lib/pacer/filter/limit_section_filter.rb
|
61
62
|
- lib/pacer/filter/loop_filter.rb
|
62
63
|
- lib/pacer/filter/object_filter.rb
|
63
64
|
- lib/pacer/filter/property_filter.rb
|
@@ -129,10 +130,12 @@ files:
|
|
129
130
|
- lib/pacer/transform/flat_map.rb
|
130
131
|
- lib/pacer/transform/gather.rb
|
131
132
|
- lib/pacer/transform/has_count_cap.rb
|
133
|
+
- lib/pacer/transform/intersect_sections.rb
|
132
134
|
- lib/pacer/transform/join.rb
|
133
135
|
- lib/pacer/transform/lookup_ids.rb
|
134
136
|
- lib/pacer/transform/make_pairs.rb
|
135
137
|
- lib/pacer/transform/map.rb
|
138
|
+
- lib/pacer/transform/parallel.rb
|
136
139
|
- lib/pacer/transform/path.rb
|
137
140
|
- lib/pacer/transform/path_tree.rb
|
138
141
|
- lib/pacer/transform/payload.rb
|
@@ -200,7 +203,6 @@ files:
|
|
200
203
|
- spec/pacer/side_effect/is_unique_spec.rb
|
201
204
|
- spec/pacer/support/array_list_spec.rb
|
202
205
|
- spec/pacer/support/enumerable_spec.rb
|
203
|
-
- spec/pacer/transform/join_spec.rb
|
204
206
|
- spec/pacer/transform/map_spec.rb
|
205
207
|
- spec/pacer/transform/path_spec.rb
|
206
208
|
- spec/pacer/transform/path_tree_spec.rb
|
@@ -218,7 +220,7 @@ files:
|
|
218
220
|
- spec/support/use_transactions.rb
|
219
221
|
- spec/tackle/simple_mixin.rb
|
220
222
|
- spec/tackle/tinkerpop_graph_mixins.rb
|
221
|
-
- lib/pacer-1.3.
|
223
|
+
- lib/pacer-1.3.3-standalone.jar
|
222
224
|
homepage: http://github.com/pangloss/pacer
|
223
225
|
licenses:
|
224
226
|
- MIT
|
@@ -280,7 +282,6 @@ test_files:
|
|
280
282
|
- spec/pacer/side_effect/is_unique_spec.rb
|
281
283
|
- spec/pacer/support/array_list_spec.rb
|
282
284
|
- spec/pacer/support/enumerable_spec.rb
|
283
|
-
- spec/pacer/transform/join_spec.rb
|
284
285
|
- spec/pacer/transform/map_spec.rb
|
285
286
|
- spec/pacer/transform/path_spec.rb
|
286
287
|
- spec/pacer/transform/path_tree_spec.rb
|
@@ -1,109 +0,0 @@
|
|
1
|
-
module Pacer
|
2
|
-
class MultiGraph < RubyGraph
|
3
|
-
def self.blank
|
4
|
-
PacerGraph.new SimpleEncoder, proc { MultiGraph.new }
|
5
|
-
end
|
6
|
-
|
7
|
-
protected
|
8
|
-
|
9
|
-
def vertex_class
|
10
|
-
MultiVertex
|
11
|
-
end
|
12
|
-
|
13
|
-
def edge_class
|
14
|
-
RubyEdge
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
class MultiVertex < RubyVertex
|
20
|
-
import com.tinkerpop.pipes.util.iterators.MultiIterator
|
21
|
-
|
22
|
-
def initialize(*args)
|
23
|
-
super
|
24
|
-
@vertex_keys = Set[]
|
25
|
-
@join_keys = @vertex_keys
|
26
|
-
end
|
27
|
-
|
28
|
-
attr_accessor :vertex_keys, :join_keys
|
29
|
-
|
30
|
-
def join_on(keys)
|
31
|
-
if keys.is_a? Enumerable
|
32
|
-
@join_keys = keys.map { |k| k.to_s }.to_set
|
33
|
-
elsif keys
|
34
|
-
@join_keys = Set[keys.to_s]
|
35
|
-
else
|
36
|
-
@join_keys = Set[]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def vertices
|
41
|
-
join_keys.flat_map do |key|
|
42
|
-
@properties[key]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def setProperty(key, value)
|
47
|
-
case value
|
48
|
-
when Pacer::Vertex
|
49
|
-
vertex_keys << key.to_s
|
50
|
-
super
|
51
|
-
when Hash
|
52
|
-
vertex_keys.delete key.to_s
|
53
|
-
super
|
54
|
-
when Enumerable
|
55
|
-
values = value.to_a
|
56
|
-
if values.any? and values.all? { |v| v.is_a? Pacer::Vertex }
|
57
|
-
vertex_keys << key.to_s
|
58
|
-
end
|
59
|
-
super(key, values)
|
60
|
-
else
|
61
|
-
vertex_keys.delete key.to_s
|
62
|
-
super
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def append_property_array(key, value)
|
67
|
-
values = value.to_a
|
68
|
-
existing_values = getProperty(key)
|
69
|
-
if existing_values
|
70
|
-
if vertex_keys.include? key and not values.all? { |v| v.is_a? Pacer::Vertex }
|
71
|
-
vertex_keys.delete key.to_s
|
72
|
-
end
|
73
|
-
raise "Can't append to key #{ key } because it is not an Array" unless existing_values.is_a? Array
|
74
|
-
else
|
75
|
-
existing_values = []
|
76
|
-
setProperty(key, existing_values)
|
77
|
-
vertex_keys << key.to_s if values.all? { |v| v.is_a? Pacer::Vertex }
|
78
|
-
end
|
79
|
-
existing_values.concat values
|
80
|
-
end
|
81
|
-
|
82
|
-
def removeProperty(key)
|
83
|
-
vertex_keys.delete key.to_s
|
84
|
-
super
|
85
|
-
end
|
86
|
-
|
87
|
-
def getEdges(direction, *labels)
|
88
|
-
vs = vertices
|
89
|
-
if vs.any?
|
90
|
-
labels = extract_varargs_strings(labels)
|
91
|
-
p = Pacer::Pipes::IdentityPipe.new
|
92
|
-
p.setStarts(MultiIterator.new super, *vs.map { |v| v.getEdges(direction, *labels).iterator })
|
93
|
-
p
|
94
|
-
else
|
95
|
-
super
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def inspect
|
100
|
-
s = super
|
101
|
-
s[2] = 'M'
|
102
|
-
s
|
103
|
-
end
|
104
|
-
|
105
|
-
def to_s
|
106
|
-
"m[#{ element_id }]"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
@@ -1,223 +0,0 @@
|
|
1
|
-
module Pacer
|
2
|
-
class RubyGraph
|
3
|
-
import com.tinkerpop.blueprints.Element
|
4
|
-
import com.tinkerpop.blueprints.Graph
|
5
|
-
import com.tinkerpop.blueprints.Features
|
6
|
-
|
7
|
-
include Graph
|
8
|
-
|
9
|
-
FEATURES = Features.new.tap do |features|
|
10
|
-
features.supportsDuplicateEdges = true
|
11
|
-
features.supportsSelfLoops = true
|
12
|
-
features.supportsSerializableObjectProperty = true
|
13
|
-
features.supportsBooleanProperty = true
|
14
|
-
features.supportsDoubleProperty = true
|
15
|
-
features.supportsFloatProperty = true
|
16
|
-
features.supportsIntegerProperty = true
|
17
|
-
features.supportsPrimitiveArrayProperty = true
|
18
|
-
features.supportsUniformListProperty = true
|
19
|
-
features.supportsMixedListProperty = true
|
20
|
-
features.supportsLongProperty = true
|
21
|
-
features.supportsMapProperty = true
|
22
|
-
features.supportsStringProperty = true
|
23
|
-
|
24
|
-
features.ignoresSuppliedIds = false
|
25
|
-
features.isPersistent = false
|
26
|
-
features.isWrapper = false
|
27
|
-
|
28
|
-
features.supportsIndices = false
|
29
|
-
features.supportsKeyIndices = false
|
30
|
-
features.supportsVertexKeyIndex = false
|
31
|
-
features.supportsEdgeKeyIndex = false
|
32
|
-
features.supportsVertexIndex = false
|
33
|
-
features.supportsEdgeIndex = false
|
34
|
-
features.supportsTransactions = false
|
35
|
-
features.supportsVertexIteration = true
|
36
|
-
features.supportsEdgeIteration = true
|
37
|
-
features.supportsEdgeRetrieval = true
|
38
|
-
features.supportsVertexProperties = true
|
39
|
-
features.supportsEdgeProperties = true
|
40
|
-
features.supportsThreadedTransactions = false
|
41
|
-
end
|
42
|
-
|
43
|
-
def initialize
|
44
|
-
clear
|
45
|
-
end
|
46
|
-
|
47
|
-
def addVertex(id)
|
48
|
-
if id
|
49
|
-
v_id = id
|
50
|
-
else
|
51
|
-
v_id = next_id
|
52
|
-
end
|
53
|
-
raise Pacer::ElementExists if @vertices.key? v_id
|
54
|
-
@vertices[v_id] = vertex_class.new self, v_id
|
55
|
-
end
|
56
|
-
|
57
|
-
def getVertex(id)
|
58
|
-
@vertices[id]
|
59
|
-
end
|
60
|
-
|
61
|
-
def removeVertex(vertex)
|
62
|
-
vertex.getEdges(Pacer::Pipes::BOTH).each do |e|
|
63
|
-
removeEdge e
|
64
|
-
end
|
65
|
-
@vertices.delete vertex.element_id
|
66
|
-
end
|
67
|
-
|
68
|
-
def getVertices
|
69
|
-
@vertices.values.to_iterable
|
70
|
-
end
|
71
|
-
|
72
|
-
def addEdge(id, outVertex, inVertex, label)
|
73
|
-
id ||= next_id
|
74
|
-
raise Pacer::ElementExists if @edges.key? id
|
75
|
-
@edges[id] = edge_class.new self, id, outVertex, inVertex, label
|
76
|
-
end
|
77
|
-
|
78
|
-
def getEdge(id)
|
79
|
-
@edges[id]
|
80
|
-
end
|
81
|
-
|
82
|
-
def removeEdge(edge)
|
83
|
-
@edges.delete edge.element_id
|
84
|
-
end
|
85
|
-
|
86
|
-
def getEdges
|
87
|
-
@edges.values.to_iterable
|
88
|
-
end
|
89
|
-
|
90
|
-
def clear
|
91
|
-
@vertices = {}
|
92
|
-
@edges = {}
|
93
|
-
@next_id = 0
|
94
|
-
end
|
95
|
-
|
96
|
-
def shutdown
|
97
|
-
clear
|
98
|
-
end
|
99
|
-
|
100
|
-
def ==(other)
|
101
|
-
other.equal? self
|
102
|
-
end
|
103
|
-
|
104
|
-
def features
|
105
|
-
FEATURES
|
106
|
-
end
|
107
|
-
|
108
|
-
protected
|
109
|
-
|
110
|
-
def vertex_class
|
111
|
-
RubyVertex
|
112
|
-
end
|
113
|
-
|
114
|
-
def edge_class
|
115
|
-
RubyEdge
|
116
|
-
end
|
117
|
-
|
118
|
-
def next_id
|
119
|
-
@next_id += 1
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
class RubyElement
|
124
|
-
include com.tinkerpop.blueprints.Element
|
125
|
-
|
126
|
-
def initialize(raw_graph, element_id)
|
127
|
-
@raw_graph = raw_graph
|
128
|
-
@element_id = element_id
|
129
|
-
@properties = {}
|
130
|
-
end
|
131
|
-
|
132
|
-
def getPropertyKeys
|
133
|
-
@properties.keys.to_hashset
|
134
|
-
end
|
135
|
-
|
136
|
-
def getProperty(key)
|
137
|
-
v = @properties[key.to_s]
|
138
|
-
if v.is_a? String
|
139
|
-
v.dup
|
140
|
-
else
|
141
|
-
v
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def setProperty(key, value)
|
146
|
-
@properties[key.to_s] = value
|
147
|
-
end
|
148
|
-
|
149
|
-
def removeProperty(key)
|
150
|
-
@properties.delete key.to_s
|
151
|
-
end
|
152
|
-
|
153
|
-
def getId
|
154
|
-
@element_id
|
155
|
-
end
|
156
|
-
|
157
|
-
protected
|
158
|
-
|
159
|
-
attr_reader :raw_graph
|
160
|
-
|
161
|
-
def extract_varargs_strings(labels)
|
162
|
-
if labels.first.is_a? ArrayJavaProxy
|
163
|
-
labels.first.map { |l| l.to_s }
|
164
|
-
else
|
165
|
-
labels
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
|
171
|
-
class RubyVertex < RubyElement
|
172
|
-
include com.tinkerpop.blueprints.Vertex
|
173
|
-
import com.tinkerpop.blueprints.util.VerticesFromEdgesIterable
|
174
|
-
|
175
|
-
def getRawVertex
|
176
|
-
self
|
177
|
-
end
|
178
|
-
|
179
|
-
def getVertices(direction, *labels)
|
180
|
-
VerticesFromEdgesIterable.new self, direction, *labels
|
181
|
-
end
|
182
|
-
|
183
|
-
def getEdges(direction, *labels)
|
184
|
-
labels = extract_varargs_strings(labels)
|
185
|
-
if direction == Pacer::Pipes::BOTH
|
186
|
-
edges = raw_graph.getEdges.select do |e|
|
187
|
-
( (e.getVertex(Pacer::Pipes::IN) == self or e.getVertex(Pacer::Pipes::OUT) == self) and
|
188
|
-
(labels.empty? or labels.include? e.getLabel) )
|
189
|
-
end
|
190
|
-
else
|
191
|
-
edges = raw_graph.getEdges.select { |e| e.getVertex(direction) == self and (labels.empty? or labels.include? e.getLabel) }
|
192
|
-
end
|
193
|
-
Pacer::Pipes::EnumerablePipe.new edges
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
class RubyEdge < RubyElement
|
198
|
-
include com.tinkerpop.blueprints.Edge
|
199
|
-
|
200
|
-
def initialize(raw_graph, id, out_vertex, in_vertex, label)
|
201
|
-
super(raw_graph, id)
|
202
|
-
@out_vertex = out_vertex
|
203
|
-
@in_vertex = in_vertex
|
204
|
-
@label = label.to_s
|
205
|
-
end
|
206
|
-
|
207
|
-
def getRawEdge
|
208
|
-
self
|
209
|
-
end
|
210
|
-
|
211
|
-
def getLabel()
|
212
|
-
@label
|
213
|
-
end
|
214
|
-
|
215
|
-
def getVertex(direction)
|
216
|
-
if direction == Pacer::Pipes::OUT
|
217
|
-
@out_vertex
|
218
|
-
else
|
219
|
-
@in_vertex
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
@@ -1,139 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
Run.tg :read_only do
|
4
|
-
use_pacer_graphml_data :read_only
|
5
|
-
|
6
|
-
describe Pacer::Transform::Join do
|
7
|
-
context 'with no key or value specified' do
|
8
|
-
subject { graph.v.join }
|
9
|
-
its(:count) { should == 7 }
|
10
|
-
specify 'each element should be a node' do
|
11
|
-
subject.each do |group|
|
12
|
-
group[:key].should be_a Pacer::Vertex
|
13
|
-
group.property_keys.to_a.should == ['key']
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'with key_route only' do
|
19
|
-
subject { graph.v.join(:key) { |r| r[:type] } }
|
20
|
-
|
21
|
-
its(:count) { should == 7 }
|
22
|
-
its(:to_a) { should_not be_empty }
|
23
|
-
specify 'each result should have one value' do
|
24
|
-
subject.each do |group|
|
25
|
-
group[:key].should be_a String
|
26
|
-
group.property_keys.to_a.should == ['key']
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'with key_route and value route' do
|
32
|
-
let(:route) { graph.v.join(:key) { |r| r[:type] }.join }
|
33
|
-
subject { route }
|
34
|
-
|
35
|
-
specify 'each result should reflect an element' do
|
36
|
-
subject.each.zip(graph.v.to_a) do |group, e|
|
37
|
-
group[:key].should == e[:type]
|
38
|
-
group.property_keys.to_set.should == Set['key', 'values']
|
39
|
-
group[:values].last.element_id.should == e.element_id
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context '#multigraph' do
|
44
|
-
subject { route.multigraph }
|
45
|
-
it { should be_a Pacer::PacerGraph }
|
46
|
-
its(:blueprints_graph) { should be_a Pacer::MultiGraph }
|
47
|
-
|
48
|
-
its('v.count') { should == 3 }
|
49
|
-
|
50
|
-
|
51
|
-
context 'person' do
|
52
|
-
subject { route.multigraph.vertex 'person' }
|
53
|
-
it 'should hove 2 values' do
|
54
|
-
subject[:values].length.should == 2
|
55
|
-
end
|
56
|
-
it { subject[:values].should == graph.v(:type => 'person').to_a }
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'project' do
|
60
|
-
subject { route.multigraph.vertex 'project' }
|
61
|
-
it 'should hove 2 values' do
|
62
|
-
subject[:values].length.should == 4
|
63
|
-
end
|
64
|
-
it { subject[:values].should == graph.v(:type => 'project').to_a }
|
65
|
-
end
|
66
|
-
|
67
|
-
context 'reduced to a count' do
|
68
|
-
subject do
|
69
|
-
route.multigraph.v.reduce({}) do |h, v|
|
70
|
-
h[v.element_id] = v[:values].count
|
71
|
-
h
|
72
|
-
end
|
73
|
-
end
|
74
|
-
specify 'it should have a count for values' do
|
75
|
-
subject['project'].should == 4
|
76
|
-
subject['person'].should == 2
|
77
|
-
subject['group'].should == 1
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'reduced to a string' do
|
82
|
-
subject do
|
83
|
-
route.multigraph.v.reduce({}) do |h, v|
|
84
|
-
h[v.element_id] = v[:values].map { |v| v[:name] }.join ', '
|
85
|
-
h
|
86
|
-
end
|
87
|
-
end
|
88
|
-
specify do
|
89
|
-
subject['project'].should == 'blueprints, pipes, pacer, gremlin'
|
90
|
-
subject['person'].should == 'pangloss, okram'
|
91
|
-
subject['group'].should == 'tinkerpop'
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
context 'with a key block that returns a literal value' do
|
98
|
-
subject { graph.v.join { |r| r[:type] }.key { |r| r[:type].length } }
|
99
|
-
its(:count) { should == 7 }
|
100
|
-
specify 'each value should have a numeric key' do
|
101
|
-
subject.each do |v|
|
102
|
-
v[:key].should == v.element_id
|
103
|
-
v[:key].should == v[:values].first.length
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context 'with values_maps' do
|
109
|
-
let(:counted_group) do
|
110
|
-
graph.v.join(:count) { |r| r.out_e.counted.cap }.
|
111
|
-
join(:out_e, &:out_e).
|
112
|
-
key { |r| r[:type] }
|
113
|
-
end
|
114
|
-
subject do
|
115
|
-
counted_group.multigraph
|
116
|
-
end
|
117
|
-
its('v.count') { should == 3 }
|
118
|
-
specify { counted_group.count.should == 7 }
|
119
|
-
specify 'combine(:count) should group the counts in a hash' do
|
120
|
-
hash = Hash[subject.v[[:key, :count]].to_a]
|
121
|
-
hash.should == {"project"=>[0, 1, 3, 2], "person"=>[1, 3], "group"=>[4]}
|
122
|
-
end
|
123
|
-
|
124
|
-
specify 'reduce summarizes edge labels for each type' do
|
125
|
-
result = Hash[subject.v.map { |v| [v.element_id, v[:out_e].group_count { |e| e.label }] }.to_a]
|
126
|
-
result.should == {"project" => {"uses" => 5, "modelled_on" => 1},
|
127
|
-
"person" => {"wrote" => 4},
|
128
|
-
"group" => {"projects" => 3, "member" => 1}}
|
129
|
-
end
|
130
|
-
|
131
|
-
its(:blueprints_graph) { should be_a Pacer::MultiGraph }
|
132
|
-
|
133
|
-
specify do
|
134
|
-
counted_group.inspect.should ==
|
135
|
-
"#<GraphV -> V-Join(#<V -> Obj(type) -> decode>: {:count=>#<V -> outE -> Obj-Cap(E-Counted)>, :out_e=>#<V -> outE>})>"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|