wewoo 0.1.5
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 +7 -0
- data/.gitignore +21 -0
- data/Gemfile +6 -0
- data/Guardfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +176 -0
- data/Rakefile +1 -0
- data/bin/wewoo +15 -0
- data/lib/wewoo.rb +19 -0
- data/lib/wewoo/adapter.rb +58 -0
- data/lib/wewoo/configuration.rb +24 -0
- data/lib/wewoo/edge.rb +54 -0
- data/lib/wewoo/element.rb +28 -0
- data/lib/wewoo/graph.rb +233 -0
- data/lib/wewoo/result_set.rb +99 -0
- data/lib/wewoo/version.rb +3 -0
- data/lib/wewoo/vertex.rb +63 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/graph_sets.rb +33 -0
- data/spec/wewoo/edge_spec.rb +43 -0
- data/spec/wewoo/graph_spec.rb +265 -0
- data/spec/wewoo/gremlin_spec.rb +434 -0
- data/spec/wewoo/result_set_spec.rb +225 -0
- data/spec/wewoo/vertex_spec.rb +75 -0
- data/wewoo.gemspec +35 -0
- metadata +237 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Wewoo
|
4
|
+
describe Vertex do
|
5
|
+
before :all do
|
6
|
+
@g = Graph.new(:test_graph)
|
7
|
+
build_test_graph( @g )
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'equality' do
|
11
|
+
it 'validates two egdes are the same' do
|
12
|
+
expect( @v1.outE(:love) == @v1.outE(:love) ).to eq true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'validates two egdes are different' do
|
16
|
+
e1, e2 = @v1.outE(:friend).first, @v1.outE(:friend).last
|
17
|
+
|
18
|
+
expect( e1 == e2 ).to eq false
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'validates anything against null' do
|
22
|
+
expect( @v1.outE(:love) == nil ).to be false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'vertices' do
|
27
|
+
it "fetches edge head correctly" do
|
28
|
+
expect( @e1.in ).to eq @v2
|
29
|
+
end
|
30
|
+
|
31
|
+
it "fetches edge tail correctly" do
|
32
|
+
expect( @e1.out ).to eq @v1
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'deletes an edge correctly' do
|
36
|
+
before = @g.E.count()
|
37
|
+
@e1.destroy
|
38
|
+
|
39
|
+
expect( @g.E.count() ).to eq before-1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Wewoo
|
4
|
+
describe Graph do
|
5
|
+
before :all do
|
6
|
+
@g = Graph.new( :test_graph )
|
7
|
+
build_test_graph( @g )
|
8
|
+
end
|
9
|
+
|
10
|
+
context "Graphs" do
|
11
|
+
it "show all available graphs" do
|
12
|
+
expect( Graph.available_graphs ).to_not be_empty
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'opens a graph correctly' do
|
16
|
+
expect( @g.V ).to have(4).items
|
17
|
+
expect( @g.E ).to have(5).items
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'errors out if a graph does not exist' do
|
21
|
+
expect{ Graph.new( :test_yo ) }.to raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'Query' do
|
26
|
+
it 'retrieves frienships correctly' do
|
27
|
+
edges = @g.query( "g.v(#{@v1.id}).outE('friend')" )
|
28
|
+
|
29
|
+
expect( edges ).to have(2).items
|
30
|
+
expect( edges ).to eq [@e1, @e2]
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'retrieves friends correctly' do
|
34
|
+
vertices = @g.query( "g.v(#{@v1.id}).out('friend')" )
|
35
|
+
|
36
|
+
expect( vertices ).to have(2).items
|
37
|
+
expect( vertices ).to eq [@v2, @v3]
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'retrieves friends of friends correctly' do
|
41
|
+
vertices = @g.query( "g.v(#{@v1.id}).out('friend').out('friend')" )
|
42
|
+
|
43
|
+
expect( vertices ).to have(2).items
|
44
|
+
expect( vertices ).to eq [@v3, @v4]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "paginates results correctly" do
|
48
|
+
vertices = @g.query( "g.V", page:1, per_page:2 )
|
49
|
+
|
50
|
+
expect( vertices ).to have(2).items
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'Vertex' do
|
55
|
+
it 'checks for vertex existance correctly' do
|
56
|
+
v1 = @g.find_first_vertex( :gid, 1 )
|
57
|
+
|
58
|
+
expect( @g.vertex_exists?( v1.id ) ).to eq true
|
59
|
+
expect( @g.vertex_exists?( 1234 ) ).to eq false
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'creates a vertex correctly' do
|
63
|
+
v = @g.add_vertex( name:'test', age:20, gid: 100 )
|
64
|
+
vg = @g.find_vertex( v.id )
|
65
|
+
|
66
|
+
expect( vg ).to_not be_nil
|
67
|
+
expect( vg.props.age ).to eq 20
|
68
|
+
expect( vg.props.name ).to eq 'test'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'updates a vertex correctly' do
|
72
|
+
v = @g.find_first_vertex( :gid, 100 )
|
73
|
+
v_prime = @g.update_vertex( v.id, age: 30, blee:'testola', weight: 160.5 )
|
74
|
+
|
75
|
+
expect( v_prime ).to_not be_nil
|
76
|
+
expect( v_prime.props.weight ).to eq 160.5
|
77
|
+
expect( v_prime.props.name ).to eq 'test'
|
78
|
+
expect( v_prime.props.blee ).to eq 'testola'
|
79
|
+
expect( v_prime.gid ).to eq 100
|
80
|
+
expect( v_prime.props.age ).to eq 30
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'mine types' do
|
84
|
+
it 'coerve floats correctly' do
|
85
|
+
v = @g.add_vertex( weight: 18.5 )
|
86
|
+
|
87
|
+
expect( v.props.weight ).to eq 18.5
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'coerce integer correctly' do
|
91
|
+
v = @g.add_vertex( age: 30 )
|
92
|
+
|
93
|
+
expect( v.props.age ).to eq 30
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'coerce boolean correctly' do
|
97
|
+
v = @g.add_vertex( dead: false )
|
98
|
+
|
99
|
+
expect( v.props.dead ).to eq false
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'coerce array correctly' do
|
103
|
+
v = @g.add_vertex( blees: [1,2,3] )
|
104
|
+
|
105
|
+
expect( v.props.blees ).to eq [1,2,3]
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'coerce hash correctly' do
|
109
|
+
hash = {a:1,b:2,c:3}
|
110
|
+
v = @g.add_vertex( blees: hash )
|
111
|
+
|
112
|
+
expect( v.properties.blees ).to eq hash
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'coerce complex types correctly' do
|
116
|
+
hash = {a:[1,2,3],b:2.0,c:3}
|
117
|
+
v = @g.add_vertex( blees: hash )
|
118
|
+
|
119
|
+
expect( v.properties.blees ).to eq hash
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'finders' do
|
124
|
+
it 'finds a vertex by id correctly' do
|
125
|
+
expect( @g.find_vertex( @v1.id ) ).to eq @v1
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'finds a vertex by gid correctly' do
|
129
|
+
expect( @g.find_vertex_by_gid( @v1.gid ) ).to eq @v1
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'finds the first vertex matching a prop' do
|
133
|
+
expect( @g.find_first_vertex( :name, 'fred' ) ).to eq @v1
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'finds the first vertex matching a an int prop' do
|
137
|
+
expect( @g.find_first_vertex( :age, 50 ) ).to eq @v4
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'finds the first vertex matching a a float prop' do
|
141
|
+
expect( @g.find_first_vertex( :rating, 5.5 ) ).to eq @v4
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'finds the first vertex matching a boolean prop' do
|
145
|
+
expect( @g.find_first_vertex( :busy, false ) ).to eq @v2
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
# context 'deletes' do
|
150
|
+
# it 'deletes a node correctly' do
|
151
|
+
# v1 = g.add_vertex( age:18 )
|
152
|
+
# expect( g.vertices ).to have(1).item
|
153
|
+
#
|
154
|
+
# g.remove_vertex( v1.id )
|
155
|
+
#
|
156
|
+
# expect( g.V ).to be_empty
|
157
|
+
# end
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# context 'connected' do
|
161
|
+
# let!(:v2) { g.add_vertex( name:'blee', age:50 ) }
|
162
|
+
# let!(:e1) { g.add_edge( v1.id, v2.id, :friend ) }
|
163
|
+
#
|
164
|
+
# it 'deletes an origin node correctly' do
|
165
|
+
# g.remove_vertex( v1.id )
|
166
|
+
#
|
167
|
+
# expect( g.E ).to be_empty
|
168
|
+
# expect( g.V ).to have(1).item
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# it 'deletes an destination node correctly' do
|
172
|
+
# g.remove_vertex( v2.id )
|
173
|
+
#
|
174
|
+
# expect( g.E ).to be_empty
|
175
|
+
# expect( g.V ).to have(1).item
|
176
|
+
# end
|
177
|
+
# end
|
178
|
+
# end
|
179
|
+
|
180
|
+
context 'Edge' do
|
181
|
+
it 'checks for edge existance correctly' do
|
182
|
+
expect( @g.edge_exists?( @e1.id ) ).to eq true
|
183
|
+
expect( @g.edge_exists?( 1234 ) ).to eq false
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'creates an edge correctly' do
|
187
|
+
e6 = @g.add_edge( @v1, @v2, :test, city: "Denver", state: "CO")
|
188
|
+
edge = @g.find_edge( e6.id )
|
189
|
+
|
190
|
+
expect( edge.label ).to eq 'test'
|
191
|
+
expect( edge.from_id ).to eq @v1.id
|
192
|
+
expect( edge.to_id ).to eq @v2.id
|
193
|
+
expect( edge.props.city ).to eq 'Denver'
|
194
|
+
expect( edge.props.state ).to eq 'CO'
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'updates an edge correctly' do
|
198
|
+
e = @g.find_first_edge( :state, "CO" )
|
199
|
+
e_prime = @g.update_edge( e.id, name: :testola, approved: true )
|
200
|
+
|
201
|
+
expect( e_prime ).to_not be_nil
|
202
|
+
expect( e_prime.props.name ).to eq 'testola'
|
203
|
+
expect( e_prime.props.approved ).to eq true
|
204
|
+
expect( e_prime.props.city ).to eq "Denver"
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'deletes an edge correctly' do
|
208
|
+
e = @g.find_first_edge( :city, "Denver" )
|
209
|
+
@g.remove_edge( e.id )
|
210
|
+
|
211
|
+
lambda{ @g.e( e.id ) }.should raise_error Graph::GraphElementNotFoundError
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'find' do
|
215
|
+
it 'find an edge by id correctly' do
|
216
|
+
edge = @g.e( @e1.id )
|
217
|
+
|
218
|
+
expect( edge ).to eq @e1
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'find first edge by property correctly' do
|
222
|
+
edge = @g.find_first_edge( :rating, 2.5 )
|
223
|
+
|
224
|
+
expect( edge ).to eq @e2
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'find an edge by property correctly' do
|
228
|
+
edges = @g.find_edges( :rating, 5.5 )
|
229
|
+
|
230
|
+
expect( edges ).to have(2).items
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'load/save' do
|
236
|
+
it 'saves a graph correctly' do
|
237
|
+
expect( @g.save( '/tmp/test_graph.xml' ) ).to be_true
|
238
|
+
expect( File.exists?( '/tmp/test_graph.xml' ) ).to be_true
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'create sub dirs if necessary before save' do
|
242
|
+
expect( @g.save( '/tmp/graphs/test_graph.xml' ) ).to be_true
|
243
|
+
expect( File.exists?( '/tmp/graphs/test_graph.xml' ) ).to be_true
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'loads a graph correctly' do
|
247
|
+
b_count = @g.V.count
|
248
|
+
|
249
|
+
expect( @g.load( '/tmp/test_graph.xml') ).to be_true
|
250
|
+
expect( @g.V.count ).to eq b_count
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'appends a graph correctly' do
|
254
|
+
b_count = @g.V.count
|
255
|
+
|
256
|
+
expect( @g.load( '/tmp/test_graph.xml', append:true) ).to be_true
|
257
|
+
expect( @g.V.count ).to eq 2*b_count
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'raise exeption if not graphs' do
|
261
|
+
expect{ @g.load( '/tmp/test_graphico.xml')}.to raise_error
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
@@ -0,0 +1,434 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/graph_sets'
|
3
|
+
|
4
|
+
module Wewoo
|
5
|
+
describe 'Gremlin' do
|
6
|
+
before :all do
|
7
|
+
@g = Graph.new( :test_graph )
|
8
|
+
build_sample_graph( @g )
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'Transforms' do
|
12
|
+
it 'Both' do
|
13
|
+
q = "g.v(#{@v4.id}).both('knows','created')"
|
14
|
+
|
15
|
+
expect( @g.q( q ) ).to eq [@v1,@v5,@v3]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'BothE' do
|
19
|
+
q = "g.v(#{@v4.id}).bothE('knows','created')"
|
20
|
+
|
21
|
+
expect( @g.q( q ) ).to eq [@e8,@e10,@e11]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'BothV' do
|
25
|
+
q = "g.e('#{@e12.id}').bothV"
|
26
|
+
|
27
|
+
expect( @g.q( q ) ).to eq [@v6,@v3]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'Cap' do
|
31
|
+
q = "g.V('lang', 'java').in('created').name.groupCount.cap"
|
32
|
+
|
33
|
+
expect( @g.q( q ) ).to eq( {"marko"=>1, "peter"=>1, "josh"=>2} )
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'E' do
|
37
|
+
q = "g.E.weight"
|
38
|
+
|
39
|
+
expect( @g.q( q ).sort ).to eq [0.2, 0.4, 0.4, 0.5, 1, 1]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'Gather' do
|
43
|
+
q = "g.v(#{@v1.id}).out.gather"
|
44
|
+
|
45
|
+
expect( @g.q( q ) ).to eq [@v2,@v4,@v3]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "Id" do
|
49
|
+
q = "g.v(#{@v1.id}).id"
|
50
|
+
|
51
|
+
expect( @g.q( q ) ).to eq [@v1.id]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "In" do
|
55
|
+
q = "g.v(#{@v3.id}).in('created')"
|
56
|
+
|
57
|
+
expect( @g.q( q ) ).to eq [@v4, @v1, @v6]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "InE" do
|
61
|
+
q = "g.v(#{@v3.id}).inE('created')"
|
62
|
+
|
63
|
+
expect( @g.q( q ) ).to eq [@e11, @e9, @e12]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "InV" do
|
67
|
+
q = "g.e('#{@e12.id}').inV"
|
68
|
+
|
69
|
+
expect( @g.q( q ) ).to eq [@v3]
|
70
|
+
end
|
71
|
+
|
72
|
+
it "Out" do
|
73
|
+
q = "g.v(#{@v6.id}).out('created')"
|
74
|
+
|
75
|
+
expect( @g.q( q ) ).to eq [@v3]
|
76
|
+
end
|
77
|
+
|
78
|
+
it "OutE" do
|
79
|
+
q = "g.v(#{@v6.id}).outE('created')"
|
80
|
+
|
81
|
+
expect( @g.q( q ) ).to eq [@e12]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "OutV" do
|
85
|
+
q = "g.e('#{@e12.id}').outV"
|
86
|
+
|
87
|
+
expect( @g.q( q ) ).to eq [@v6]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "Key" do
|
91
|
+
q = "g.v(#{@v3.id}).getProperty('name')"
|
92
|
+
|
93
|
+
expect( @g.q( q ) ).to eq ['lop']
|
94
|
+
end
|
95
|
+
|
96
|
+
it "Label" do
|
97
|
+
q = "g.e('#{@e7.id}').label"
|
98
|
+
|
99
|
+
expect( @g.q( q ) ).to eq ['knows']
|
100
|
+
end
|
101
|
+
|
102
|
+
# pending 'LinkBoth'
|
103
|
+
|
104
|
+
it 'Map' do
|
105
|
+
q = "g.v('#{@v1.id}').map"
|
106
|
+
|
107
|
+
expect( @g.q( q ) ).to eq( {'age' => 29, 'name' => 'marko', 'gid' => @v1.id} )
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'Memoize' do
|
111
|
+
q = ["m=[:]"]
|
112
|
+
q << "g.V.out.out.memoize(1)"
|
113
|
+
q << "g.V.out.out.memoize(1,m).name"
|
114
|
+
|
115
|
+
expect( @g.q( q.join(';') ) ).to eq( ['ripple', 'lop'] )
|
116
|
+
end
|
117
|
+
|
118
|
+
it "Order" do
|
119
|
+
q = "g.V.name.order{it.b <=> it.a}"
|
120
|
+
|
121
|
+
expect( @g.q( q ) ).to eq %w[vadas ripple peter marko lop josh]
|
122
|
+
end
|
123
|
+
|
124
|
+
it "GroupCount" do
|
125
|
+
q = "g.V.both.groupCount.cap.orderMap(T.decr)"
|
126
|
+
|
127
|
+
expect( @g.q( q ).sort{ |a,b| a.id <=> b.id } ).to eq [@v1, @v2, @v3, @v4, @v5, @v6]
|
128
|
+
end
|
129
|
+
|
130
|
+
it "Path" do
|
131
|
+
q = "g.v(#{@v1.id}).out.path"
|
132
|
+
expect( @g.q( q ) ).to eq [[@v1, @v2], [@v1, @v4], [@v1, @v3]]
|
133
|
+
|
134
|
+
q = "g.v(#{@v1.id}).out.path{it.name}"
|
135
|
+
expect( @g.q( q ) ).to eq [["marko", "vadas"], ["marko", "josh"], ["marko", "lop"]]
|
136
|
+
|
137
|
+
q = "g.v(#{@v1.id}).out.path{it.id}{it.name}"
|
138
|
+
expect( @g.q( q ) ).to eq [[@v1.id, "vadas"], [@v1.id, "josh"], [@v1.id, "lop"]]
|
139
|
+
end
|
140
|
+
|
141
|
+
it "Scatter" do
|
142
|
+
q = "g.v(#{@v1.id}).out.gather{it[1..2]}"
|
143
|
+
expect( @g.q( q ) ).to eq [@v4,@v3]
|
144
|
+
|
145
|
+
q = "g.v(#{@v1.id}).out.gather{it[1..2]}.scatter"
|
146
|
+
expect( @g.q( q ) ).to eq [@v4,@v3]
|
147
|
+
end
|
148
|
+
|
149
|
+
# BOZO!! WTF x:fred ??
|
150
|
+
pending "Select", "Don't know to implement this??" do
|
151
|
+
q = "g.v(#{@v1.id}).as('x').out('knows').as('y').select"
|
152
|
+
expect( @g.q( q ) ).to eq [@v4,@v3]
|
153
|
+
end
|
154
|
+
|
155
|
+
it "Shuffle" do
|
156
|
+
q = "g.v(#{@v1.id}).out.shuffle"
|
157
|
+
expect( @g.q( q ) ).to have(3).items
|
158
|
+
end
|
159
|
+
|
160
|
+
it "Transform" do
|
161
|
+
q = "g.E.has('weight', T.gt, 0.5f).outV.age.transform{it+2}"
|
162
|
+
expect( @g.q( q ).sort ).to eq [31,34]
|
163
|
+
|
164
|
+
q = "g.E.has('weight',T.gt,0.5d).outV.transform{[name:it.name,age:it.age]}"
|
165
|
+
expect( @g.q(q).sort{ |a,b| a['name'] <=> b['name']} ).to eq(
|
166
|
+
[{'name'=>'josh','age'=>32}, {'name'=>'marko','age'=>29}] )
|
167
|
+
end
|
168
|
+
|
169
|
+
it "V" do
|
170
|
+
q = "g.V"
|
171
|
+
expect( @g.q( q ) ).to have(6).items
|
172
|
+
|
173
|
+
q = "g.V( 'name', 'marko')"
|
174
|
+
expect( @g.q( q ) ).to eq [@v1]
|
175
|
+
|
176
|
+
q = "g.V( 'name', 'marko').name"
|
177
|
+
expect( @g.q( q ) ).to eq [@v1.props.name]
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'fetch vertex names correctly' do
|
181
|
+
script = 'g.V.both.groupCount.cap.orderMap(T.decr)[0..1].name'
|
182
|
+
|
183
|
+
expect( @g.q(script) ).to have(2).items
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "Filter" do
|
188
|
+
it '[]' do
|
189
|
+
script = 'g.V[0].name'
|
190
|
+
expect( @g.q(script) ).to have(1).item
|
191
|
+
end
|
192
|
+
|
193
|
+
it '[..]' do
|
194
|
+
script = 'g.V[0..2].name'
|
195
|
+
expect( @g.q(script) ).to have(3).items
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'And' do
|
199
|
+
script = 'g.V.and(_().both("knows"), _().both("created"))'
|
200
|
+
expect( @g.q(script).sort ).to eq [@v1,@v4]
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
it 'Back' do
|
205
|
+
script = "g.V.as('x').outE('knows').inV.has('age', T.gt, 30).name.back('x')"
|
206
|
+
expect( @g.q(script) ).to eq [@v1]
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'Dedup' do
|
210
|
+
script = "g.v(#{@v1.id}).out.in.dedup()"
|
211
|
+
expect( @g.q(script) ).to eq [@v1, @v4, @v6]
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'Except' do
|
215
|
+
q = ["x = [g.v(#{@v1.id}), g.v(#{@v2.id}), g.v(#{@v3.id})]"]
|
216
|
+
q << "g.V.except(x)"
|
217
|
+
expect( @g.q(q.join(";")).sort ).to eq [@v4, @v5, @v6]
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'Filter' do
|
221
|
+
script = "g.V.filter{it.age > 29}.name"
|
222
|
+
expect( @g.q( script ).sort ).to eq %w[josh peter]
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'Has' do
|
226
|
+
script = "g.v(#{@v1.id}).outE.has('weight', T.gte, 0.5f).weight"
|
227
|
+
expect( @g.q( script ).sort ).to eq [0.5, 1.0]
|
228
|
+
end
|
229
|
+
|
230
|
+
# BOZO !! No support for full filter ??
|
231
|
+
it 'HasNot' do
|
232
|
+
script = "g.v(#{@v1.id}).outE.hasNot('name', 'marko').weight"
|
233
|
+
expect( @g.q( script ).sort ).to eq [0.4, 0.5, 1.0]
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'Interval' do
|
237
|
+
script = "g.E.interval('weight', 0.3f, 0.9f).weight"
|
238
|
+
expect( @g.q( script ).sort ).to eq [0.4, 0.4, 0.5]
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'Or' do
|
242
|
+
script = "g.V.or(_().both('knows'), _().both('created'))"
|
243
|
+
expect( @g.q( script ).sort ).to eq [@v1, @v2, @v3, @v4, @v5, @v6]
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'Random' do
|
247
|
+
script = "g.V.random(0.9)"
|
248
|
+
expect( @g.q( script ) ).to_not be_empty
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'Retain' do
|
252
|
+
q = ["x = [g.v(#{@v1.id}), g.v(#{@v2.id}), g.v(#{@v3.id})]"]
|
253
|
+
q << 'g.V.retain(x)'
|
254
|
+
expect( @g.q( q.join(';') ).sort ).to eq [@v1, @v2, @v3]
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'SimplePath' do
|
258
|
+
script = "g.v(#{@v1.id}).out.in.simplePath"
|
259
|
+
expect( @g.q( script ).sort ).to eq [@v4, @v6]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'Side Effect' do
|
264
|
+
it 'Aggregate' do
|
265
|
+
script = "x=[];g.v(#{@v1.id}).out.aggregate(x)"
|
266
|
+
expect( @g.q( script ).sort ).to eq [@v2,@v3,@v4]
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'As' do
|
270
|
+
script = "g.V.as('x').outE('knows').inV.has('age', T.gt, 30).back('x').age"
|
271
|
+
expect( @g.q( script ).sort ).to eq [29]
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'GroupBy' do
|
275
|
+
exp = {
|
276
|
+
@v1 => [@v2, @v4, @v3],
|
277
|
+
@v2 => [],
|
278
|
+
@v3 => [],
|
279
|
+
@v4 => [@v5,@v3],
|
280
|
+
@v5 => [],
|
281
|
+
@v6 => [@v3]
|
282
|
+
}
|
283
|
+
@g.q( "g.V.groupBy{it}{it.out}.cap" ).each_pair { |k,v|
|
284
|
+
expect( v ).to eq exp[k]
|
285
|
+
}
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'GroupCount' do
|
289
|
+
exp = {
|
290
|
+
@v2 => 1,
|
291
|
+
@v4 => 1,
|
292
|
+
@v3 => 3,
|
293
|
+
@v5 => 1
|
294
|
+
}
|
295
|
+
q = "x=[:];g.V.out.groupCount(x).cap"
|
296
|
+
@g.q( q ).each_pair { |k,v| expect( v ).to eq exp[k] }
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'Optional' do
|
300
|
+
script = "g.V.as('x').outE('knows').inV.has('age', T.gt, 30).optional('x')"
|
301
|
+
expect( @g.q( script ).sort ).to eq [@v1,@v2,@v3,@v4,@v5,@v6]
|
302
|
+
end
|
303
|
+
|
304
|
+
pending 'SideEffect' do
|
305
|
+
q = ["y = 1000"]
|
306
|
+
q << "g.V.has('age').sideEffect{y=y>it.age?it.age:y}"
|
307
|
+
q << "y"
|
308
|
+
expect( @g.q( q.join(";") ) ).to eq 27
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'Store' do
|
312
|
+
q = "x=[];g.v(#{@v1.id}).out.store(x).next();x"
|
313
|
+
expect( @g.q( q ) ).to eq [@v2]
|
314
|
+
end
|
315
|
+
|
316
|
+
pending 'Table' do
|
317
|
+
q = "t= new Table();g.V.as('x').name.as('name').back('x').age.as('age').table(t);t"
|
318
|
+
expect( @g.q( q ) ).to eq [@v2]
|
319
|
+
end
|
320
|
+
|
321
|
+
pending 'Tree'
|
322
|
+
end
|
323
|
+
|
324
|
+
context 'Branch' do
|
325
|
+
it 'CopySplit'do
|
326
|
+
q = "g.v(#{@v1.id}).out('knows').copySplit(_().out('created').name, _().age)"
|
327
|
+
expect( @g.q( q ) ).to eq [@v2,@v4]
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'ExhaustMerge' do
|
331
|
+
q = "g.v(#{@v1.id}).out('knows').copySplit(_().out('created').name, _().age).exhaustMerge"
|
332
|
+
expect( @g.q( q ) ).to eq ['ripple', 'lop', 27, 32]
|
333
|
+
end
|
334
|
+
|
335
|
+
it 'FairMerge' do
|
336
|
+
q = "g.v(#{@v1.id}).out('knows').copySplit(_().out('created').name, _().age).fairMerge"
|
337
|
+
expect( @g.q( q ) ).to eq ['ripple', 27, 'lop', 32]
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'IfThenElse' do
|
341
|
+
q = "g.v(#{@v1.id}).out.ifThenElse{it.name=='josh'}{it.age}{it.name}"
|
342
|
+
expect( @g.q( q ) ).to eq ['vadas', 32, 'lop']
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'Loop' do
|
346
|
+
q = "g.v(#{@v1.id}).out.loop(1){it.loops<3}{it.object.name=='josh'} "
|
347
|
+
expect( @g.q( q ) ).to eq [@v4]
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'Methods' do
|
352
|
+
it 'Keys' do
|
353
|
+
q = "g.v(#{@v1.id}).keys()"
|
354
|
+
expect( @g.q( q ) ).to eq %w[name age gid]
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'Remove' do
|
358
|
+
expect( @g.q( "g.E.has('label','test').remove()" ) ).to be true
|
359
|
+
end
|
360
|
+
|
361
|
+
it 'Values' do
|
362
|
+
q = "g.v(#{@v1.id}).values()"
|
363
|
+
expect( @g.q( q ) ).to eq ['marko', 29, @v1.id]
|
364
|
+
end
|
365
|
+
|
366
|
+
it 'AddEdge' do
|
367
|
+
q = "v1=g.v(#{@v1.id});v2=g.v(#{@v2.id});g.addEdge(v1, v2, 'test')"
|
368
|
+
expect( @g.q(q) ).to have(1).item
|
369
|
+
end
|
370
|
+
|
371
|
+
it 'RemoveEdge' do
|
372
|
+
q = "g.removeEdge( g.E.has('label', 'test').next() )"
|
373
|
+
expect( @g.q(q) ).to eq true
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'AddVertex' do
|
377
|
+
q = "g.addVertex( name: 'Fred' )"
|
378
|
+
expect( @g.q(q) ).to have(1).item
|
379
|
+
end
|
380
|
+
|
381
|
+
it 'RemoveVertex' do
|
382
|
+
q = "g.removeVertex( g.V.has('name', 'Fred').next() )"
|
383
|
+
expect( @g.q(q) ).to eq true
|
384
|
+
end
|
385
|
+
|
386
|
+
pending 'idx'
|
387
|
+
pending 'CreateIndex' do
|
388
|
+
q = "g.createIndex('test_index', Vertex.class)"
|
389
|
+
expect( @g.q(q) ).to eq []
|
390
|
+
end
|
391
|
+
|
392
|
+
it 'e' do
|
393
|
+
q = "g.e('#{@e9.id}', '#{@e10.id}', '#{@e11.id}')"
|
394
|
+
expect( @g.q( q ) ).to eq [@e9,@e10,@e11]
|
395
|
+
end
|
396
|
+
|
397
|
+
it 'v' do
|
398
|
+
q = "g.v(#{@v1.id}, #{@v2.id}, #{@v3.id})"
|
399
|
+
expect( @g.q( q ) ).to eq [@v1,@v2,@v3]
|
400
|
+
end
|
401
|
+
|
402
|
+
it 'EnablePath' do
|
403
|
+
q = "g.v(#{@v1.id}).out.loop(1){it.loops < 3}{it.path.contains(g.v(#{@v4.id}))}.enablePath()"
|
404
|
+
expect( @g.q(q) ).to eq [@v5,@v3]
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'Fill' do
|
408
|
+
q = "x=[];g.v(#{@v1.id}).out.fill(x)"
|
409
|
+
expect( @g.q(q) ).to eq [@v2,@v4,@v3]
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'Iterate' do
|
413
|
+
q = "g.V.sideEffect{it.name='same'}.iterate();g.V.name"
|
414
|
+
expect( @g.q(q) ).to eq %w[same]*6
|
415
|
+
end
|
416
|
+
|
417
|
+
it 'Next' do
|
418
|
+
q = "g.V.sideEffect{it.name='same'}.next(3);g.V.name"
|
419
|
+
expect( @g.q(q) ).to eq %w[same]*6
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'Save' do
|
423
|
+
@g.q( "g.saveGraphML('/tmp/graph_test.xml')" )
|
424
|
+
expect( File.exists?( '/tmp/graph_test.xml') ).to eq true
|
425
|
+
end
|
426
|
+
|
427
|
+
it 'Load' do
|
428
|
+
@g.clear
|
429
|
+
@g.q( "g.loadGraphML('/tmp/graph_test.xml')")
|
430
|
+
expect( @g.V.count ).to eq 6
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
end
|