arangorb 1.2.0 → 1.3.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/ArangoRB.gemspec +18 -18
  3. data/Gemfile +8 -7
  4. data/LICENSE +21 -21
  5. data/README.md +906 -867
  6. data/lib/ArangoRB_AQL.rb +181 -160
  7. data/lib/ArangoRB_Cache.rb +174 -174
  8. data/lib/ArangoRB_Col.rb +526 -499
  9. data/lib/ArangoRB_DB.rb +363 -339
  10. data/lib/ArangoRB_Doc.rb +319 -298
  11. data/lib/ArangoRB_Edg.rb +184 -169
  12. data/lib/ArangoRB_Gra.rb +201 -180
  13. data/lib/ArangoRB_Index.rb +135 -115
  14. data/lib/ArangoRB_Replication.rb +261 -0
  15. data/lib/ArangoRB_Ser.rb +446 -441
  16. data/lib/ArangoRB_Task.rb +129 -113
  17. data/lib/ArangoRB_Tra.rb +169 -142
  18. data/lib/ArangoRB_Tran.rb +68 -53
  19. data/lib/ArangoRB_User.rb +149 -136
  20. data/lib/ArangoRB_Ver.rb +162 -147
  21. data/lib/arangorb.rb +16 -15
  22. data/spec/arangoRB_helper.rb +4 -4
  23. data/spec/arangoRestart_helper.rb +14 -14
  24. data/spec/lib/0.1.0/arangoAQL_helper.rb +64 -64
  25. data/spec/lib/0.1.0/arangoC_helper.rb +170 -170
  26. data/spec/lib/0.1.0/arangoDB_helper.rb +119 -119
  27. data/spec/lib/0.1.0/arangoDoc_helper.rb +79 -79
  28. data/spec/lib/0.1.0/arangoE_helper.rb +50 -50
  29. data/spec/lib/0.1.0/arangoG_helper.rb +78 -78
  30. data/spec/lib/0.1.0/arangoS_helper.rb +37 -37
  31. data/spec/lib/0.1.0/arangoT_helper.rb +48 -48
  32. data/spec/lib/0.1.0/arangoV_helper.rb +65 -65
  33. data/spec/lib/1.0.0/arangoC_helper.rb +73 -73
  34. data/spec/lib/1.0.0/arangoDB_helper.rb +48 -48
  35. data/spec/lib/1.0.0/arangoI_helper.rb +43 -43
  36. data/spec/lib/1.0.0/arangoS_helper.rb +192 -192
  37. data/spec/lib/1.0.0/arangoTa_helper.rb +49 -49
  38. data/spec/lib/1.0.0/arangoTr_helper.rb +15 -15
  39. data/spec/lib/1.0.0/arangoU_helper.rb +72 -72
  40. data/spec/lib/1.1.0/arangoRB_helper.rb +144 -144
  41. data/spec/lib/1.1.0/arangoRB_walks_helper.rb +19 -19
  42. data/spec/lib/1.2.0/arangoCache_helper.rb +66 -66
  43. data/spec/lib/1.3.0/arangoHash_helper.rb +30 -0
  44. data/spec/lib/arangoRB_0.1.0_helper.rb +9 -9
  45. data/spec/lib/arangoRB_1.0.0_helper.rb +6 -6
  46. data/spec/lib/arangoRB_1.1.0_helper.rb +2 -2
  47. data/spec/lib/arangoRB_1.2.0_helper.rb +2 -1
  48. data/spec/spec_helper.rb +41 -41
  49. metadata +6 -5
@@ -1,499 +1,526 @@
1
- # === COLLECTION ===
2
-
3
- class ArangoCollection < ArangoServer
4
- def initialize(collection: @@collection, database: @@database, body: {}, type: nil) # TESTED
5
- if collection.is_a?(String)
6
- @collection = collection
7
- elsif collection.is_a?(ArangoCollection)
8
- @collection = collection.collection
9
- else
10
- raise "collection should be a String or an ArangoCollection instance, not a #{collection.class}"
11
- end
12
-
13
- if database.is_a?(String)
14
- @database = database
15
- elsif database.is_a?(ArangoDatabase)
16
- @database = database.database
17
- else
18
- raise "database should be a String or an ArangoDatabase instance, not a #{database.class}"
19
- end
20
-
21
- if body.is_a?(Hash)
22
- @body = body
23
- else
24
- raise "body should be a Hash, not a #{body.class}"
25
- end
26
-
27
- if !@type.nil? && @type != "Document" && @type != "Edge"
28
- raise "type should be \"Document\" or \"Edge\""
29
- else
30
- @type = type
31
- if @type == "Document"
32
- @body["type"] = 2
33
- elsif @type == "Edge"
34
- @body["type"] = 3
35
- end
36
- end
37
- @idCache = "COL_#{@collection}"
38
- end
39
-
40
- attr_reader :collection, :body, :type, :idCache
41
- alias name collection
42
-
43
- # === RETRIEVE ===
44
-
45
- def [](document_name)
46
- ArangoDocument.new(key: document_name, collection: @collection, database: @database)
47
- end
48
- alias document []
49
-
50
- def database
51
- ArangoDatabase.new(database: @database)
52
- end
53
-
54
- # === GET ===
55
-
56
- def retrieve # TESTED
57
- result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}", @@request)
58
- self.return_result result: result, checkType: true
59
- end
60
-
61
- def properties # TESTED
62
- result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/properties", @@request)
63
- result = self.return_result result: result
64
- return result.is_a?(ArangoCollection) ? result.body : result
65
- end
66
-
67
- def count # TESTED
68
- result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/count", @@request)
69
- self.return_result result: result, key: "count"
70
- end
71
-
72
- def statistics # TESTED
73
- result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/figures", @@request)
74
- self.return_result result: result, key: "figures"
75
- end
76
-
77
- def revision # TESTED
78
- result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/revision", @@request)
79
- self.return_result result: result, key: "revision"
80
- end
81
-
82
- def checksum(withRevisions: nil, withData: nil) # TESTED
83
- query = {
84
- "withRevisions": withRevisions,
85
- "withData": withData
86
- }.delete_if{|k,v| v.nil?}
87
- request = @@request.merge({ :query => query })
88
- result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/checksum", request)
89
- self.return_result result: result, key: "checksum"
90
- end
91
-
92
- # === POST ===
93
-
94
- def create(type: nil, journalSize: nil, keyOptions: nil, waitForSync: nil, doCompact: nil, isVolatile: nil, shardKeys: nil, numberOfShards: nil, isSystem: nil, indexBuckets: nil) # TESTED
95
- type = 3 if type == "Edge"
96
- type = nil if type == "Document"
97
- body = {
98
- "name" => collection,
99
- "type" => type,
100
- "journalSize" => journalSize,
101
- "keyOptions" => keyOptions,
102
- "waitForSync" => waitForSync,
103
- "doCompact" => doCompact,
104
- "isVolatile" => isVolatile,
105
- "shardKeys" => shardKeys,
106
- "numberOfShards" => numberOfShards,
107
- "isSystem" => isSystem,
108
- "indexBuckets" => indexBuckets
109
- }
110
- body = body.delete_if{|k,v| v.nil?}.to_json
111
- request = @@request.merge({ :body => body })
112
- result = self.class.post("/_db/#{@database}/_api/collection", request)
113
- self.return_result result: result, checkType: true
114
- end
115
- alias create_collection create
116
- alias create_document_collection create
117
- alias create_vertex_collection create
118
-
119
- def create_edge_collection(journalSize: nil, keyOptions: nil, waitForSync: nil, doCompact: nil, isVolatile: nil, shardKeys: nil, numberOfShards: nil, isSystem: nil, indexBuckets: nil) # TESTED
120
- self.create type: 3, journalSize: journalSize, keyOptions: keyOptions, waitForSync: waitForSync, doCompact: doCompact, isVolatile: isVolatile, shardKeys: shardKeys, numberOfShards: numberOfShards, isSystem: isSystem, indexBuckets: indexBuckets
121
- end
122
-
123
- def create_document(document: {}, waitForSync: nil, returnNew: nil) # TESTED
124
- ArangoDocument.create(body: document, waitForSync: waitForSync, returnNew: returnNew, database: @database, collection: @collection)
125
- end
126
- alias create_vertex create_document
127
-
128
- def create_edge(document: {}, from:, to:, waitForSync: nil, returnNew: nil) # TESTED
129
- ArangoDocument.create_edge(body: document, from: from, to: to, waitForSync: waitForSync, returnNew: returnNew, database: @database, collection: @collection)
130
- end
131
-
132
- # === DELETE ===
133
-
134
- def destroy # TESTED
135
- result = self.class.delete("/_db/#{@database}/_api/collection/#{@collection}", @@request)
136
- self.return_result result: result, caseTrue: true
137
- end
138
-
139
- def truncate # TESTED
140
- result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/truncate", @@request)
141
- self.return_result result: result
142
- end
143
-
144
- # === MODIFY ===
145
-
146
- def load # TESTED
147
- result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/load", @@request)
148
- self.return_result result: result
149
- end
150
-
151
- def unload # TESTED
152
- result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/unload", @@request)
153
- self.return_result result: result
154
- end
155
-
156
- def change(waitForSync: nil, journalSize: nil) # TESTED
157
- body = {
158
- "journalSize" => journalSize,
159
- "waitForSync" => waitForSync
160
- }
161
- body = body.delete_if{|k,v| k.nil?}.to_json
162
- request = @@request.merge({ :body => body })
163
- result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/properties", request)
164
- self.return_result result: result
165
- end
166
-
167
- def rename(newName) # TESTED
168
- body = { "name" => newName }
169
- request = @@request.merge({ :body => body.to_json })
170
- result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/rename", request)
171
- @collection = newName unless result.parsed_response["error"]
172
- self.return_result result: result
173
- end
174
-
175
- def rotate
176
- result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/rotate", @@request)
177
- self.return_result result: result, caseTrue: true
178
- end
179
-
180
- # === SIMPLE FUNCTIONS ===
181
-
182
- def documents(type: nil) # "path", "id", "key" # TESTED
183
- body = {
184
- "collection" => @collection,
185
- "type" => type
186
- }.delete_if{|k,v| v.nil?}.to_json
187
- request = @@request.merge({ :body => body })
188
- result = self.class.put("/_db/#{@database}/_api/simple/all-keys", request)
189
- return result.headers["x-arango-async-id"] if @@async == "store"
190
- result = result.parsed_response
191
- if type.nil?
192
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| value = self.class.get(x).parsed_response; ArangoDocument.new(key: value["_key"], collection: @collection, body: value)}
193
- else
194
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"]
195
- end
196
- end
197
-
198
- def allDocuments(skip: nil, limit: nil, batchSize: nil) # TESTED
199
- body = {
200
- "collection" => @collection,
201
- "skip" => skip,
202
- "limit" => limit,
203
- "batchSize" => batchSize
204
- }.delete_if{|k,v| v.nil?}.to_json
205
- request = @@request.merge({ :body => body })
206
- result = self.class.put("/_db/#{@database}/_api/simple/all", request)
207
- result.headers["x-arango-async-id"] if @@async == "store"
208
- result = result.parsed_response
209
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, body: x)}
210
- end
211
-
212
- def documentsMatch(match:, skip: nil, limit: nil, batchSize: nil) # TESTED
213
- body = {
214
- "collection" => @collection,
215
- "example" => match,
216
- "skip" => skip,
217
- "limit" => limit,
218
- "batchSize" => batchSize
219
- }.delete_if{|k,v| v.nil?}.to_json
220
- request = @@request.merge({ :body => body })
221
- result = self.class.put("/_db/#{@database}/_api/simple/by-example", request)
222
- return result.headers["x-arango-async-id"] if @@async == "store"
223
- result = result.parsed_response
224
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, body: x)}
225
- end
226
-
227
- def documentMatch(match:) # TESTED
228
- body = {
229
- "collection" => @collection,
230
- "example" => match
231
- }.delete_if{|k,v| v.nil?}.to_json
232
- request = @@request.merge({ :body => body })
233
- result = self.class.put("/_db/#{@database}/_api/simple/first-example", request)
234
- return result.headers["x-arango-async-id"] if @@async == "store"
235
- result = result.parsed_response
236
- @@verbose ? result : result["error"] ? result["errorMessage"] : ArangoDocument.new(key: result["document"]["_key"], collection: @collection, body: result["document"])
237
- end
238
-
239
- def documentByKeys(keys:) # TESTED
240
- keys = keys.map{|x| x.is_a?(String) ? x : x.is_a?(ArangoDocument) ? x.key : nil} if keys.is_a? Array
241
- keys = [keys] if keys.is_a? String
242
- body = { "collection" => @collection, "keys" => keys }
243
- request = @@request.merge({ :body => body.to_json })
244
- result = self.class.put("/_db/#{@database}/_api/simple/lookup-by-keys", request)
245
- return result.headers["x-arango-async-id"] if @@async == "store"
246
- result = result.parsed_response
247
- @@verbose ? result : result["error"] ? result["errorMessage"] : result["documents"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, body: x)}
248
- end
249
-
250
- def random # TESTED
251
- body = { "collection" => @collection }.to_json
252
- request = @@request.merge({ :body => body })
253
- result = self.class.put("/_db/#{@database}/_api/simple/any", request)
254
- return result.headers["x-arango-async-id"] if @@async == "store"
255
- result = result.parsed_response
256
- @@verbose ? result : result["error"] ? result["errorMessage"] : ArangoDocument.new(key: result["document"]["_key"], collection: @collection, body: result["document"])
257
- end
258
-
259
- def removeByKeys(keys:, options: nil) # TESTED
260
- keys = keys.map{|x| x.is_a?(String) ? x : x.is_a?(ArangoDocument) ? x.key : nil}
261
- body = { "collection" => @collection, "keys" => keys, "options" => options }.delete_if{|k,v| v.nil?}.to_json
262
- request = @@request.merge({ :body => body })
263
- result = self.class.put("/_db/#{@database}/_api/simple/remove-by-keys", request)
264
- self.return_result result: result, key: "removed"
265
- end
266
-
267
- def removeMatch(match:, options: nil) # TESTED
268
- body = {
269
- "collection" => @collection,
270
- "example" => match,
271
- "options" => options
272
- }.delete_if{|k,v| v.nil?}.to_json
273
- request = @@request.merge({ :body => body })
274
- result = self.class.put("/_db/#{@database}/_api/simple/remove-by-example", request)
275
- self.return_result result: result, key: "deleted"
276
- end
277
-
278
- def replaceMatch(match:, newValue:, options: nil) # TESTED
279
- body = {
280
- "collection" => @collection,
281
- "example" => match,
282
- "options" => options,
283
- "newValue" => newValue
284
- }.delete_if{|k,v| v.nil?}.to_json
285
- request = @@request.merge({ :body => body })
286
- result = self.class.put("/_db/#{@database}/_api/simple/replace-by-example", request)
287
- self.return_result result: result, key: "replaced"
288
- end
289
-
290
- def updateMatch(match:, newValue:, options: nil) # TESTED
291
- body = {
292
- "collection" => @collection,
293
- "example" => match,
294
- "options" => options,
295
- "newValue" => newValue
296
- }.delete_if{|k,v| v.nil?}.to_json
297
- request = @@request.merge({ :body => body })
298
- result = self.class.put("/_db/#{@database}/_api/simple/update-by-example", request)
299
- self.return_result result: result, key: "updated"
300
- end
301
-
302
- # === IMPORT ===
303
-
304
- def import(attributes:, values:, from: nil, to: nil, overwrite: nil, waitForSync: nil, onDuplicate: nil, complete: nil, details: nil) # TESTED
305
- query = {
306
- "collection": @collection,
307
- "fromPrefix": from,
308
- "toPrefix": to,
309
- "overwrite": overwrite,
310
- "waitForSync": waitForSync,
311
- "onDuplicate": onDuplicate,
312
- "complete": complete,
313
- "details": details
314
- }.delete_if{|k,v| v.nil?}
315
- body = "#{attributes}\n"
316
- values[0].is_a?(Array) ? values.each{|x| body += "#{x}\n"} : body += "#{values}\n"
317
- request = @@request.merge({ :body => body, :query => query })
318
- result = self.class.post("/_db/#{@database}/_api/import", request)
319
- return result.headers["x-arango-async-id"] if @@async == "store"
320
- result = result.parsed_response
321
- @@verbose ? result : result["error"] ? result["errorMessage"] : result.delete_if{|k,v| k == "error" || k == "code"}
322
- end
323
-
324
- def importJSON(body:, type: "auto", from: nil, to: nil, overwrite: nil, waitForSync: nil, onDuplicate: nil, complete: nil, details: nil) # TESTED
325
- query = {
326
- "collection": @collection,
327
- "type": type,
328
- "fromPrefix": from,
329
- "toPrefix": to,
330
- "overwrite": overwrite,
331
- "waitForSync": waitForSync,
332
- "onDuplicate": onDuplicate,
333
- "complete": complete,
334
- "details": details
335
- }.delete_if{|k,v| v.nil?}
336
- request = @@request.merge({ :body => body.to_json, :query => query })
337
- result = self.class.post("/_db/#{@database}/_api/import", request)
338
- return result.headers["x-arango-async-id"] if @@async == "store"
339
- result = result.parsed_response
340
- @@verbose ? result : result["error"] ? result["errorMessage"] : result.delete_if{|k,v| k == "error" || k == "code"}
341
- end
342
-
343
- # === EXPORT ===
344
-
345
- def export(count: nil, restrict: nil, batchSize: nil, flush: nil, limit: nil, ttl: nil) # TESTED
346
- query = { "collection": @collection }
347
- body = {
348
- "count" => count,
349
- "restrict" => restrict,
350
- "batchSize" => batchSize,
351
- "flush" => flush,
352
- "limit" => limit,
353
- "ttl" => ttl
354
- }.delete_if{|k,v| v.nil?}
355
- request = @@request.merge({ :body => body.to_json, :query => query })
356
- result = self.class.post("/_db/#{@database}/_api/export", request)
357
- return result.headers["x-arango-async-id"] if @@async == "store"
358
- result = result.parsed_response
359
- return @@verbose ? result : result["errorMessage"] if result["error"]
360
- @countExport = result["count"]
361
- @hasMoreExport = result["hasMore"]
362
- @idExport = result["id"]
363
- if(result["result"][0].nil? || !result["result"][0].is_a?(Hash) || !result["result"][0].key?("_key"))
364
- result = result["result"]
365
- else
366
- result = result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, database: @database, body: x)}
367
- end
368
- result
369
- end
370
-
371
- def exportNext # TESTED
372
- unless @hasMoreExport
373
- print "No other results"
374
- else
375
- query = { "collection": @collection }
376
- request = @@request.merge({ :query => query })
377
- result = self.class.put("/_db/#{@database}/_api/cursor/#{@idExport}", request)
378
- return result.headers["x-arango-async-id"] if @@async == "store"
379
- result = result.parsed_response
380
- return @@verbose ? result : result["errorMessage"] if result["error"]
381
- @countExport = result["count"]
382
- @hasMoreExport = result["hasMore"]
383
- @idExport = result["id"]
384
- if(result["result"][0].nil? || !result["result"][0].is_a?(Hash) || !result["result"][0].key?("_key"))
385
- result = result["result"]
386
- else
387
- result = result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, database: @database, body: x)}
388
- end
389
- result
390
- end
391
- end
392
-
393
- # === INDEXES ===
394
-
395
- # def retrieveIndex(id:) # TESTED
396
- # result = self.class.get("/_db/#{@database}/_api/index/#{@collection}/#{id}", @@request)
397
- # if @@async == "store"
398
- # result.headers["x-arango-async-id"]
399
- # else
400
- # result = result.parsed_response
401
- # if @@verbose
402
- # result
403
- # else
404
- # if result["error"]
405
- # result["errorMessage"]
406
- # else
407
- # ArangoIndex.new(body: result, id: result["id"], database: @database, collection: @collection, type: result["type"], unique: result["unique"], fields: result["fields"])
408
- # end
409
- # end
410
- # end
411
- # end
412
-
413
- def indexes # TESTED
414
- query = { "collection": @collection }
415
- request = @@request.merge({ :query => query })
416
- result = self.class.get("/_db/#{@database}/_api/index", request)
417
- return result.headers["x-arango-async-id"] if @@async == "store"
418
- result = result.parsed_response
419
- return result if @@verbose
420
- return result["errorMessage"] if result["error"]
421
- result.delete_if{|k,v| k == "error" || k == "code"}
422
- result["indexes"] = result["indexes"].map{|x| ArangoIndex.new(body: x, id: x["id"], database: @database, collection: @collection, type: x["type"], unique: x["unique"], fields: x["fields"])}
423
- result
424
- end
425
-
426
- def createIndex(body: {}, unique: nil, type:, fields:, id: nil) # TESTED
427
- body["fields"] = fields.is_a?(Array) ? fields : [fields]
428
- body["unique"] = unique unless unique.nil?
429
- body["type"] = type unless type.nil?
430
- body["id"] = id unless type.nil?
431
- query = { "collection": @collection }
432
- request = @@request.merge({ :body => body.to_json, :query => query })
433
- result = self.class.post("/_db/#{@database}/_api/index", request)
434
- return result.headers["x-arango-async-id"] if @@async == "store"
435
- result = result.parsed_response
436
- @@verbose ? result : result["error"] ? result["errorMessage"] : ArangoIndex.new(body: result, id: result["id"], database: @database, collection: @collection, type: result["type"], unique: result["unique"], fields: result["fields"])
437
- end
438
- #
439
- # def deleteIndex(id:) # TESTED
440
- # result = self.class.delete("/_db/#{@database}/_api/index/#{@collection}/#{id}", @@request)
441
- # if @@async == "store"
442
- # result.headers["x-arango-async-id"]
443
- # else
444
- # result = result.parsed_response
445
- # if @@verbose
446
- # result
447
- # else
448
- # if result["error"]
449
- # result["errorMessage"]
450
- # else
451
- # true
452
- # end
453
- # end
454
- # end
455
- # end
456
-
457
- # === REPLICATION ===
458
-
459
- def data(from: nil, to: nil, chunkSize: nil, includeSystem: false, failOnUnknown: nil, ticks: nil, flush: nil) # TESTED
460
- query = {
461
- "collection": @collection,
462
- "from": from,
463
- "to": to,
464
- "chunkSize": chunkSize,
465
- "includeSystem": includeSystem,
466
- "failOnUnknown": failOnUnknown,
467
- "ticks": ticks,
468
- "flush": flush
469
- }.delete_if{|k,v| v.nil?}
470
- request = @@request.merge({ :query => query })
471
- result = self.class.get("/_db/#{@database}/_api/replication/dump", request)
472
- return result.headers["x-arango-async-id"] if @@async == "store"
473
- result = result.parsed_response
474
- @@verbose ? result : result["error"] ? result["errorMessage"] : result
475
- end
476
-
477
- # === UTILITY ===
478
-
479
- def return_result(result:, caseTrue: false, key: nil, checkType: false)
480
- return result.headers["x-arango-async-id"] if @@async == "store"
481
- result = result.parsed_response
482
- if @@verbose || !result.is_a?(Hash)
483
- resultTemp = result
484
- unless result["errorMessage"]
485
- result.delete_if{|k,v| k == "error" || k == "code"}
486
- @body = result
487
- @type = result["type"] == 2 ? "Document" : "Edge" if(checkType)
488
- end
489
- resultTemp
490
- else
491
- return result["errorMessage"] if result["error"]
492
- return true if caseTrue
493
- result.delete_if{|k,v| k == "error" || k == "code"}
494
- @body = result
495
- @type = result["type"] == 2 ? "Document" : "Edge" if(checkType)
496
- key.nil? ? self : result[key]
497
- end
498
- end
499
- end
1
+ # === COLLECTION ===
2
+
3
+ class ArangoCollection < ArangoServer
4
+ def initialize(collection: @@collection, database: @@database, body: {}, type: nil) # TESTED
5
+ if collection.is_a?(String)
6
+ @collection = collection
7
+ elsif collection.is_a?(ArangoCollection)
8
+ @collection = collection.collection
9
+ else
10
+ raise "collection should be a String or an ArangoCollection instance, not a #{collection.class}"
11
+ end
12
+
13
+ if database.is_a?(String)
14
+ @database = database
15
+ elsif database.is_a?(ArangoDatabase)
16
+ @database = database.database
17
+ else
18
+ raise "database should be a String or an ArangoDatabase instance, not a #{database.class}"
19
+ end
20
+
21
+ if body.is_a?(Hash)
22
+ @body = body
23
+ else
24
+ raise "body should be a Hash, not a #{body.class}"
25
+ end
26
+
27
+ if !@type.nil? && @type != "Document" && @type != "Edge"
28
+ raise "type should be \"Document\" or \"Edge\""
29
+ else
30
+ @type = type
31
+ if @type == "Document"
32
+ @body["type"] = 2
33
+ elsif @type == "Edge"
34
+ @body["type"] = 3
35
+ end
36
+ end
37
+ @idCache = "COL_#{@collection}"
38
+ end
39
+
40
+ attr_reader :collection, :body, :type, :idCache
41
+ alias name collection
42
+
43
+ # === RETRIEVE ===
44
+
45
+ def to_hash
46
+ {
47
+ "collection" => @collection,
48
+ "database" => @database,
49
+ "type" => @type,
50
+ "body" => @body,
51
+ "idCache" => @idCache
52
+ }.delete_if{|k,v| v.nil?}
53
+ end
54
+ alias to_h to_hash
55
+
56
+ def [](document_name)
57
+ ArangoDocument.new(key: document_name, collection: @collection, database: @database)
58
+ end
59
+ alias document []
60
+
61
+ def database
62
+ ArangoDatabase.new(database: @database)
63
+ end
64
+
65
+ # === GET ===
66
+
67
+ def retrieve # TESTED
68
+ result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}", @@request)
69
+ self.return_result result: result, checkType: true
70
+ end
71
+
72
+ def properties # TESTED
73
+ result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/properties", @@request)
74
+ result = self.return_result result: result
75
+ return result.is_a?(ArangoCollection) ? result.body : result
76
+ end
77
+
78
+ def count # TESTED
79
+ result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/count", @@request)
80
+ self.return_result result: result, key: "count"
81
+ end
82
+
83
+ def statistics # TESTED
84
+ result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/figures", @@request)
85
+ self.return_result result: result, key: "figures"
86
+ end
87
+
88
+ def revision # TESTED
89
+ result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/revision", @@request)
90
+ self.return_result result: result, key: "revision"
91
+ end
92
+
93
+ def checksum(withRevisions: nil, withData: nil) # TESTED
94
+ query = {
95
+ "withRevisions": withRevisions,
96
+ "withData": withData
97
+ }.delete_if{|k,v| v.nil?}
98
+ request = @@request.merge({ :query => query })
99
+ result = self.class.get("/_db/#{@database}/_api/collection/#{@collection}/checksum", request)
100
+ self.return_result result: result, key: "checksum"
101
+ end
102
+
103
+ # === POST ===
104
+
105
+ def create(type: nil, journalSize: nil, keyOptions: nil, waitForSync: nil, doCompact: nil, isVolatile: nil, shardKeys: nil, numberOfShards: nil, isSystem: nil, indexBuckets: nil) # TESTED
106
+ type = 3 if type == "Edge"
107
+ type = nil if type == "Document"
108
+ body = {
109
+ "name" => collection,
110
+ "type" => type,
111
+ "journalSize" => journalSize,
112
+ "keyOptions" => keyOptions,
113
+ "waitForSync" => waitForSync,
114
+ "doCompact" => doCompact,
115
+ "isVolatile" => isVolatile,
116
+ "shardKeys" => shardKeys,
117
+ "numberOfShards" => numberOfShards,
118
+ "isSystem" => isSystem,
119
+ "indexBuckets" => indexBuckets
120
+ }
121
+ body = body.delete_if{|k,v| v.nil?}.to_json
122
+ request = @@request.merge({ :body => body })
123
+ result = self.class.post("/_db/#{@database}/_api/collection", request)
124
+ self.return_result result: result, checkType: true
125
+ end
126
+ alias create_collection create
127
+ alias create_document_collection create
128
+ alias create_vertex_collection create
129
+
130
+ def create_edge_collection(journalSize: nil, keyOptions: nil, waitForSync: nil, doCompact: nil, isVolatile: nil, shardKeys: nil, numberOfShards: nil, isSystem: nil, indexBuckets: nil) # TESTED
131
+ self.create type: 3, journalSize: journalSize, keyOptions: keyOptions, waitForSync: waitForSync, doCompact: doCompact, isVolatile: isVolatile, shardKeys: shardKeys, numberOfShards: numberOfShards, isSystem: isSystem, indexBuckets: indexBuckets
132
+ end
133
+
134
+ def create_document(document: {}, waitForSync: nil, returnNew: nil) # TESTED
135
+ ArangoDocument.create(body: document, waitForSync: waitForSync, returnNew: returnNew, database: @database, collection: @collection)
136
+ end
137
+ alias create_vertex create_document
138
+
139
+ def create_edge(document: {}, from:, to:, waitForSync: nil, returnNew: nil) # TESTED
140
+ ArangoDocument.create_edge(body: document, from: from, to: to, waitForSync: waitForSync, returnNew: returnNew, database: @database, collection: @collection)
141
+ end
142
+
143
+ # === DELETE ===
144
+
145
+ def destroy # TESTED
146
+ result = self.class.delete("/_db/#{@database}/_api/collection/#{@collection}", @@request)
147
+ self.return_result result: result, caseTrue: true
148
+ end
149
+
150
+ def truncate # TESTED
151
+ result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/truncate", @@request)
152
+ self.return_result result: result
153
+ end
154
+
155
+ # === MODIFY ===
156
+
157
+ def load # TESTED
158
+ result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/load", @@request)
159
+ self.return_result result: result
160
+ end
161
+
162
+ def unload # TESTED
163
+ result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/unload", @@request)
164
+ self.return_result result: result
165
+ end
166
+
167
+ def change(waitForSync: nil, journalSize: nil) # TESTED
168
+ body = {
169
+ "journalSize" => journalSize,
170
+ "waitForSync" => waitForSync
171
+ }
172
+ body = body.delete_if{|k,v| k.nil?}.to_json
173
+ request = @@request.merge({ :body => body })
174
+ result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/properties", request)
175
+ self.return_result result: result
176
+ end
177
+
178
+ def rename(newName) # TESTED
179
+ body = { "name" => newName }
180
+ request = @@request.merge({ :body => body.to_json })
181
+ result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/rename", request)
182
+ @collection = newName unless result.parsed_response["error"]
183
+ self.return_result result: result
184
+ end
185
+
186
+ def rotate
187
+ result = self.class.put("/_db/#{@database}/_api/collection/#{@collection}/rotate", @@request)
188
+ self.return_result result: result, caseTrue: true
189
+ end
190
+
191
+ # === SIMPLE FUNCTIONS ===
192
+
193
+ def documents(type: nil) # "path", "id", "key" # TESTED
194
+ body = {
195
+ "collection" => @collection,
196
+ "type" => type
197
+ }.delete_if{|k,v| v.nil?}.to_json
198
+ request = @@request.merge({ :body => body })
199
+ result = self.class.put("/_db/#{@database}/_api/simple/all-keys", request)
200
+ return result.headers["x-arango-async-id"] if @@async == "store"
201
+ return true if @@async
202
+ result = result.parsed_response
203
+ if type.nil?
204
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| value = self.class.get(x).parsed_response; ArangoDocument.new(key: value["_key"], collection: @collection, body: value)}
205
+ else
206
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"]
207
+ end
208
+ end
209
+
210
+ def allDocuments(skip: nil, limit: nil, batchSize: nil) # TESTED
211
+ body = {
212
+ "collection" => @collection,
213
+ "skip" => skip,
214
+ "limit" => limit,
215
+ "batchSize" => batchSize
216
+ }.delete_if{|k,v| v.nil?}.to_json
217
+ request = @@request.merge({ :body => body })
218
+ result = self.class.put("/_db/#{@database}/_api/simple/all", request)
219
+ return result.headers["x-arango-async-id"] if @@async == "store"
220
+ return true if @@async
221
+ result = result.parsed_response
222
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, body: x)}
223
+ end
224
+
225
+ def documentsMatch(match:, skip: nil, limit: nil, batchSize: nil) # TESTED
226
+ body = {
227
+ "collection" => @collection,
228
+ "example" => match,
229
+ "skip" => skip,
230
+ "limit" => limit,
231
+ "batchSize" => batchSize
232
+ }.delete_if{|k,v| v.nil?}.to_json
233
+ request = @@request.merge({ :body => body })
234
+ result = self.class.put("/_db/#{@database}/_api/simple/by-example", request)
235
+ return result.headers["x-arango-async-id"] if @@async == "store"
236
+ return true if @@async
237
+ result = result.parsed_response
238
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, body: x)}
239
+ end
240
+
241
+ def documentMatch(match:) # TESTED
242
+ body = {
243
+ "collection" => @collection,
244
+ "example" => match
245
+ }.delete_if{|k,v| v.nil?}.to_json
246
+ request = @@request.merge({ :body => body })
247
+ result = self.class.put("/_db/#{@database}/_api/simple/first-example", request)
248
+ return result.headers["x-arango-async-id"] if @@async == "store"
249
+ return true if @@async
250
+ result = result.parsed_response
251
+ @@verbose ? result : result["error"] ? result["errorMessage"] : ArangoDocument.new(key: result["document"]["_key"], collection: @collection, body: result["document"])
252
+ end
253
+
254
+ def documentByKeys(keys:) # TESTED
255
+ keys = keys.map{|x| x.is_a?(String) ? x : x.is_a?(ArangoDocument) ? x.key : nil} if keys.is_a? Array
256
+ keys = [keys] if keys.is_a? String
257
+ body = { "collection" => @collection, "keys" => keys }
258
+ request = @@request.merge({ :body => body.to_json })
259
+ result = self.class.put("/_db/#{@database}/_api/simple/lookup-by-keys", request)
260
+ return result.headers["x-arango-async-id"] if @@async == "store"
261
+ return true if @@async
262
+ result = result.parsed_response
263
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result["documents"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, body: x)}
264
+ end
265
+
266
+ def random # TESTED
267
+ body = { "collection" => @collection }.to_json
268
+ request = @@request.merge({ :body => body })
269
+ result = self.class.put("/_db/#{@database}/_api/simple/any", request)
270
+ return result.headers["x-arango-async-id"] if @@async == "store"
271
+ return true if @@async
272
+ result = result.parsed_response
273
+ @@verbose ? result : result["error"] ? result["errorMessage"] : ArangoDocument.new(key: result["document"]["_key"], collection: @collection, body: result["document"])
274
+ end
275
+
276
+ def removeByKeys(keys:, options: nil) # TESTED
277
+ keys = keys.map{|x| x.is_a?(String) ? x : x.is_a?(ArangoDocument) ? x.key : nil}
278
+ body = { "collection" => @collection, "keys" => keys, "options" => options }.delete_if{|k,v| v.nil?}.to_json
279
+ request = @@request.merge({ :body => body })
280
+ result = self.class.put("/_db/#{@database}/_api/simple/remove-by-keys", request)
281
+ self.return_result result: result, key: "removed"
282
+ end
283
+
284
+ def removeMatch(match:, options: nil) # TESTED
285
+ body = {
286
+ "collection" => @collection,
287
+ "example" => match,
288
+ "options" => options
289
+ }.delete_if{|k,v| v.nil?}.to_json
290
+ request = @@request.merge({ :body => body })
291
+ result = self.class.put("/_db/#{@database}/_api/simple/remove-by-example", request)
292
+ self.return_result result: result, key: "deleted"
293
+ end
294
+
295
+ def replaceMatch(match:, newValue:, options: nil) # TESTED
296
+ body = {
297
+ "collection" => @collection,
298
+ "example" => match,
299
+ "options" => options,
300
+ "newValue" => newValue
301
+ }.delete_if{|k,v| v.nil?}.to_json
302
+ request = @@request.merge({ :body => body })
303
+ result = self.class.put("/_db/#{@database}/_api/simple/replace-by-example", request)
304
+ self.return_result result: result, key: "replaced"
305
+ end
306
+
307
+ def updateMatch(match:, newValue:, options: nil) # TESTED
308
+ body = {
309
+ "collection" => @collection,
310
+ "example" => match,
311
+ "options" => options,
312
+ "newValue" => newValue
313
+ }.delete_if{|k,v| v.nil?}.to_json
314
+ request = @@request.merge({ :body => body })
315
+ result = self.class.put("/_db/#{@database}/_api/simple/update-by-example", request)
316
+ self.return_result result: result, key: "updated"
317
+ end
318
+
319
+ # === IMPORT ===
320
+
321
+ def import(attributes:, values:, from: nil, to: nil, overwrite: nil, waitForSync: nil, onDuplicate: nil, complete: nil, details: nil) # TESTED
322
+ query = {
323
+ "collection": @collection,
324
+ "fromPrefix": from,
325
+ "toPrefix": to,
326
+ "overwrite": overwrite,
327
+ "waitForSync": waitForSync,
328
+ "onDuplicate": onDuplicate,
329
+ "complete": complete,
330
+ "details": details
331
+ }.delete_if{|k,v| v.nil?}
332
+ body = "#{attributes}\n"
333
+ values[0].is_a?(Array) ? values.each{|x| body += "#{x}\n"} : body += "#{values}\n"
334
+ request = @@request.merge({ :body => body, :query => query })
335
+ result = self.class.post("/_db/#{@database}/_api/import", request)
336
+ return result.headers["x-arango-async-id"] if @@async == "store"
337
+ return true if @@async
338
+ result = result.parsed_response
339
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result.delete_if{|k,v| k == "error" || k == "code"}
340
+ end
341
+
342
+ def importJSON(body:, type: "auto", from: nil, to: nil, overwrite: nil, waitForSync: nil, onDuplicate: nil, complete: nil, details: nil) # TESTED
343
+ query = {
344
+ "collection": @collection,
345
+ "type": type,
346
+ "fromPrefix": from,
347
+ "toPrefix": to,
348
+ "overwrite": overwrite,
349
+ "waitForSync": waitForSync,
350
+ "onDuplicate": onDuplicate,
351
+ "complete": complete,
352
+ "details": details
353
+ }.delete_if{|k,v| v.nil?}
354
+ request = @@request.merge({ :body => body.to_json, :query => query })
355
+ result = self.class.post("/_db/#{@database}/_api/import", request)
356
+ return result.headers["x-arango-async-id"] if @@async == "store"
357
+ return true if @@async
358
+ result = result.parsed_response
359
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result.delete_if{|k,v| k == "error" || k == "code"}
360
+ end
361
+
362
+ # === EXPORT ===
363
+
364
+ def export(count: nil, restrict: nil, batchSize: nil, flush: nil, limit: nil, ttl: nil) # TESTED
365
+ query = { "collection": @collection }
366
+ body = {
367
+ "count" => count,
368
+ "restrict" => restrict,
369
+ "batchSize" => batchSize,
370
+ "flush" => flush,
371
+ "limit" => limit,
372
+ "ttl" => ttl
373
+ }.delete_if{|k,v| v.nil?}
374
+ request = @@request.merge({ :body => body.to_json, :query => query })
375
+ result = self.class.post("/_db/#{@database}/_api/export", request)
376
+ return result.headers["x-arango-async-id"] if @@async == "store"
377
+ return true if @@async
378
+ result = result.parsed_response
379
+ return @@verbose ? result : result["errorMessage"] if result["error"]
380
+ @countExport = result["count"]
381
+ @hasMoreExport = result["hasMore"]
382
+ @idExport = result["id"]
383
+ if(result["result"][0].nil? || !result["result"][0].is_a?(Hash) || !result["result"][0].key?("_key"))
384
+ result = result["result"]
385
+ else
386
+ result = result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, database: @database, body: x)}
387
+ end
388
+ result
389
+ end
390
+
391
+ def exportNext # TESTED
392
+ unless @hasMoreExport
393
+ print "No other results"
394
+ else
395
+ query = { "collection": @collection }
396
+ request = @@request.merge({ :query => query })
397
+ result = self.class.put("/_db/#{@database}/_api/cursor/#{@idExport}", request)
398
+ return result.headers["x-arango-async-id"] if @@async == "store"
399
+ return true if @@async
400
+ result = result.parsed_response
401
+ return @@verbose ? result : result["errorMessage"] if result["error"]
402
+ @countExport = result["count"]
403
+ @hasMoreExport = result["hasMore"]
404
+ @idExport = result["id"]
405
+ if(result["result"][0].nil? || !result["result"][0].is_a?(Hash) || !result["result"][0].key?("_key"))
406
+ result = result["result"]
407
+ else
408
+ result = result["result"].map{|x| ArangoDocument.new(key: x["_key"], collection: @collection, database: @database, body: x)}
409
+ end
410
+ result
411
+ end
412
+ end
413
+
414
+ # === INDEXES ===
415
+
416
+ # def retrieveIndex(id:) # TESTED
417
+ # result = self.class.get("/_db/#{@database}/_api/index/#{@collection}/#{id}", @@request)
418
+ # if @@async == "store"
419
+ # result.headers["x-arango-async-id"]
420
+ # else
421
+ # result = result.parsed_response
422
+ # if @@verbose
423
+ # result
424
+ # else
425
+ # if result["error"]
426
+ # result["errorMessage"]
427
+ # else
428
+ # ArangoIndex.new(body: result, id: result["id"], database: @database, collection: @collection, type: result["type"], unique: result["unique"], fields: result["fields"])
429
+ # end
430
+ # end
431
+ # end
432
+ # end
433
+
434
+ def indexes # TESTED
435
+ query = { "collection": @collection }
436
+ request = @@request.merge({ :query => query })
437
+ result = self.class.get("/_db/#{@database}/_api/index", request)
438
+ return result.headers["x-arango-async-id"] if @@async == "store"
439
+ return true if @@async
440
+ result = result.parsed_response
441
+ return result if @@verbose
442
+ return result["errorMessage"] if result["error"]
443
+ result.delete_if{|k,v| k == "error" || k == "code"}
444
+ result["indexes"] = result["indexes"].map{|x| ArangoIndex.new(body: x, id: x["id"], database: @database, collection: @collection, type: x["type"], unique: x["unique"], fields: x["fields"])}
445
+ result
446
+ end
447
+
448
+ def createIndex(body: {}, unique: nil, type:, fields:, id: nil) # TESTED
449
+ body["fields"] = fields.is_a?(Array) ? fields : [fields]
450
+ body["unique"] = unique unless unique.nil?
451
+ body["type"] = type unless type.nil?
452
+ body["id"] = id unless type.nil?
453
+ query = { "collection": @collection }
454
+ request = @@request.merge({ :body => body.to_json, :query => query })
455
+ result = self.class.post("/_db/#{@database}/_api/index", request)
456
+ return result.headers["x-arango-async-id"] if @@async == "store"
457
+ return true if @@async
458
+ result = result.parsed_response
459
+ @@verbose ? result : result["error"] ? result["errorMessage"] : ArangoIndex.new(body: result, id: result["id"], database: @database, collection: @collection, type: result["type"], unique: result["unique"], fields: result["fields"])
460
+ end
461
+ #
462
+ # def deleteIndex(id:) # TESTED
463
+ # result = self.class.delete("/_db/#{@database}/_api/index/#{@collection}/#{id}", @@request)
464
+ # if @@async == "store"
465
+ # result.headers["x-arango-async-id"]
466
+ # else
467
+ # result = result.parsed_response
468
+ # if @@verbose
469
+ # result
470
+ # else
471
+ # if result["error"]
472
+ # result["errorMessage"]
473
+ # else
474
+ # true
475
+ # end
476
+ # end
477
+ # end
478
+ # end
479
+
480
+ # === REPLICATION ===
481
+
482
+ def data(from: nil, to: nil, chunkSize: nil, includeSystem: false, failOnUnknown: nil, ticks: nil, flush: nil) # TESTED
483
+ query = {
484
+ "collection": @collection,
485
+ "from": from,
486
+ "to": to,
487
+ "chunkSize": chunkSize,
488
+ "includeSystem": includeSystem,
489
+ "failOnUnknown": failOnUnknown,
490
+ "ticks": ticks,
491
+ "flush": flush
492
+ }.delete_if{|k,v| v.nil?}
493
+ request = @@request.merge({ :query => query })
494
+ result = self.class.get("/_db/#{@database}/_api/replication/dump", request)
495
+ return result.headers["x-arango-async-id"] if @@async == "store"
496
+ return true if @@async
497
+ result = result.parsed_response
498
+ return nil if result.nil?
499
+ @@verbose ? result : result["error"] ? result["errorMessage"] : result
500
+ end
501
+ alias dump data
502
+
503
+ # === UTILITY ===
504
+
505
+ def return_result(result:, caseTrue: false, key: nil, checkType: false)
506
+ return result.headers["x-arango-async-id"] if @@async == "store"
507
+ return true if @@async
508
+ result = result.parsed_response
509
+ if @@verbose || !result.is_a?(Hash)
510
+ resultTemp = result
511
+ unless result["errorMessage"]
512
+ result.delete_if{|k,v| k == "error" || k == "code"}
513
+ @body = result
514
+ @type = result["type"] == 2 ? "Document" : "Edge" if(checkType)
515
+ end
516
+ resultTemp
517
+ else
518
+ return result["errorMessage"] if result["error"]
519
+ return true if caseTrue
520
+ result.delete_if{|k,v| k == "error" || k == "code"}
521
+ @body = result
522
+ @type = result["type"] == 2 ? "Document" : "Edge" if(checkType)
523
+ key.nil? ? self : result[key]
524
+ end
525
+ end
526
+ end