red_grape 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +1 -0
- data/bin/juicer +111 -0
- data/lib/ext/object_ext.rb +5 -0
- data/lib/red_grape/edge.rb +13 -0
- data/lib/red_grape/graph.rb +11 -0
- data/lib/red_grape/pipe/as_pipe.rb +0 -1
- data/lib/red_grape/pipe/base.rb +3 -0
- data/lib/red_grape/pipe/both_pipe.rb +30 -0
- data/lib/red_grape/pipe/context.rb +16 -1
- data/lib/red_grape/pipe/count_pipe.rb +14 -0
- data/lib/red_grape/pipe/map_pipe.rb +11 -0
- data/lib/red_grape/pipe/select_pipe.rb +11 -0
- data/lib/red_grape/vertex.rb +11 -0
- data/lib/red_grape.rb +5 -1
- data/test/test_count_pipe.rb +13 -0
- data/test/test_map_pipe.rb +21 -0
- data/test/test_on_the_nature_of_pipes.rb +21 -20
- data/test/test_out_pipe.rb +26 -0
- data/test/test_select_pipe.rb +15 -0
- data/test/test_traversal_patterns.rb +32 -32
- metadata +18 -4
data/.gitignore
CHANGED
data/README.md
CHANGED
data/bin/juicer
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('../../lib', __FILE__)
|
3
|
+
|
4
|
+
require 'sinatra'
|
5
|
+
require 'red_grape'
|
6
|
+
|
7
|
+
use Rack::Static, :urls => ['/cellar', '/js', '/css'], :root => 'public'
|
8
|
+
|
9
|
+
graphs = {
|
10
|
+
'tinkergraph' => RedGrape.create_tinker_graph
|
11
|
+
}
|
12
|
+
|
13
|
+
get '/' do
|
14
|
+
{
|
15
|
+
version: RedGrape::VERSION,
|
16
|
+
supportedPaths: {
|
17
|
+
GET: [
|
18
|
+
'/graphs',
|
19
|
+
'/graphs/[graph]',
|
20
|
+
'/graphs/[graph]/vertices',
|
21
|
+
'/graphs/[graph]/vertices?key=[key]&value=[value]',
|
22
|
+
'/graphs/[graph]/vertices/[vertex]',
|
23
|
+
'/graphs/[graph]/vertices/[vertex]/out',
|
24
|
+
'/graphs/[graph]/vertices/[vertex]/in',
|
25
|
+
'/graphs/[graph]/vertices/[vertex]/both',
|
26
|
+
'/graphs/[graph]/vertices/[vertex]/[dir]?_label=[label]',
|
27
|
+
'/graphs/[graph]/edges',
|
28
|
+
'/graphs/[graph]/edges/[edge]',
|
29
|
+
'/graphs/[graph]/vertices/[edge]/outE',
|
30
|
+
'/graphs/[graph]/vertices/[edge]/inE',
|
31
|
+
'/graphs/[graph]/vertices/[edge]/bothE',
|
32
|
+
'/graphs/[graph]/vertices/[edge]/[dir]E?_label=[label]',
|
33
|
+
],
|
34
|
+
POST: [
|
35
|
+
#'/graphs/[graph]/vertices',
|
36
|
+
#'/graphs/[graph]/vertices/[vertex]',
|
37
|
+
#'/graphs/[graph]/vertices/[vertex]?[key1]=[value1]&[key2]=[value2]',
|
38
|
+
#'/graphs/[graph]/edges?_outV=[vertex1]&_label=[label]&_inV=[vertex2]&[key1]=[value1]&=[key2]=[value2]',
|
39
|
+
#'/graphs/[graph]/edges/[edge]?_outV=[vertex1]&_label=[label]&_inV=[vertex2]&[key1]=[value1]&=[key2]=[value2]',
|
40
|
+
#'/graphs/[graph]/edges/[edge]?[key1]=[key2]'
|
41
|
+
],
|
42
|
+
PUT: [
|
43
|
+
#'/graphs/[graph]/vertices/[vertex]?[key1]=[value1]&[key2]=[value2]',
|
44
|
+
#'/graphs/[graph]/edges/[edge]?[key1]=[value1]&[key2]=[value2]'
|
45
|
+
],
|
46
|
+
DELETE: [
|
47
|
+
#'/graphs/[graph]/vertices/[vertex]',
|
48
|
+
#'/graphs/[graph]/vertices/[vertex]?[key1]&[key2]',
|
49
|
+
#'/graphs/[graph]/edges/[edge]',
|
50
|
+
#'/graphs/[graph]/edges/[edge]?[key1]&[key2]'
|
51
|
+
]
|
52
|
+
}
|
53
|
+
}.to_pretty_json
|
54
|
+
end
|
55
|
+
|
56
|
+
get %r{/graphs/?$} do
|
57
|
+
{
|
58
|
+
version: RedGrape::VERSION,
|
59
|
+
name: 'Juicer: A Graph Server',
|
60
|
+
graphs: graphs.keys
|
61
|
+
}.to_pretty_json
|
62
|
+
end
|
63
|
+
|
64
|
+
get %r{/graphs/([^/]+)/?$} do |graph_id|
|
65
|
+
graphs[graph_id].to_h.to_pretty_json
|
66
|
+
end
|
67
|
+
|
68
|
+
get %r{/graphs/([^/]+)/vertices/?$} do |graph_id|
|
69
|
+
graph = graphs[graph_id]
|
70
|
+
k, v = params['key'], params['value']
|
71
|
+
vertices =
|
72
|
+
if k
|
73
|
+
graph.vertex.find_all{|e| e[k].to_s == v}
|
74
|
+
else
|
75
|
+
graph.vertex
|
76
|
+
end
|
77
|
+
vertices.map(&:to_h).to_pretty_json
|
78
|
+
end
|
79
|
+
|
80
|
+
get %r{/graphs/([^/]+)/vertices/([^/]+)/?$} do |graph_id, vertex_id|
|
81
|
+
graphs[graph_id].vertex(vertex_id).to_h.to_pretty_json
|
82
|
+
end
|
83
|
+
|
84
|
+
get %r{/graphs/([^/]+)/vertices/([^/]+)/(out|in|both)/?$} do |graph_id, vertex_id, dir|
|
85
|
+
label = params['_label']
|
86
|
+
vertex = graphs[graph_id].vertex(vertex_id)
|
87
|
+
if label
|
88
|
+
vertex.send(dir, label)[].map(&:to_h).to_pretty_json
|
89
|
+
else
|
90
|
+
vertex.send(dir)[].map(&:to_h).to_pretty_json
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
get %r{/graphs/([^/]+)/edges/?$} do |graph_id|
|
95
|
+
graphs[graph_id].edge.map(&:to_h).to_pretty_json
|
96
|
+
end
|
97
|
+
|
98
|
+
get %r{/graphs/([^/]+)/edges/([^/]+)/?$} do |graph_id, edge_id|
|
99
|
+
graphs[graph_id].edge(edge_id).to_h.to_pretty_json
|
100
|
+
end
|
101
|
+
|
102
|
+
get %r{/graphs/([^/]+)/vertices/([^/]+)/(out_e|in_e|both_e|outE|inE|bothE)/?$} do |graph_id, vertex_id, dir|
|
103
|
+
label = params['_label']
|
104
|
+
vertex = graphs[graph_id].vertex(vertex_id)
|
105
|
+
if label
|
106
|
+
vertex.send(dir, label)[].map(&:to_h).to_pretty_json
|
107
|
+
else
|
108
|
+
vertex.send(dir)[].map(&:to_h).to_pretty_json
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
data/lib/ext/object_ext.rb
CHANGED
data/lib/red_grape/edge.rb
CHANGED
@@ -29,5 +29,18 @@ module RedGrape
|
|
29
29
|
def to_s
|
30
30
|
"e[#{@id}][#{@source.id}-#{@label}->#{@target.id}]"
|
31
31
|
end
|
32
|
+
|
33
|
+
def to_h
|
34
|
+
{
|
35
|
+
version: RedGrape::VERSION,
|
36
|
+
results: {
|
37
|
+
_type: '_edge',
|
38
|
+
_id: @id,
|
39
|
+
_label: @label,
|
40
|
+
_source: @source.id,
|
41
|
+
_target: @target.id
|
42
|
+
}.merge(@property)
|
43
|
+
}
|
44
|
+
end
|
32
45
|
end
|
33
46
|
end
|
data/lib/red_grape/graph.rb
CHANGED
@@ -243,5 +243,16 @@ module RedGrape
|
|
243
243
|
def to_s
|
244
244
|
"redgrape[vertices:#{@vertices.size} edges:#{@edges.size}]"
|
245
245
|
end
|
246
|
+
|
247
|
+
def to_h
|
248
|
+
{
|
249
|
+
version:RedGrape::VERSION,
|
250
|
+
name:'-',
|
251
|
+
graph:to_s,
|
252
|
+
features:self.class.features,
|
253
|
+
readOnly:readonly?,
|
254
|
+
type:self.class.name
|
255
|
+
}
|
256
|
+
end
|
246
257
|
end
|
247
258
|
end
|
data/lib/red_grape/pipe/base.rb
CHANGED
@@ -57,12 +57,15 @@ module RedGrape
|
|
57
57
|
def take(context=Context.new)
|
58
58
|
if first?
|
59
59
|
val = @prev.pass_through self, context
|
60
|
+
# TODO: should be refactored
|
60
61
|
if context.aggregating?
|
61
62
|
context.resume_from_aggregating
|
62
63
|
elsif context.grouping?
|
63
64
|
context.resume_from_grouping
|
64
65
|
elsif context.gathering?
|
65
66
|
context.resume_from_gathering
|
67
|
+
elsif context.counting?
|
68
|
+
context.resume_from_counting
|
66
69
|
else
|
67
70
|
val
|
68
71
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'red_grape/pipe/base'
|
2
|
+
|
3
|
+
module RedGrape
|
4
|
+
module Pipe
|
5
|
+
module Both
|
6
|
+
def both(*opts)
|
7
|
+
BothPipe.new self, *opts
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class BothPipe < Pipe::Base
|
12
|
+
def pipe_name
|
13
|
+
@opts.empty? ? super : "#{super}(#{@opts.first})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def pass(obj, context)
|
17
|
+
group =
|
18
|
+
if self.opts.empty? or self.opts.first.empty? # TODO なぜかlabelに[]が入ってる
|
19
|
+
(obj.out_edges.map(&:target) + obj.in_edges.map(&:source)).uniq
|
20
|
+
else
|
21
|
+
label = self.opts.first
|
22
|
+
out_edges = obj.out_edges.find_all{|e| e.label == label}.map(&:target)
|
23
|
+
in_edges = obj.in_edges.find_all{|e| e.label == label}.map(&:source)
|
24
|
+
(out_edges + in_edges).uniq
|
25
|
+
end
|
26
|
+
pass_next context, obj, group
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,7 +2,7 @@ module RedGrape
|
|
2
2
|
module Pipe
|
3
3
|
class Context
|
4
4
|
attr_accessor :it, :loops
|
5
|
-
attr_reader :history, :grouping_items
|
5
|
+
attr_reader :history, :grouping_items, :marks
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@history = []
|
@@ -11,6 +11,7 @@ module RedGrape
|
|
11
11
|
@aggregated_items = {}
|
12
12
|
@grouping_items = {}
|
13
13
|
@gathering_items = []
|
14
|
+
@counting_items = []
|
14
15
|
@loops = 1
|
15
16
|
end
|
16
17
|
|
@@ -113,6 +114,20 @@ module RedGrape
|
|
113
114
|
end
|
114
115
|
end
|
115
116
|
|
117
|
+
def count(obj, next_pipe)
|
118
|
+
@counting_items << obj
|
119
|
+
end
|
120
|
+
|
121
|
+
def counting?
|
122
|
+
not @counting_items.empty?
|
123
|
+
end
|
124
|
+
|
125
|
+
def resume_from_counting
|
126
|
+
size = @counting_items.size
|
127
|
+
@counting_items.clear
|
128
|
+
size
|
129
|
+
end
|
130
|
+
|
116
131
|
def eval(args={}, &block)
|
117
132
|
args.each {|k, v| self.send "#{k}=", v}
|
118
133
|
instance_eval(&block)
|
data/lib/red_grape/vertex.rb
CHANGED
@@ -2,6 +2,7 @@ require 'red_grape/element'
|
|
2
2
|
|
3
3
|
module RedGrape
|
4
4
|
class Vertex < Element
|
5
|
+
include RedGrape::Pipe::Both
|
5
6
|
include RedGrape::Pipe::Out
|
6
7
|
include RedGrape::Pipe::OutE
|
7
8
|
include RedGrape::Pipe::In
|
@@ -47,5 +48,15 @@ module RedGrape
|
|
47
48
|
def to_s
|
48
49
|
"v[#{@id}]"
|
49
50
|
end
|
51
|
+
|
52
|
+
def to_h
|
53
|
+
{
|
54
|
+
version: RedGrape::VERSION,
|
55
|
+
results: {
|
56
|
+
_type: '_vertex',
|
57
|
+
_id: @id
|
58
|
+
}.merge(@property)
|
59
|
+
}
|
60
|
+
end
|
50
61
|
end
|
51
62
|
end
|
data/lib/red_grape.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module RedGrape
|
2
|
-
VERSION = '0.0.
|
2
|
+
VERSION = '0.0.12'
|
3
3
|
end
|
4
4
|
|
5
5
|
require 'ext/nil_class_ext'
|
@@ -8,8 +8,10 @@ require 'ext/array_ext'
|
|
8
8
|
require 'red_grape/pipe/aggregate_pipe'
|
9
9
|
require 'red_grape/pipe/as_pipe'
|
10
10
|
require 'red_grape/pipe/back_pipe'
|
11
|
+
require 'red_grape/pipe/both_pipe'
|
11
12
|
require 'red_grape/pipe/cap_pipe'
|
12
13
|
require 'red_grape/pipe/copy_split_pipe'
|
14
|
+
require 'red_grape/pipe/count_pipe'
|
13
15
|
require 'red_grape/pipe/except_pipe'
|
14
16
|
require 'red_grape/pipe/exhaust_merge_pipe'
|
15
17
|
require 'red_grape/pipe/fill_pipe'
|
@@ -24,6 +26,7 @@ require 'red_grape/pipe/in_pipe'
|
|
24
26
|
require 'red_grape/pipe/in_e_pipe'
|
25
27
|
require 'red_grape/pipe/in_v_pipe'
|
26
28
|
require 'red_grape/pipe/loop_pipe'
|
29
|
+
require 'red_grape/pipe/map_pipe'
|
27
30
|
require 'red_grape/pipe/out_pipe'
|
28
31
|
require 'red_grape/pipe/out_e_pipe'
|
29
32
|
require 'red_grape/pipe/out_v_pipe'
|
@@ -31,6 +34,7 @@ require 'red_grape/pipe/property_pipe'
|
|
31
34
|
require 'red_grape/pipe/paths_pipe'
|
32
35
|
require 'red_grape/pipe/retain_pipe'
|
33
36
|
require 'red_grape/pipe/scatter_pipe'
|
37
|
+
require 'red_grape/pipe/select_pipe'
|
34
38
|
require 'red_grape/pipe/side_effect_pipe'
|
35
39
|
require 'red_grape/pipe/transform_pipe'
|
36
40
|
require 'red_grape/pipe/v_pipe'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
|
4
|
+
class CountPipeTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@g1 = RedGrape.load_graph 'data/graph-example-1.xml'
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_count
|
10
|
+
assert_equal 6, @g1.V.count[]
|
11
|
+
assert_equal 3, @g1.v(1).out.count[]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
|
4
|
+
class MapPipeTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@g1 = RedGrape.load_graph 'data/graph-example-1.xml'
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_map
|
10
|
+
assert_equal [
|
11
|
+
{"name"=>"marko", "age"=>29},
|
12
|
+
{"name"=>"vadas", "age"=>27},
|
13
|
+
{"name"=>"lop", "lang"=>"java"},
|
14
|
+
{"name"=>"josh", "age"=>32},
|
15
|
+
{"name"=>"ripple", "lang"=>"java"},
|
16
|
+
{"name"=>"peter", "age"=>35}
|
17
|
+
] , @g1.V.map[]
|
18
|
+
|
19
|
+
assert_equal({"name"=>"marko", "age"=>29}, @g1.v(1).map[])
|
20
|
+
end
|
21
|
+
end
|
@@ -9,15 +9,16 @@ class OnTheNatureOfPipesTest < Test::Unit::TestCase
|
|
9
9
|
|
10
10
|
def test_basic
|
11
11
|
assert_equal '1',
|
12
|
-
@graph.v(1).
|
12
|
+
@graph.v(1)[].id
|
13
13
|
|
14
14
|
assert_equal %w(2 3 4),
|
15
|
-
@graph.v(1).out.
|
15
|
+
@graph.v(1).out[].map(&:id).sort
|
16
16
|
|
17
17
|
assert_equal %w(josh lop vadas),
|
18
|
-
@graph.v(1).out.name.
|
18
|
+
@graph.v(1).out.name[].sort
|
19
19
|
|
20
|
-
paths = @graph.v(1).out.name.paths
|
20
|
+
#paths = @graph.v(1).out.name.paths[]
|
21
|
+
paths = @graph.v(1).out.name.paths[]
|
21
22
|
assert_equal 3,
|
22
23
|
paths.size
|
23
24
|
|
@@ -30,16 +31,16 @@ class OnTheNatureOfPipesTest < Test::Unit::TestCase
|
|
30
31
|
|
31
32
|
def test_filter
|
32
33
|
assert_equal %w(2 4),
|
33
|
-
@graph.v(1).out('knows').
|
34
|
+
@graph.v(1).out('knows')[].map(&:id).sort
|
34
35
|
|
35
36
|
assert_equal %w(2),
|
36
|
-
@graph.v(1).out('knows').filter{it.age < 30}.
|
37
|
+
@graph.v(1).out('knows').filter{it.age < 30}[].map(&:id).sort
|
37
38
|
|
38
39
|
assert_equal %w(vadas),
|
39
|
-
@graph.v(1).out('knows').filter{it.age < 30}.name.
|
40
|
+
@graph.v(1).out('knows').filter{it.age < 30}.name[].sort
|
40
41
|
|
41
42
|
assert_equal [5],
|
42
|
-
@graph.v(1).out('knows').filter{it.age < 30}.name.transform{it.size}.
|
43
|
+
@graph.v(1).out('knows').filter{it.age < 30}.name.transform{it.size}[].sort
|
43
44
|
|
44
45
|
assert_equal %w[V Out(knows) Filter Property(name) Transform],
|
45
46
|
@graph.v(1).out('knows').filter{it.age < 30}.name.transform{it.size}.to_a
|
@@ -47,16 +48,16 @@ class OnTheNatureOfPipesTest < Test::Unit::TestCase
|
|
47
48
|
|
48
49
|
def test_side_effect
|
49
50
|
assert_equal 'marko',
|
50
|
-
@graph.v(1).side_effect{@x = it}.
|
51
|
+
@graph.v(1).side_effect{@x = it}[].name
|
51
52
|
|
52
53
|
assert_equal %w(3),
|
53
|
-
@graph.v(1).side_effect{@x = it}.out('created').
|
54
|
+
@graph.v(1).side_effect{@x = it}.out('created')[].map(&:id).sort
|
54
55
|
|
55
56
|
assert_equal %w(1 4 6),
|
56
|
-
@graph.v(1).side_effect{@x = it}.out('created').in('created').
|
57
|
+
@graph.v(1).side_effect{@x = it}.out('created').in('created')[].map(&:id).sort
|
57
58
|
|
58
59
|
assert_equal %w(4 6),
|
59
|
-
@graph.v(1).side_effect{@x = it}.out('created').in('created').filter{it != @x}.
|
60
|
+
@graph.v(1).side_effect{@x = it}.out('created').in('created').filter{it != @x}[].map(&:id).sort
|
60
61
|
|
61
62
|
assert_equal %w(V SideEffect Out(created) In(created) Filter),
|
62
63
|
@graph.v(1).side_effect{@x = it}.out('created').in('created').filter{it != @x}.to_a
|
@@ -65,35 +66,35 @@ class OnTheNatureOfPipesTest < Test::Unit::TestCase
|
|
65
66
|
def test_if_then_else
|
66
67
|
#assert_equal ['vadas', ['ripple', 'lop']],
|
67
68
|
assert_equal ['vadas', 'ripple', 'lop'],
|
68
|
-
@graph.v(1).out('knows').if_then_else(_{it.age < 30}, _{it.name}, _{it.out('created').name}).
|
69
|
+
@graph.v(1).out('knows').if_then_else(_{it.age < 30}, _{it.name}, _{it.out('created').name})[].to_a
|
69
70
|
end
|
70
71
|
|
71
72
|
def test_back
|
72
73
|
assert_equal %w(josh vadas),
|
73
|
-
@graph.v(1).out('knows').name.
|
74
|
+
@graph.v(1).out('knows').name[].to_a.sort
|
74
75
|
|
75
76
|
assert_equal %w(vadas),
|
76
|
-
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.
|
77
|
+
@graph.v(1).out('knows').name.filter{it[0] == 'v'}[].to_a
|
77
78
|
|
78
79
|
assert_equal %w(2),
|
79
|
-
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.back(2).
|
80
|
+
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.back(2)[].to_a.map(&:id)
|
80
81
|
|
81
82
|
assert_equal %w(V Out(knows) Property(name) Filter Back),
|
82
83
|
@graph.v(1).out('knows').name.filter{it[0] == 'v'}.back(2).to_a
|
83
84
|
|
84
85
|
assert_equal %w(2),
|
85
|
-
@graph.v(1).out('knows').as('here').name.filter{it[0] == 'v'}.back('here').
|
86
|
+
@graph.v(1).out('knows').as('here').name.filter{it[0] == 'v'}.back('here')[].to_a.map(&:id)
|
86
87
|
end
|
87
88
|
|
88
89
|
def test_loop
|
89
90
|
assert_equal %w(3 5),
|
90
|
-
@graph.v(1).out.out.
|
91
|
+
@graph.v(1).out.out[].to_a.map(&:id).sort
|
91
92
|
|
92
93
|
assert_equal %w(3 5),
|
93
|
-
@graph.v(1).out.loop(1){loops < 3}.
|
94
|
+
@graph.v(1).out.loop(1){loops < 3}[].to_a.map(&:id).sort
|
94
95
|
|
95
96
|
assert_equal %w(lop ripple),
|
96
|
-
@graph.v(1).out.loop(1){loops < 3}.name.
|
97
|
+
@graph.v(1).out.loop(1){loops < 3}.name[].sort
|
97
98
|
|
98
99
|
assert_equal %w(V Out Loop Property(name)),
|
99
100
|
@graph.v(1).out.loop(1){loops < 3}.name.to_a
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
|
4
|
+
class OutPipeTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@g1 = RedGrape.load_graph 'data/graph-example-1.xml'
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_out
|
10
|
+
out = @g1.v(1).out[]
|
11
|
+
assert_equal 3, out.size
|
12
|
+
assert_equal RedGrape::Vertex, out[0].class
|
13
|
+
assert_equal '2', out[0].id
|
14
|
+
assert_equal RedGrape::Vertex, out[1].class
|
15
|
+
assert_equal '4', out[1].id
|
16
|
+
assert_equal RedGrape::Vertex, out[2].class
|
17
|
+
assert_equal '3', out[2].id
|
18
|
+
|
19
|
+
out2 = @g1.v(1).out.out[]
|
20
|
+
assert_equal 2, out2.size
|
21
|
+
assert_equal RedGrape::Vertex, out2[0].class
|
22
|
+
assert_equal '5', out2[0].id
|
23
|
+
assert_equal RedGrape::Vertex, out2[1].class
|
24
|
+
assert_equal '3', out2[1].id
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'red_grape'
|
3
|
+
|
4
|
+
class SelectPipeTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@g1 = RedGrape.load_graph 'data/graph-example-1.xml'
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_select
|
10
|
+
assert_equal(
|
11
|
+
'[{"v1"=>v[1], "children"=>v[3]}, {"v1"=>v[1], "children"=>v[3]}, {"v1"=>v[1], "children"=>v[3]}]',
|
12
|
+
@g1.v(1).as('v1').out.as('children').select[].to_s
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
@@ -8,32 +8,32 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
8
8
|
|
9
9
|
# https://github.com/tinkerpop/gremlin/wiki/Backtrack-Pattern
|
10
10
|
def test_backtrack_pattern
|
11
|
-
assert_equal [29], @g1.V.out('knows').has('age', :gt, 30).back(2).age
|
12
|
-
assert_equal [29], @g1.V.as('x').outE('knows').inV.has('age', :gt, 30).back('x').age
|
11
|
+
assert_equal [29], @g1.V.out('knows').has('age', :gt, 30).back(2).age[]
|
12
|
+
assert_equal [29], @g1.V.as('x').outE('knows').inV.has('age', :gt, 30).back('x').age[]
|
13
13
|
end
|
14
14
|
|
15
15
|
# https://github.com/tinkerpop/gremlin/wiki/Except-Retain-Pattern
|
16
16
|
def test_except_retain_pattern
|
17
|
-
assert_equal %w(2 3 4), @g1.v(1).out.
|
18
|
-
assert_equal %w(3 5), @g1.v(1).out.out.
|
19
|
-
assert_equal %w(5), @g1.v(1).out.aggregate(:x).out.except(:x).
|
20
|
-
assert_equal %w(3), @g1.v(1).out.aggregate(:x).out.retain(:x).
|
17
|
+
assert_equal %w(2 3 4), @g1.v(1).out[].map(&:id).sort
|
18
|
+
assert_equal %w(3 5), @g1.v(1).out.out[].map(&:id).sort
|
19
|
+
assert_equal %w(5), @g1.v(1).out.aggregate(:x).out.except(:x)[].map(&:id).sort
|
20
|
+
assert_equal %w(3), @g1.v(1).out.aggregate(:x).out.retain(:x)[].map(&:id).sort
|
21
21
|
end
|
22
22
|
|
23
23
|
# https://github.com/tinkerpop/gremlin/wiki/Flow-Rank-Pattern
|
24
24
|
def test_flow_rank_pattern
|
25
|
-
assert_equal %w(3 5), @g1.V('lang', 'java').
|
25
|
+
assert_equal %w(3 5), @g1.V('lang', 'java')[].map(&:id).sort
|
26
26
|
software = []
|
27
|
-
@g1.V('lang', 'java').fill(software)
|
27
|
+
@g1.V('lang', 'java').fill(software)[]
|
28
28
|
assert_equal %w(3 5), software.map(&:id).sort
|
29
|
-
assert_equal %w(marko josh peter josh), software._.in('created').name
|
29
|
+
assert_equal %w(marko josh peter josh), software._.in('created').name[]
|
30
30
|
assert_equal(
|
31
31
|
{'marko' => 1, 'josh' => 2, 'peter' => 1},
|
32
|
-
software._.in('created').name.groupCount.cap
|
32
|
+
software._.in('created').name.groupCount.cap[]
|
33
33
|
)
|
34
34
|
|
35
35
|
m = {}
|
36
|
-
assert_equal %w(marko josh peter josh), software._.in('created').name.groupCount(m)
|
36
|
+
assert_equal %w(marko josh peter josh), software._.in('created').name.groupCount(m)[]
|
37
37
|
assert_equal({'marko' => 1, 'josh' => 2, 'peter' => 1}, m)
|
38
38
|
end
|
39
39
|
|
@@ -41,28 +41,28 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
41
41
|
def test_path_pattern
|
42
42
|
v1 = @g1.vertex(1)
|
43
43
|
|
44
|
-
assert_equal %w(josh lop vadas), v1.out.name.
|
44
|
+
assert_equal %w(josh lop vadas), v1.out.name[].sort
|
45
45
|
|
46
|
-
path = v1.out.name.path
|
46
|
+
path = v1.out.name.path[]
|
47
47
|
assert_equal 3, path.size
|
48
48
|
assert_equal 3, path.first.size
|
49
49
|
assert_equal '[[v[1], v[2], "vadas"], [v[1], v[4], "josh"], [v[1], v[3], "lop"]]', path.to_s
|
50
50
|
|
51
|
-
path = v1.outE.inV.name.path
|
51
|
+
path = v1.outE.inV.name.path[]
|
52
52
|
assert_equal '[[v[1], e[7][1-knows->2], v[2], "vadas"], [v[1], e[8][1-knows->4], v[4], "josh"], [v[1], e[9][1-created->3], v[3], "lop"]]', path.to_s
|
53
53
|
|
54
54
|
assert_equal(
|
55
55
|
[["marko", 0.5, "vadas"], ["marko", 1.0, "josh"], ["marko", 0.4, "lop"]].to_s,
|
56
|
-
v1.outE.inV.path(_{it.name}, _{it.weight}, _{it.name}).
|
56
|
+
v1.outE.inV.path(_{it.name}, _{it.weight}, _{it.name})[].to_s
|
57
57
|
)
|
58
58
|
end
|
59
59
|
|
60
60
|
def test_loop_pattern
|
61
61
|
@g2 ||= RedGrape.load_graph 'data/graph-example-2.xml'
|
62
62
|
v89 = @g2.vertex 89
|
63
|
-
assert_equal 36, v89.outE.inV.path.
|
63
|
+
assert_equal 36, v89.outE.inV.path[].size
|
64
64
|
|
65
|
-
path = v89.outE.inV.loop(2){it.loops < 3}.path.
|
65
|
+
path = v89.outE.inV.loop(2){it.loops < 3}.path[].first
|
66
66
|
assert_equal '[v[89], e[7006][89-followed_by->127], v[127], e[7786][127-sung_by->340], v[340]]', path.to_s
|
67
67
|
assert_equal RedGrape::Vertex, path[0].class
|
68
68
|
assert_equal RedGrape::Edge, path[1].class
|
@@ -70,7 +70,7 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
70
70
|
assert_equal RedGrape::Edge, path[3].class
|
71
71
|
assert_equal RedGrape::Vertex, path[4].class
|
72
72
|
|
73
|
-
path = v89.as('x').outE.inV.loop('x'){it.loops < 3}.path.
|
73
|
+
path = v89.as('x').outE.inV.loop('x'){it.loops < 3}.path[].first
|
74
74
|
assert_equal '[v[89], e[7006][89-followed_by->127], v[127], e[7786][127-sung_by->340], v[340]]', path.to_s
|
75
75
|
assert_equal RedGrape::Vertex, path[0].class
|
76
76
|
assert_equal RedGrape::Edge, path[1].class
|
@@ -78,7 +78,7 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
78
78
|
assert_equal RedGrape::Edge, path[3].class
|
79
79
|
assert_equal RedGrape::Vertex, path[4].class
|
80
80
|
|
81
|
-
path = v89.outE.inV.outE.inV.path.
|
81
|
+
path = v89.outE.inV.outE.inV.path[].first
|
82
82
|
assert_equal '[v[89], e[7006][89-followed_by->127], v[127], e[7786][127-sung_by->340], v[340]]', path.to_s
|
83
83
|
assert_equal RedGrape::Vertex, path[0].class
|
84
84
|
assert_equal RedGrape::Edge, path[1].class
|
@@ -88,17 +88,17 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
88
88
|
|
89
89
|
#assert_equal(
|
90
90
|
# 70307,
|
91
|
-
# v89.out.loop(1, _{it.loops < 4}).
|
91
|
+
# v89.out.loop(1, _{it.loops < 4})[].size
|
92
92
|
#) #=> OK
|
93
93
|
|
94
94
|
#assert_equal(
|
95
95
|
# 71972,
|
96
|
-
# v89.out.loop(1, _{it.loops < 4}, _{true}).
|
96
|
+
# v89.out.loop(1, _{it.loops < 4}, _{true})[].size
|
97
97
|
#) #=> 70307
|
98
98
|
|
99
99
|
#assert_equal(
|
100
100
|
# 582,
|
101
|
-
# v89.out.loop(1, _{it.loops < 4}, _{it.object.id == '89'}).
|
101
|
+
# v89.out.loop(1, _{it.loops < 4}, _{it.object.id == '89'})[].size
|
102
102
|
#) #=> 564
|
103
103
|
end
|
104
104
|
|
@@ -108,12 +108,12 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
108
108
|
|
109
109
|
#assert_equal(
|
110
110
|
# ['ripple', 27, 'lop', 32],
|
111
|
-
# v1.out('knows').copy_split(_.out('created').name, _.age).fair_merge
|
111
|
+
# v1.out('knows').copy_split(_.out('created').name, _.age).fair_merge[]
|
112
112
|
#) # TODO: not yet
|
113
113
|
|
114
114
|
assert_equal(
|
115
115
|
[27, 'ripple', 'lop', 32],
|
116
|
-
v1.out('knows').copy_split(_.out('created').name, _.age).exhaust_merge
|
116
|
+
v1.out('knows').copy_split(_.out('created').name, _.age).exhaust_merge[]
|
117
117
|
)
|
118
118
|
end
|
119
119
|
|
@@ -122,17 +122,17 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
122
122
|
@g2 ||= RedGrape.load_graph 'data/graph-example-2.xml'
|
123
123
|
assert_equal(
|
124
124
|
{'cover'=>313, 'original'=>184},
|
125
|
-
@g2.V.has_not('song_type', nil).group_count(_{it.song_type}).cap
|
125
|
+
@g2.V.has_not('song_type', nil).group_count(_{it.song_type}).cap[]
|
126
126
|
)
|
127
127
|
|
128
|
-
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it}).cap
|
128
|
+
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it}).cap[]
|
129
129
|
assert_equal 2, ret.keys.size
|
130
130
|
assert_equal 313, ret.values[0].size
|
131
131
|
assert ret.values[0].all?{|e| e.is_a? RedGrape::Vertex}
|
132
132
|
assert_equal 184, ret.values[1].size
|
133
133
|
assert ret.values[1].all?{|e| e.is_a? RedGrape::Vertex}
|
134
134
|
|
135
|
-
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it.name}).cap
|
135
|
+
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it.name}).cap[]
|
136
136
|
assert_equal 2, ret.keys.size
|
137
137
|
assert_equal 313, ret.values[0].size
|
138
138
|
assert ret.values[0].all?{|e| e.is_a? String}
|
@@ -141,23 +141,23 @@ class TraversalPatternsTest < Test::Unit::TestCase
|
|
141
141
|
assert_equal 'HEY BO DIDDLEY', ret.values[0][0]
|
142
142
|
assert_equal 'BERTHA', ret.values[1][0]
|
143
143
|
|
144
|
-
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{1}).cap
|
144
|
+
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{1}).cap[]
|
145
145
|
assert_equal 2, ret.keys.size
|
146
146
|
assert ret.values[0].all?{|e| e == 1}
|
147
147
|
assert ret.values[1].all?{|e| e == 1}
|
148
148
|
|
149
|
-
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{1}, _{it.size}).cap
|
149
|
+
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{1}, _{it.size}).cap[]
|
150
150
|
assert_equal 313, ret.values[0]
|
151
151
|
assert_equal 184, ret.values[1]
|
152
152
|
|
153
|
-
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it.out('sung_by')
|
153
|
+
ret = @g2.V.has_not('song_type', nil).group_by(_{it.song_type}, _{it.out('sung_by')[]}, _{it._.name.group_count.cap[]}).cap[]
|
154
154
|
assert_equal 66, ret[0]['cover']['Weir']
|
155
155
|
assert_equal 33, ret[0]['original']['Weir']
|
156
156
|
end
|
157
157
|
|
158
158
|
# https://github.com/tinkerpop/gremlin/wiki/Depth-First-vs.-Breadth-First
|
159
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.
|
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.
|
160
|
+
assert_equal %w(1 4 6), @g1.v(1).out_e('created').in_v.in_e('created').out_v[].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[].map(&:id)
|
162
162
|
end
|
163
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.
|
4
|
+
version: 0.0.12
|
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-
|
12
|
+
date: 2012-06-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
16
|
-
requirement: &
|
16
|
+
requirement: &70277502305260 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,13 +21,14 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70277502305260
|
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.
|
28
28
|
email:
|
29
29
|
- andyjpn@gmail.com
|
30
30
|
executables:
|
31
|
+
- juicer
|
31
32
|
- redgrape
|
32
33
|
- trellis
|
33
34
|
extensions: []
|
@@ -37,6 +38,7 @@ files:
|
|
37
38
|
- Gemfile
|
38
39
|
- README.md
|
39
40
|
- Rakefile
|
41
|
+
- bin/juicer
|
40
42
|
- bin/redgrape
|
41
43
|
- bin/trellis
|
42
44
|
- data/graph-example-1.xml
|
@@ -53,9 +55,11 @@ files:
|
|
53
55
|
- lib/red_grape/pipe/as_pipe.rb
|
54
56
|
- lib/red_grape/pipe/back_pipe.rb
|
55
57
|
- lib/red_grape/pipe/base.rb
|
58
|
+
- lib/red_grape/pipe/both_pipe.rb
|
56
59
|
- lib/red_grape/pipe/cap_pipe.rb
|
57
60
|
- lib/red_grape/pipe/context.rb
|
58
61
|
- lib/red_grape/pipe/copy_split_pipe.rb
|
62
|
+
- lib/red_grape/pipe/count_pipe.rb
|
59
63
|
- lib/red_grape/pipe/e_pipe.rb
|
60
64
|
- lib/red_grape/pipe/except_pipe.rb
|
61
65
|
- lib/red_grape/pipe/exhaust_merge_pipe.rb
|
@@ -71,6 +75,7 @@ files:
|
|
71
75
|
- lib/red_grape/pipe/in_pipe.rb
|
72
76
|
- lib/red_grape/pipe/in_v_pipe.rb
|
73
77
|
- lib/red_grape/pipe/loop_pipe.rb
|
78
|
+
- lib/red_grape/pipe/map_pipe.rb
|
74
79
|
- lib/red_grape/pipe/out_e_pipe.rb
|
75
80
|
- lib/red_grape/pipe/out_pipe.rb
|
76
81
|
- lib/red_grape/pipe/out_v_pipe.rb
|
@@ -78,6 +83,7 @@ files:
|
|
78
83
|
- lib/red_grape/pipe/property_pipe.rb
|
79
84
|
- lib/red_grape/pipe/retain_pipe.rb
|
80
85
|
- lib/red_grape/pipe/scatter_pipe.rb
|
86
|
+
- lib/red_grape/pipe/select_pipe.rb
|
81
87
|
- lib/red_grape/pipe/side_effect_pipe.rb
|
82
88
|
- lib/red_grape/pipe/transform_pipe.rb
|
83
89
|
- lib/red_grape/pipe/underscore_pipe.rb
|
@@ -89,11 +95,15 @@ files:
|
|
89
95
|
- lib/red_grape/vertex.rb
|
90
96
|
- red_grape.gemspec
|
91
97
|
- test/all.rb
|
98
|
+
- test/test_count_pipe.rb
|
92
99
|
- test/test_element.rb
|
93
100
|
- test/test_graph.rb
|
101
|
+
- test/test_map_pipe.rb
|
94
102
|
- test/test_on_the_nature_of_pipes.rb
|
103
|
+
- test/test_out_pipe.rb
|
95
104
|
- test/test_pipe.rb
|
96
105
|
- test/test_pipe_base.rb
|
106
|
+
- test/test_select_pipe.rb
|
97
107
|
- test/test_traversal_patterns.rb
|
98
108
|
- test/test_vertex.rb
|
99
109
|
homepage: https://github.com/technohippy/red-grape
|
@@ -122,10 +132,14 @@ specification_version: 3
|
|
122
132
|
summary: RedGrape - Extremely Simple GraphDB
|
123
133
|
test_files:
|
124
134
|
- test/all.rb
|
135
|
+
- test/test_count_pipe.rb
|
125
136
|
- test/test_element.rb
|
126
137
|
- test/test_graph.rb
|
138
|
+
- test/test_map_pipe.rb
|
127
139
|
- test/test_on_the_nature_of_pipes.rb
|
140
|
+
- test/test_out_pipe.rb
|
128
141
|
- test/test_pipe.rb
|
129
142
|
- test/test_pipe_base.rb
|
143
|
+
- test/test_select_pipe.rb
|
130
144
|
- test/test_traversal_patterns.rb
|
131
145
|
- test/test_vertex.rb
|