arangorb 0.1.0

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.
@@ -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