arangorb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,157 @@
1
+ # === GRAPH EDGE ===
2
+
3
+ class ArangoE < ArangoDoc
4
+ def initialize(key: nil, collection: @@collection, graph: @@graph, database: @@database, body: {}, from: nil, to: nil)
5
+ if collection.is_a?(String)
6
+ @collection = collection
7
+ elsif collection.is_a?(ArangoC)
8
+ @collection = collection.collection
9
+ else
10
+ raise "collection should be a String or an ArangoC instance, not a #{collection.class}"
11
+ end
12
+
13
+ if graph.is_a?(String)
14
+ @graph = graph
15
+ elsif graph.is_a?(ArangoG)
16
+ @graph = graph.graph
17
+ else
18
+ raise "graph should be a String or an ArangoG instance, not a #{graph.class}"
19
+ end
20
+
21
+ if database.is_a?(String)
22
+ @database = database
23
+ else
24
+ raise "database should be a String, not a #{database.class}"
25
+ end
26
+
27
+ if key.is_a?(String) || key.nil?
28
+ @key = key
29
+ unless key.nil?
30
+ body["_key"] = @key
31
+ @id = "#{@collection}/#{@key}"
32
+ end
33
+ else
34
+ raise "key should be a String, not a #{key.class}"
35
+ end
36
+
37
+ if body.is_a?(Hash)
38
+ @body = body
39
+ else
40
+ raise "body should be a Hash, not a #{body.class}"
41
+ end
42
+
43
+ if from.is_a?(String)
44
+ @body["_from"] = from
45
+ elsif from.is_a?(ArangoDoc)
46
+ @body["_from"] = from.id
47
+ elsif from.nil?
48
+ else
49
+ raise "from should be a String or an ArangoDoc instance, not a #{from.class}"
50
+ end
51
+
52
+ if to.is_a?(String)
53
+ @body["_to"] = to
54
+ elsif to.is_a?(ArangoDoc)
55
+ @body["_to"] = to.id
56
+ elsif to.nil?
57
+ else
58
+ raise "to should be a String or an ArangoDoc instance, not a #{to.class}"
59
+ end
60
+ end
61
+
62
+ attr_reader :key, :id, :body, :database, :graph, :collection
63
+
64
+ # === GET ===
65
+
66
+ def retrieve #DONE
67
+ result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@id}").parsed_response
68
+ if @@verbose
69
+ @body = result["edge"] unless result["error"]
70
+ result
71
+ else
72
+ if result["error"]
73
+ result["errorMessage"]
74
+ else
75
+ @body = result["edge"]
76
+ self
77
+ end
78
+ end
79
+ end
80
+
81
+ # === POST ====
82
+
83
+ def create(body: {}, from: @body["_from"], to: @body["_to"], waitForSync: nil) #DONE
84
+ query = {"waitForSync" => waitForSync}.delete_if{|k,v| v.nil?}
85
+ body["_key"] = @key if body["_key"].nil? && !@key.nil?
86
+ body["_from"] = from.is_a?(String) ? from : from.id
87
+ body["_to"] = to.is_a?(String) ? to : to.id
88
+ new_Document = { :body => body.to_json, :query => query }.delete_if{|k,v| v.nil?}
89
+ result = self.class.post("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@collection}", new_Document).parsed_response
90
+ self.return_result(result, body)
91
+ end
92
+ alias create_document create
93
+ alias create_vertex create
94
+
95
+ # === MODIFY ===
96
+
97
+ def replace(body: {}, waitForSync: nil)
98
+ query = { "waitForSync" => waitForSync }.delete_if{|k,v| v.nil?}
99
+ new_Document = { :body => body.to_json, :query => query }.delete_if{|k,v| v.nil?}
100
+ result = self.class.put("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@id}", new_Document).parsed_response
101
+ self.return_result(result, body)
102
+ end
103
+
104
+ def update(body: {}, waitForSync: nil, keepNull: nil) #DONE
105
+ query = {"waitForSync" => waitForSync, "keepNull" => keepNull}.delete_if{|k,v| v.nil?}
106
+ new_Document = { :body => body.to_json, :query => query }
107
+ result = self.class.patch("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@id}", new_Document).parsed_response
108
+ if @@verbose
109
+ unless result["error"]
110
+ @key = result["_key"]
111
+ @id = "#{@collection}/#{@key}"
112
+ @body = body
113
+ end
114
+ result
115
+ else
116
+ if result["error"]
117
+ result["errorMessage"]
118
+ else
119
+ @key = result["_key"]
120
+ @id = "#{@collection}/#{@key}"
121
+ @body = @body.merge(body)
122
+ self
123
+ end
124
+ end
125
+ end
126
+
127
+ # === DELETE ===
128
+
129
+ def destroy(body: nil, waitForSync: nil) #OONE
130
+ query = { "waitForSync" => waitForSync }.delete_if{|k,v| v.nil?}
131
+ new_Document = { :query => query }
132
+ result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{@id}").parsed_response
133
+ @@verbose ? result : result["error"] ? result["errorMessage"] : true
134
+ end
135
+
136
+ # === UTILITY ===
137
+
138
+ def return_result(result, body)
139
+ if @@verbose
140
+ unless result["error"]
141
+ @key = result["edge"]["_key"]
142
+ @id = "#{@collection}/#{@key}"
143
+ @body = body
144
+ end
145
+ result
146
+ else
147
+ if result["error"]
148
+ result["errorMessage"]
149
+ else
150
+ @key = result["edge"]["_key"]
151
+ @id = "#{@collection}/#{@key}"
152
+ @body = body
153
+ self
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,168 @@
1
+ # ==== GRAPH ====
2
+
3
+ class ArangoG < ArangoS
4
+ def initialize(graph: @@graph, database: @@database, edgeDefinitions: [], orphanCollections: [])
5
+ if database.is_a?(String)
6
+ @database = database
7
+ else
8
+ raise "database should be a String, not a #{collection.class}"
9
+ end
10
+
11
+ if graph.is_a?(String)
12
+ @graph = graph
13
+ ArangoS.graph = graph
14
+ else
15
+ raise "graph should be a String, not a #{graph.class}"
16
+ end
17
+
18
+ if edgeDefinitions.is_a?(Array)
19
+ @edgeDefinitions = edgeDefinitions
20
+ else
21
+ raise "edgeDefinitions should be an Array, not a #{edgeDefinitions.class}"
22
+ end
23
+
24
+ if orphanCollections.is_a?(Array)
25
+ @orphanCollections = orphanCollections
26
+ else
27
+ raise "orphanCollections should be an Array, not a #{orphanCollections.class}"
28
+ end
29
+ end
30
+
31
+ attr_reader :graph, :edgeDefinitions, :orphanCollections, :database
32
+
33
+ # === GET ===
34
+
35
+ def retrieve
36
+ result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}").parsed_response
37
+ if @@verbose
38
+ result
39
+ else
40
+ if result["error"]
41
+ result["errorMessage"]
42
+ else
43
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
44
+ @orphanCollections = result["graph"]["orphanCollections"]
45
+ self
46
+ end
47
+ end
48
+ end
49
+
50
+ # === POST ===
51
+
52
+ def create
53
+ body = { "name" => @graph, "edgeDefinitions" => @edgeDefinitions, "orphanCollections" => @orphanCollections }
54
+ new_Document = { :body => body.to_json }
55
+ result = self.class.post("/_db/#{@database}/_api/gharial", new_Document).parsed_response
56
+ @@verbose ? result : result["error"] ? result["errorMessage"] : self
57
+ end
58
+
59
+ # === DELETE ===
60
+
61
+ def destroy
62
+ result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}").parsed_response
63
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["removed"]
64
+ end
65
+
66
+ # === VERTEX COLLECTION ===
67
+
68
+ def vertexCollections
69
+ result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}/vertex").parsed_response
70
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["collections"].map{|x| ArangoC.new(collection: x)}
71
+ end
72
+
73
+ def addVertexCollection(collection:)
74
+ collection = collection.is_a?(String) ? collection : collection.collection
75
+ body = { "collection" => collection }
76
+ new_Document = { :body => body.to_json }
77
+ result = self.class.post("/_db/#{@database}/_api/gharial/#{@graph}/vertex", new_Document).parsed_response
78
+ if @@verbose
79
+ result
80
+ else
81
+ if result["error"]
82
+ result["errorMessage"]
83
+ else
84
+ @orphanCollections << collection
85
+ self
86
+ end
87
+ end
88
+ end
89
+
90
+ def removeVertexCollection(collection:)
91
+ collection = collection.is_a?(String) ? collection : collection.collection
92
+ result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}/vertex/#{collection}")
93
+ if @@verbose
94
+ result
95
+ else
96
+ if result["error"]
97
+ result["errorMessage"]
98
+ else
99
+ @orphanCollections -= [collection]
100
+ self
101
+ end
102
+ end
103
+ end
104
+
105
+ # === EDGE COLLECTION ===
106
+
107
+ def edgeCollections
108
+ result = self.class.get("/_db/#{@database}/_api/gharial/#{@graph}/edge").parsed_response
109
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["collections"].map{|x| ArangoC.new(collection: x)}
110
+ end
111
+
112
+ def addEdgeCollection(collection:, from:, to:, replace: false)
113
+ from = from.is_a?(String) ? [from] : from.is_a?(ArangoC) ? [from.collection] : from
114
+ to = to.is_a?(String) ? [to] : to.is_a?(ArangoC) ? [to.collection] : to
115
+ body = {}
116
+ collection = collection.is_a?(String) ? collection : collection.collection
117
+ body["collection"] = collection
118
+ body["from"] = from.map{|f| f.is_a?(String) ? f : f.id }
119
+ body["to"] = to.map{|t| t.is_a?(String) ? t : t.id }
120
+ new_Document = { :body => body.to_json }
121
+
122
+ if replace
123
+ result = self.class.put("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{collection}", new_Document).parsed_response
124
+ else
125
+ result = self.class.post("/_db/#{@database}/_api/gharial/#{@graph}/edge", new_Document).parsed_response
126
+ end
127
+
128
+ if @@verbose
129
+ unless result["error"]
130
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
131
+ @orphanCollections = result["graph"]["orphanCollections"]
132
+ end
133
+ result
134
+ else
135
+ if result["error"]
136
+ result["errorMessage"]
137
+ else
138
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
139
+ @orphanCollections = result["graph"]["orphanCollections"]
140
+ self
141
+ end
142
+ end
143
+ end
144
+
145
+ def replaceEdgeCollection(collection:, from:, to:)
146
+ self.addEdgeCollection(collection: collection, from: from, to: to, replace: true)
147
+ end
148
+
149
+ def removeEdgeCollection(collection:)
150
+ collection = collection.is_a?(String) ? collection : collection.collection
151
+ result = self.class.delete("/_db/#{@database}/_api/gharial/#{@graph}/edge/#{collection}")
152
+ if @@verbose
153
+ unless result["error"]
154
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
155
+ @orphanCollections = result["graph"]["orphanCollections"]
156
+ end
157
+ result
158
+ else
159
+ if result["error"]
160
+ result["errorMessage"]
161
+ else
162
+ @edgeDefinitions = result["graph"]["edgeDefinitions"]
163
+ @orphanCollections = result["graph"]["orphanCollections"]
164
+ self
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,64 @@
1
+ # === SERVER ===
2
+
3
+ class ArangoS
4
+ include HTTParty
5
+ @@verbose = false
6
+ @@database = "_system"
7
+ @@graph = nil
8
+ @@collection = nil
9
+
10
+ def self.default_server(user: "root", password:, server: "localhost", port: "8529")
11
+ base_uri "http://#{server}:#{port}"
12
+ basic_auth user, password
13
+ end
14
+
15
+ def self.verbose=(verbose)
16
+ @@verbose = verbose
17
+ end
18
+
19
+ def self.verbose
20
+ @@verbose
21
+ end
22
+
23
+ def self.database=(database)
24
+ if database.is_a? String
25
+ @@database = database
26
+ elsif database.is_a? ArangoDB
27
+ @@database = database.database
28
+ else
29
+ raise "database should be a String or an ArangoDB instance, not a #{database.class}"
30
+ end
31
+ end
32
+
33
+ def self.database
34
+ @@database
35
+ end
36
+
37
+ def self.graph=(graph)
38
+ if graph.is_a? String
39
+ @@graph = graph
40
+ elsif graph.is_a? ArangoG
41
+ @@graph = graph
42
+ else
43
+ raise "graph should be a String or an ArangoG instance, not a #{graph.class}"
44
+ end
45
+ end
46
+
47
+ def self.graph
48
+ @@graph
49
+ end
50
+
51
+ def self.collection=(collection)
52
+ if collection.is_a? String
53
+ @@collection = collection
54
+ elsif collection.is_a? ArangoC
55
+ @@collection = collection
56
+ else
57
+ raise "graph should be a String or an ArangoC instance, not a #{collection.class}"
58
+ end
59
+ end
60
+
61
+ def self.collection
62
+ @@collection
63
+ end
64
+ end
@@ -0,0 +1,132 @@
1
+ # === TRAVERSAL ===
2
+
3
+ class ArangoT < ArangoS
4
+ def initialize(body: {}, database: @@database, graph: nil, edgeCollection: nil)
5
+ @sort = body["sort"]
6
+ @direction = body["direction"]
7
+ @maxDepth = body["maxDepth"]
8
+ @minDepth = body["minDepth"]
9
+ @startVertex = body["startVertex"]
10
+ @visitor = body["visitor"]
11
+ @itemOrder = body["itemOrder"]
12
+ @strategy = body["strategy"]
13
+ @filter = body["filter"]
14
+ @init = body["init"]
15
+ @maxiterations = body["maxiterations"]
16
+ @uniqueness = body["uniqueness"]
17
+ @order = body["order"]
18
+ @graphName = body["graphName"].nil? ? graph : body["graphName"]
19
+ @expander = body["expander"]
20
+ @edgeCollection = body["edgeCollection"].nil? ? edgeCollection : body["edgeCollection"]
21
+ @database = database
22
+ @vertices = nil
23
+ @paths = nil
24
+ end
25
+
26
+ attr_accessor :sort, :direction, :maxDepth, :minDepth, :visitor, :itemOrder, :strategy, :filter, :init, :maxiterations, :uniqueness, :order, :expander, :vertices, :paths, :database
27
+ attr_reader :startVertex, :graphName, :edgeCollection
28
+
29
+ def startVertex=(startVertex)
30
+ if startVertex.is_a?(String)
31
+ @startVertex = startVertex
32
+ elsif startVertex.is_a?(ArangoDoc)
33
+ @startVertex = startVertex.id
34
+ else
35
+ raise "startVertex should be a String or an ArangoDoc instance, not a #{startVertex.class}"
36
+ end
37
+ end
38
+
39
+ def graphName=(graphName)
40
+ if graphName.is_a?(String) || graphName.nil?
41
+ @graphName = graphName
42
+ elsif graphName.is_a?(ArangoG)
43
+ @graphName = graphName.graph
44
+ else
45
+ raise "graphName should be a String or an ArangoG instance, not a #{graphName.class}"
46
+ end
47
+ end
48
+
49
+ def edgeCollection=(edgeCollection)
50
+ if edgeCollection.is_a?(String) || edgeCollection.nil?
51
+ @edgeCollection = edgeCollection
52
+ elsif edgeCollection.is_a?(ArangoC)
53
+ @edgeCollection = edgeCollection.collection
54
+ else
55
+ raise "edgeCollection should be a String or an ArangoC instance, not a #{edgeCollection.class}"
56
+ end
57
+ end
58
+
59
+ def in
60
+ @direction = "inbound"
61
+ end
62
+
63
+ def out
64
+ @direction = "outbound"
65
+ end
66
+
67
+ def any
68
+ @direction = "any"
69
+ end
70
+
71
+ alias vertex= startVertex=
72
+ alias vertex startVertex
73
+ alias max maxDepth
74
+ alias max= maxDepth=
75
+ alias min minDepth
76
+ alias min= minDepth=
77
+ alias collection edgeCollection
78
+ alias collection= edgeCollection=
79
+ alias graph graphName
80
+ alias graph= graphName=
81
+
82
+ def execute
83
+ body = {
84
+ "sort" => @sort,
85
+ "direction" => @direction,
86
+ "maxDepth" => @maxDepth,
87
+ "minDepth" => @minDepth,
88
+ "startVertex" => @startVertex,
89
+ "visitor" => @visitor,
90
+ "itemOrder" => @itemOrder,
91
+ "strategy" => @strategy,
92
+ "filter" => @filter,
93
+ "init" => @init,
94
+ "maxiterations" => @maxiterations,
95
+ "uniqueness" => @uniqueness,
96
+ "order" => @order,
97
+ "graphName" => @graphName,
98
+ "expander" => @expander,
99
+ "edgeCollection" => @edgeCollection
100
+ }.delete_if{|k,v| v.nil?}
101
+ new_Document = { :body => body.to_json }
102
+ result = self.class.post("/_db/#{@database}/_api/traversal", new_Document).parsed_response
103
+ if result["error"]
104
+ return @@verbose ? result : result["errorMessage"]
105
+ else
106
+ @vertices = result["result"]["visited"]["vertices"].map{|x| ArangoDoc.new(
107
+ key: x["_key"],
108
+ collection: x["_id"].split("/")[0],
109
+ database: @database,
110
+ body: x
111
+ )}
112
+ @paths = result["result"]["visited"]["paths"].map{|x|
113
+ { "edges" => x["edges"].map{|e| ArangoDoc.new(
114
+ key: e["_key"],
115
+ collection: e["_id"].split("/")[0],
116
+ database: @database,
117
+ body: e,
118
+ from: e["_from"],
119
+ to: e["_to"]
120
+ )},
121
+ "vertices" => x["vertices"].map{|v| ArangoDoc.new(
122
+ key: v["_key"],
123
+ collection: v["_id"].split("/")[0],
124
+ database: @database,
125
+ body: v
126
+ )}
127
+ }
128
+ }
129
+ return @@verbose ? result : self
130
+ end
131
+ end
132
+ end