arango-driver 3.5.0.alpha0
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/LICENSE +21 -0
- data/README.md +1073 -0
- data/arango_opal.js +15 -0
- data/lib/arango-driver.rb +61 -0
- data/lib/arango.rb +96 -0
- data/lib/arango/aql.rb +188 -0
- data/lib/arango/collection.rb +575 -0
- data/lib/arango/collection/documents.rb +122 -0
- data/lib/arango/collection/edges.rb +149 -0
- data/lib/arango/collection/importing.rb +57 -0
- data/lib/arango/collection/indexes.rb +53 -0
- data/lib/arango/collection/replication.rb +24 -0
- data/lib/arango/collection/user.rb +28 -0
- data/lib/arango/cursor.rb +67 -0
- data/lib/arango/database.rb +188 -0
- data/lib/arango/database/analyzer.rb +21 -0
- data/lib/arango/database/aql_functions.rb +54 -0
- data/lib/arango/database/aql_queries.rb +114 -0
- data/lib/arango/database/aql_query_cache.rb +27 -0
- data/lib/arango/database/collections.rb +100 -0
- data/lib/arango/database/foxx_services.rb +103 -0
- data/lib/arango/database/graph_access.rb +27 -0
- data/lib/arango/database/http_route.rb +9 -0
- data/lib/arango/database/replication.rb +96 -0
- data/lib/arango/database/stream_transactions.rb +25 -0
- data/lib/arango/database/tasks.rb +67 -0
- data/lib/arango/database/transactions.rb +15 -0
- data/lib/arango/database/user.rb +26 -0
- data/lib/arango/database/view_access.rb +37 -0
- data/lib/arango/document.rb +443 -0
- data/lib/arango/edge.rb +164 -0
- data/lib/arango/error.rb +97 -0
- data/lib/arango/error_db.rb +27 -0
- data/lib/arango/foxx.rb +255 -0
- data/lib/arango/graph.rb +202 -0
- data/lib/arango/graph/basics.rb +39 -0
- data/lib/arango/graph/edge_access.rb +56 -0
- data/lib/arango/graph/vertex_access.rb +33 -0
- data/lib/arango/helper/collection_assignment.rb +13 -0
- data/lib/arango/helper/database_assignment.rb +14 -0
- data/lib/arango/helper/request_method.rb +45 -0
- data/lib/arango/helper/return.rb +21 -0
- data/lib/arango/helper/satisfaction.rb +28 -0
- data/lib/arango/helper/server_assignment.rb +13 -0
- data/lib/arango/helper/traversal.rb +12 -0
- data/lib/arango/index.rb +103 -0
- data/lib/arango/replication.rb +231 -0
- data/lib/arango/request.rb +92 -0
- data/lib/arango/request_batch.rb +174 -0
- data/lib/arango/result.rb +130 -0
- data/lib/arango/search_view.rb +23 -0
- data/lib/arango/server.rb +68 -0
- data/lib/arango/server/administration.rb +296 -0
- data/lib/arango/server/agency.rb +23 -0
- data/lib/arango/server/async.rb +51 -0
- data/lib/arango/server/batch.rb +35 -0
- data/lib/arango/server/config.rb +76 -0
- data/lib/arango/server/databases.rb +71 -0
- data/lib/arango/server/monitoring.rb +17 -0
- data/lib/arango/server/opal_support.rb +95 -0
- data/lib/arango/server/tasks.rb +69 -0
- data/lib/arango/server/user.rb +22 -0
- data/lib/arango/task.rb +223 -0
- data/lib/arango/transaction.rb +113 -0
- data/lib/arango/traversal.rb +212 -0
- data/lib/arango/user.rb +174 -0
- data/lib/arango/version.rb +3 -0
- data/lib/arango/vertex.rb +112 -0
- data/lib/arango/view.rb +124 -0
- data/lib/arango/view/basics.rb +25 -0
- metadata +296 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module FoxxServices
|
4
|
+
# === FOXX ===
|
5
|
+
def install_service
|
6
|
+
# TODO
|
7
|
+
end
|
8
|
+
|
9
|
+
def replace_service
|
10
|
+
# TODO
|
11
|
+
end
|
12
|
+
|
13
|
+
def upgrade_service
|
14
|
+
# TODO
|
15
|
+
end
|
16
|
+
|
17
|
+
def uninstall_service
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def list_services
|
22
|
+
# TODO
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_service
|
26
|
+
# TODO
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_service_configuration
|
30
|
+
# TODO
|
31
|
+
end
|
32
|
+
|
33
|
+
def replace_service_configuration
|
34
|
+
# TODO
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_service_configuration
|
38
|
+
# TODO
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_service_dependencies
|
42
|
+
# TODO
|
43
|
+
end
|
44
|
+
|
45
|
+
def replace_service_dependencies
|
46
|
+
# TODO
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_service_dependencies
|
50
|
+
# TODO
|
51
|
+
end
|
52
|
+
|
53
|
+
def enable_service_development_mode
|
54
|
+
# TODO
|
55
|
+
end
|
56
|
+
|
57
|
+
def disable_service_development_mode
|
58
|
+
# TODO
|
59
|
+
end
|
60
|
+
|
61
|
+
def list_service_scripts
|
62
|
+
# TODO
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_service_script
|
66
|
+
# TODO
|
67
|
+
end
|
68
|
+
|
69
|
+
def run_service_tests
|
70
|
+
# TODO
|
71
|
+
end
|
72
|
+
|
73
|
+
def download_service
|
74
|
+
# TODO
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_service_readme
|
78
|
+
# TODO
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_service_documentation
|
82
|
+
# TODO
|
83
|
+
end
|
84
|
+
|
85
|
+
def commit_local_Service_state
|
86
|
+
# TODO
|
87
|
+
end
|
88
|
+
# def foxxes
|
89
|
+
# result = request("GET", "_api/foxx")
|
90
|
+
# return result if return_directly?(result)
|
91
|
+
# result.map do |fox|
|
92
|
+
# Arango::Foxx.new(database: self, mount: fox[:mount], body: fox)
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
|
96
|
+
# def foxx(body: {}, development: nil, legacy: nil, mount:, name: nil, provides: nil, setup: nil, teardown: nil, type: "application/json",
|
97
|
+
# version: nil)
|
98
|
+
# Arango::Foxx.new(body: body, database: self, development: development, legacy: legacy, mount: mount, name: name, provides: provides,
|
99
|
+
# setup: setup, teardown: teardown, type: type, version: version)
|
100
|
+
# end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module GraphAccess
|
4
|
+
# == GRAPH ==
|
5
|
+
|
6
|
+
def create_graph
|
7
|
+
|
8
|
+
end
|
9
|
+
def graphs
|
10
|
+
result = request("GET", "_api/gharial")
|
11
|
+
return result if return_directly?(result)
|
12
|
+
result[:graphs].map do |graph|
|
13
|
+
Arango::Graph.new(database: self, name: graph[:_key], body: graph)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def graph(name:, edge_definitions: [], orphan_collections: [],
|
18
|
+
body: {})
|
19
|
+
Arango::Graph.new(name: name, database: self, edge_definitions: edge_definitions, orphan_collections: orphan_collections, body: body)
|
20
|
+
end
|
21
|
+
|
22
|
+
def list_graphs
|
23
|
+
# TODO
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module Replication
|
4
|
+
# === REPLICATION ===
|
5
|
+
|
6
|
+
def inventory(batch_id:, global: nil, include_system: nil)
|
7
|
+
query = {
|
8
|
+
batchId: batch_id,
|
9
|
+
global: global,
|
10
|
+
includeSystem: include_system
|
11
|
+
}
|
12
|
+
request("GET", "_api/replication/inventory", query: query)
|
13
|
+
end
|
14
|
+
|
15
|
+
def cluster_inventory(include_system: nil)
|
16
|
+
query = { includeSystem: include_system }
|
17
|
+
request("GET", "_api/replication/clusterInventory", query: query)
|
18
|
+
end
|
19
|
+
|
20
|
+
def logger
|
21
|
+
request("GET", "_api/replication/logger-state")
|
22
|
+
end
|
23
|
+
|
24
|
+
def logger_follow(from: nil, to: nil, chunk_size: nil, include_system: nil)
|
25
|
+
query = {
|
26
|
+
from: from,
|
27
|
+
to: to,
|
28
|
+
chunkSize: chunk_size,
|
29
|
+
includeSystem: include_system
|
30
|
+
}
|
31
|
+
request("GET", "_api/replication/logger-follow", query: query)
|
32
|
+
end
|
33
|
+
|
34
|
+
def logger_first_tick
|
35
|
+
request("GET", "_api/replication/logger-first-tick", key: :firstTick)
|
36
|
+
end
|
37
|
+
|
38
|
+
def logger_range_tick
|
39
|
+
request("GET", "_api/replication/logger-tick-ranges")
|
40
|
+
end
|
41
|
+
|
42
|
+
def server_id
|
43
|
+
request("GET", "_api/replication/server-id", key: :serverId)
|
44
|
+
end
|
45
|
+
|
46
|
+
def range
|
47
|
+
request("GET", "_api/wal/range")
|
48
|
+
end
|
49
|
+
|
50
|
+
def last_tick
|
51
|
+
request("GET", "_api/wal/lastTick")
|
52
|
+
end
|
53
|
+
|
54
|
+
def tail(from: nil, to: nil, global: nil, chunk_size: nil,
|
55
|
+
server_id: nil, barrier_id: nil)
|
56
|
+
query = {
|
57
|
+
from: from,
|
58
|
+
to: to,
|
59
|
+
barrierID: barrier_id,
|
60
|
+
chunkSize: chunk_size,
|
61
|
+
global: global,
|
62
|
+
serverID: server_id,
|
63
|
+
}
|
64
|
+
request("GET", "_api/wal/tail", query: query)
|
65
|
+
end
|
66
|
+
|
67
|
+
def replication(master:, adaptive_polling: nil, auto_resync: nil, auto_resync_retries: nil, chunk_size: nil, connect_timeout: nil,
|
68
|
+
connection_retry_wait_time: nil, idle_max_wait_time: nil, idle_min_wait_time: nil, include_system: true, incremental: nil,
|
69
|
+
initial_sync_max_wait_time: nil, max_connect_retries: nil, request_timeout: nil, require_from_present: nil,
|
70
|
+
restrict_collections: nil, restrict_type: nil, verbose: nil)
|
71
|
+
Arango::Replication.new(slave: self, master: master, adaptive_polling: adaptive_polling, auto_resync: auto_resync,
|
72
|
+
auto_resync_retries: auto_resync_retries, chunk_size: chunk_size, connect_timeout: connect_timeout,
|
73
|
+
connection_retry_wait_time: connection_retry_wait_time, idle_max_wait_time: idle_max_wait_time,
|
74
|
+
idle_min_wait_time: idle_min_wait_time, include_system: include_system, incremental: incremental,
|
75
|
+
initial_sync_max_wait_time: initial_sync_max_wait_time, max_connect_retries: max_connect_retries,
|
76
|
+
request_timeout: request_timeout, require_from_present: require_from_present,
|
77
|
+
restrict_collections: restrict_collections, restrict_type: restrict_type, verbose: verbose)
|
78
|
+
end
|
79
|
+
|
80
|
+
def replication_as_master(slave:, adaptive_polling: nil, auto_resync: nil, auto_resync_retries: nil, chunk_size: nil, connect_timeout: nil,
|
81
|
+
connection_retry_wait_time: nil, idle_max_wait_time: nil, idle_min_wait_time: nil, include_system: true,
|
82
|
+
incremental: nil, initial_sync_max_wait_time: nil, max_connect_retries: nil, request_timeout: nil,
|
83
|
+
require_from_present: nil, restrict_collections: nil, restrict_type: nil, verbose: nil)
|
84
|
+
Arango::Replication.new(master: self, slave: slave, adaptive_polling: adaptive_polling, auto_resync: auto_resync,
|
85
|
+
auto_resync_retries: auto_resync_retries, chunk_size: chunk_size, connect_timeout: connect_timeout,
|
86
|
+
connection_retry_wait_time: connection_retry_wait_time, idle_max_wait_time: idle_max_wait_time,
|
87
|
+
idle_min_wait_time: idle_min_wait_time, include_system: include_system, incremental: incremental,
|
88
|
+
initial_sync_max_wait_time: initial_sync_max_wait_time, max_connect_retries: max_connect_retries,
|
89
|
+
request_timeout: request_timeout, require_from_present: require_from_present,
|
90
|
+
restrict_collections: restrict_collections, restrict_type: restrict_type, verbose: verbose)
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module StreamTransactions
|
4
|
+
def begin_stream_transaction
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
def stream_transaction
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def list_stream_transactions
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def commit_stream_transaction
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def abort_stream_transaction
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module Tasks
|
4
|
+
# Get all tasks.
|
5
|
+
# @return [Array<Arango::Task>]
|
6
|
+
def all_tasks
|
7
|
+
Arango::Task.all(database: self)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Create a new task with given id, task is saved to the database.
|
11
|
+
# @param id [String]
|
12
|
+
# @param command [String] The javascript code to execute.
|
13
|
+
# @param name [String] The task name, optional.
|
14
|
+
# @param offset [Integer] The number of seconds initial delay, optional.
|
15
|
+
# @param params [Hash] Hash of params to pass to the command, optional.
|
16
|
+
# @param period [Integer] Number of seconds between executions, optional.
|
17
|
+
# @return [Arango::Task]
|
18
|
+
def create_task(id, command:, name: nil, offset: nil, params: nil, period: nil)
|
19
|
+
Arango::Task.new(id, command: command, name: name, offset: offset, params: params, period: period, database: self).create
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get a task from the database.
|
23
|
+
# @param id [String]
|
24
|
+
# @return [Arango::Task]
|
25
|
+
def get_task(id)
|
26
|
+
Arango::Task.get(id, database: self)
|
27
|
+
end
|
28
|
+
alias fetch_task get_task
|
29
|
+
alias retrieve_task get_task
|
30
|
+
|
31
|
+
# Instantiate a new task with given id, task is not saved to the database.
|
32
|
+
# @param id [String]
|
33
|
+
# @param command [String] The javascript code to execute, optional.
|
34
|
+
# @param name [String] The task name, optional.
|
35
|
+
# @param offset [Integer] The number of seconds initial delay, optional.
|
36
|
+
# @param params [Hash] Hash of params to pass to the command, optional.
|
37
|
+
# @param period [Integer] Number of seconds between executions, optional.
|
38
|
+
# @return [Arango::Task]
|
39
|
+
def new_task(id, command: nil, name: nil, offset: nil, params: nil, period: nil)
|
40
|
+
Arango::Task.new(id, command: command, name: name, offset: offset, params: params, period: period, database: self)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get a list of all task ids.
|
44
|
+
# @return [Array<String>]
|
45
|
+
def list_tasks
|
46
|
+
Arango::Task.list(database: self)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Delete task with given id.
|
50
|
+
# @param id [String]
|
51
|
+
# @return [Boolean] Returns true if task has been deleted.
|
52
|
+
def drop_task(id)
|
53
|
+
Arango::Task.delete(id, database: self)
|
54
|
+
end
|
55
|
+
alias delete_task drop_task
|
56
|
+
alias destroy_task drop_task
|
57
|
+
|
58
|
+
# Checks existence of a task.
|
59
|
+
# @param id [String]
|
60
|
+
# @return [Boolean] Returns true if the task exists, otherwise false.
|
61
|
+
def exist_task?(id)
|
62
|
+
Arango::Task.exist?(id, database: self)
|
63
|
+
end
|
64
|
+
alias task_exist? exist_task?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module Transactions
|
4
|
+
# === TRANSACTION ===
|
5
|
+
|
6
|
+
def transaction(action:, intermediate_commit_count: nil, intermediate_commit_size: nil, lock_timeout: nil, max_transaction_size: nil, params: nil,
|
7
|
+
read: [], wait_for_sync: nil, write: [])
|
8
|
+
Arango::Transaction.new(action: action, database: self, intermediate_commit_count: intermediate_commit_count,
|
9
|
+
intermediate_commit_size: intermediate_commit_size, lock_timeout: lock_timeout,
|
10
|
+
max_transaction_size: max_transaction_size, params: params, read: read, wait_for_sync: wait_for_sync, write: write)
|
11
|
+
# TODO execute
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module User
|
4
|
+
def check_user(user)
|
5
|
+
user = Arango::User.new(user: user) if user.is_a?(String)
|
6
|
+
return user
|
7
|
+
end
|
8
|
+
private :check_user
|
9
|
+
|
10
|
+
def add_user_access(grant:, user:)
|
11
|
+
user = check_user(user)
|
12
|
+
user.add_database_access(grant: grant, database: @name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def revoke_user_access(user:)
|
16
|
+
user = check_user(user)
|
17
|
+
user.revoke_database_access(database: @name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def user_access(user:)
|
21
|
+
user = check_user(user)
|
22
|
+
user.database_access(database: @name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Arango
|
2
|
+
class Database
|
3
|
+
module ViewAccess
|
4
|
+
# === VIEW ===
|
5
|
+
|
6
|
+
def create_search_view
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
def search_view(name)
|
11
|
+
# TODO Returns a ArangoSearchView instance for the given view name
|
12
|
+
end
|
13
|
+
|
14
|
+
def list_views
|
15
|
+
# TODO Fetches all views from the database and returns an array of view descriptions.
|
16
|
+
end
|
17
|
+
|
18
|
+
# verified, in js api
|
19
|
+
def views
|
20
|
+
result = request("GET", "_api/view", key: :result)
|
21
|
+
return result if return_directly?(result)
|
22
|
+
result.map do |view|
|
23
|
+
Arango::View.new(database: self, id: view[:id], name: view[:name], type: view[:type])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# not found
|
28
|
+
def view(name)
|
29
|
+
Arango::View.new(database: self, name: name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_view
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,443 @@
|
|
1
|
+
# ==== DOCUMENT ====
|
2
|
+
|
3
|
+
module Arango
|
4
|
+
class Document
|
5
|
+
include Arango::Helper::Satisfaction
|
6
|
+
include Arango::Helper::Return
|
7
|
+
include Arango::Helper::CollectionAssignment
|
8
|
+
include Arango::Helper::Traversal
|
9
|
+
|
10
|
+
extend Arango::Helper::RequestMethod
|
11
|
+
|
12
|
+
class << self
|
13
|
+
Arango.aql_request_class_method(Arango::Document, :all) do |offset: 0, limit: nil, batch_size: nil, collection:|
|
14
|
+
bind_vars = {}
|
15
|
+
query = "FOR doc IN #{collection.name}"
|
16
|
+
if limit && offset
|
17
|
+
query << "\n LIMIT @offset, @limit"
|
18
|
+
bind_vars[:offset] = offset
|
19
|
+
bind_vars[:limit] = limit
|
20
|
+
end
|
21
|
+
raise Arango::Error.new err: "offset must be used with limit" if offset > 0 && !limit
|
22
|
+
query << "\n RETURN doc"
|
23
|
+
# aql = Arango::AQL.new(database: collection.database, query: query, bind_vars: bind_vars, batch_size: batch_size)
|
24
|
+
# result = aql.execute
|
25
|
+
{ query: query, bind_vars: bind_vars, batch_size: batch_size, block: -> (aql, result) do
|
26
|
+
result_proc = ->(b) { b.result.map { |d| Arango::Document.new(d, collection: collection) }}
|
27
|
+
final_result = result_proc.call(result)
|
28
|
+
if aql.has_more?
|
29
|
+
collection.instance_variable_set(:@aql, aql)
|
30
|
+
collection.instance_variable_set(:@batch_proc, result_proc)
|
31
|
+
unless batch_size
|
32
|
+
while aql.has_more?
|
33
|
+
final_result += collection.next_batch
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
final_result
|
38
|
+
end
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
Arango.aql_request_class_method(Arango::Document, :list) do |offset: 0, limit: nil, batch_size: nil, collection:|
|
43
|
+
bind_vars = {}
|
44
|
+
query = "FOR doc IN #{collection.name}"
|
45
|
+
if limit && offset
|
46
|
+
query << "\n LIMIT @offset, @limit"
|
47
|
+
bind_vars[:offset] = offset
|
48
|
+
bind_vars[:limit] = limit
|
49
|
+
end
|
50
|
+
raise Arango::Error.new err: "offset must be used with limit" if offset > 0 && !limit
|
51
|
+
query << "\n RETURN doc._key"
|
52
|
+
# aql = Arango::AQL.new(database: collection.database, query: query, bind_vars: bind_vars, batch_size: batch_size)
|
53
|
+
# result = aql.execute
|
54
|
+
{ database: collection.database, query: query, bind_vars: bind_vars, batch_size: batch_size, block: -> (aql, result) do
|
55
|
+
result_proc = ->(b) { b.result }
|
56
|
+
final_result = result_proc.call(result)
|
57
|
+
if aql.has_more?
|
58
|
+
collection.instance_variable_set(:@aql, aql)
|
59
|
+
collection.instance_variable_set(:@batch_proc, result_proc)
|
60
|
+
unless batch_size
|
61
|
+
while aql.has_more?
|
62
|
+
final_result += collection.next_batch
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
final_result
|
67
|
+
end
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
Arango.request_class_method(Arango::Document, :exist?) do |document, match_rev: nil, collection:|
|
72
|
+
body = _body_from_arg(document)
|
73
|
+
raise Arango::Error err: "Document with key required!" unless body.key?(:_key)
|
74
|
+
request = { head: "_api/document/#{collection.name}/#{body[:_key]}" }
|
75
|
+
if body.key?(:_key) && body.key?(:_rev) && match_rev == true
|
76
|
+
request[:headers] = {'If-Match' => body[:_rev] }
|
77
|
+
elsif body.key?(:_key) && body.key?(:_rev) && match_rev == false
|
78
|
+
request[:headers] = {'If-None-Match' => body[:_rev] }
|
79
|
+
end
|
80
|
+
request[:block] = ->(result) do
|
81
|
+
case result.response_code
|
82
|
+
when 200 then true # document was found
|
83
|
+
when 304 then true # “If-None-Match” header is given and the document has the same version
|
84
|
+
when 412 then true # “If-Match” header is given and the found document has a different version.
|
85
|
+
else
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
request
|
90
|
+
end
|
91
|
+
|
92
|
+
Arango.request_class_method(Arango::Document, :create_documents) do |documents, wait_for_sync: nil, collection:|
|
93
|
+
documents = [documents] unless documents.is_a? Array
|
94
|
+
documents = documents.map{ |d| _body_from_arg(d) }
|
95
|
+
query = { returnNew: true }
|
96
|
+
query[:waitForSync] = wait_for_sync unless wait_for_sync.nil?
|
97
|
+
{ post: "_api/document/#{collection.name}", body: documents, query: query, block: ->(result) do
|
98
|
+
result.map do |doc|
|
99
|
+
Arango::Document.new(doc[:new], collection: collection)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
Arango.request_class_method(Arango::Document, :get) do |document, collection:|
|
106
|
+
document = _body_from_arg(document)
|
107
|
+
if document.key?(:_key)
|
108
|
+
{ get: "_api/document/#{collection.name}/#{document[:_key]}", block: ->(result) { Arango::Document.new(result, collection: collection) }}
|
109
|
+
else
|
110
|
+
bind_vars = {}
|
111
|
+
query = "FOR doc IN #{collection.name}"
|
112
|
+
i = 0
|
113
|
+
document.each do |k,v|
|
114
|
+
i += 1
|
115
|
+
query << "\n FILTER doc.@key#{i} == @value#{i}"
|
116
|
+
bind_vars["key#{i}"] = k.to_s
|
117
|
+
bind_vars["value#{i}"] = v
|
118
|
+
end
|
119
|
+
query << "\n LIMIT 1"
|
120
|
+
query << "\n RETURN doc"
|
121
|
+
aql = AQL.new(query: query, database: collection.database, bind_vars: bind_vars, block: ->(_, result) do
|
122
|
+
Arango::Document.new(result.result.first, collection: collection) if result.result.first
|
123
|
+
end
|
124
|
+
)
|
125
|
+
aql.request
|
126
|
+
end
|
127
|
+
end
|
128
|
+
alias fetch get
|
129
|
+
alias retrieve get
|
130
|
+
alias batch_fetch batch_get
|
131
|
+
alias batch_retrieve batch_get
|
132
|
+
|
133
|
+
Arango.multi_request_class_method(Arango::Document, :get_documents) do |documents, collection:|
|
134
|
+
documents = [documents] unless documents.is_a? Array
|
135
|
+
documents = documents.map{ |d| _body_from_arg(d) }
|
136
|
+
requests = []
|
137
|
+
result_documents = []
|
138
|
+
documents.each do |document|
|
139
|
+
if document.key?(:_key)
|
140
|
+
requests << { get: "_api/document/#{collection.name}/#{document[:_key]}", block: ->(result) do
|
141
|
+
result_documents << Arango::Document.new(result, collection: collection)
|
142
|
+
end
|
143
|
+
}
|
144
|
+
else
|
145
|
+
bind_vars = {}
|
146
|
+
query = "FOR doc IN #{collection.name}"
|
147
|
+
i = 0
|
148
|
+
document.each do |k,v|
|
149
|
+
i += 1
|
150
|
+
query << "\n FILTER doc.@key#{i} == @value#{i}"
|
151
|
+
bind_vars["key#{i}"] = k.to_s
|
152
|
+
bind_vars["value#{i}"] = v
|
153
|
+
end
|
154
|
+
query << "\n LIMIT 1"
|
155
|
+
query << "\n RETURN doc"
|
156
|
+
aql = AQL.new(query: query, database: collection.database, bind_vars: bind_vars, block: ->(_, result) do
|
157
|
+
result_documents << Arango::Document.new(result.result.first, collection: collection) if result.result.first
|
158
|
+
result_documents
|
159
|
+
end
|
160
|
+
)
|
161
|
+
requests << aql.request
|
162
|
+
end
|
163
|
+
end
|
164
|
+
requests
|
165
|
+
end
|
166
|
+
alias fetch_documents get_documents
|
167
|
+
alias retrieve_documents get_documents
|
168
|
+
alias batch_fetch_documents batch_get_documents
|
169
|
+
alias batch_retrieve_documents batch_get_documents
|
170
|
+
|
171
|
+
Arango.request_class_method(Arango::Document, :replace_documents) do |documents, ignore_revs: false, wait_for_sync: nil, collection:|
|
172
|
+
documents = [documents] unless documents.is_a? Array
|
173
|
+
documents = documents.map{ |d| _body_from_arg(d) }
|
174
|
+
query = { returnNew: true, ignoreRevs: ignore_revs }
|
175
|
+
query[:waitForSync] = wait_for_sync unless wait_for_sync.nil?
|
176
|
+
{ put: "_api/document/#{collection.name}", body: documents, query: query, block: ->(result) do
|
177
|
+
result.map do |doc|
|
178
|
+
Arango::Document.new(doc[:new], collection: collection)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
Arango.request_class_method(Arango::Document, :update_documents) do |documents, ignore_revs: false, wait_for_sync: nil, merge_objects: nil, collection:|
|
185
|
+
documents = [documents] unless documents.is_a? Array
|
186
|
+
documents = documents.map{ |d| _body_from_arg(d) }
|
187
|
+
query = { returnNew: true, ignoreRevs: ignore_revs }
|
188
|
+
query[:waitForSync] = wait_for_sync unless wait_for_sync.nil?
|
189
|
+
query[:mergeObjects] = merge_objects unless merge_objects.nil?
|
190
|
+
{ patch: "_api/document/#{collection.name}", body: documents, query: query, block: ->(result) do
|
191
|
+
result.map do |doc|
|
192
|
+
Arango::Document.new(doc[:new], collection: collection)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
}
|
196
|
+
end
|
197
|
+
|
198
|
+
Arango.request_class_method(Arango::Document, :drop) do |document, ignore_revs: false, wait_for_sync: nil, collection:|
|
199
|
+
document = _body_from_arg(document)
|
200
|
+
query = { ignoreRevs: ignore_revs }
|
201
|
+
query[:waitForSync] = wait_for_sync unless wait_for_sync.nil?
|
202
|
+
headers = nil
|
203
|
+
headers = { "If-Match": document[:_rev] } if !ignore_revs && document.key?(:_rev)
|
204
|
+
{ delete: "_api/document/#{collection.name}/#{document[:_key]}", query: query, headers: headers, block: ->(_) { nil }}
|
205
|
+
end
|
206
|
+
alias delete drop
|
207
|
+
alias destroy drop
|
208
|
+
alias batch_delete batch_drop
|
209
|
+
alias batch_destroy batch_drop
|
210
|
+
|
211
|
+
Arango.request_class_method(Arango::Document, :drop_documents) do |documents, ignore_revs: false, wait_for_sync: nil, collection:|
|
212
|
+
documents = [documents] unless documents.is_a? Array
|
213
|
+
documents = documents.map{ |d| _body_from_arg(d) }
|
214
|
+
query = { ignoreRevs: ignore_revs }
|
215
|
+
query[:waitForSync] = wait_for_sync unless wait_for_sync.nil?
|
216
|
+
{ delete: "_api/document/#{collection.name}", body: documents, query: query, block: ->(_) { nil }}
|
217
|
+
end
|
218
|
+
alias delete_documents drop_documents
|
219
|
+
alias destroy_documents drop_documents
|
220
|
+
alias batch_delete_documents batch_drop_documents
|
221
|
+
alias batch_destroy_documents batch_drop_documents
|
222
|
+
|
223
|
+
private
|
224
|
+
|
225
|
+
def _body_from_arg(arg)
|
226
|
+
case arg
|
227
|
+
when String then { _key: arg }
|
228
|
+
when Hash
|
229
|
+
arg.transform_keys!(&:to_sym)
|
230
|
+
arg[:_id] = arg.delete(:id) if arg.key?(:id) && !arg.key?(:_id)
|
231
|
+
arg[:_key] = arg.delete(:key) if arg.key?(:key) && !arg.key?(:_key)
|
232
|
+
arg[:_rev] = arg.delete(:rev) if arg.key?(:rev) && !arg.key?(:_rev)
|
233
|
+
arg.delete_if{|_,v| v.nil?}
|
234
|
+
arg
|
235
|
+
when Arango::Document then arg.to_h
|
236
|
+
when Arango::Result then arg.to_h
|
237
|
+
else
|
238
|
+
raise "Unknown arg type, must be String, Hash, Arango::Result or Arango::Document"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def initialize(document, collection:, ignore_revs: false, wait_for_sync: nil)
|
244
|
+
@body = _body_from_arg(document)
|
245
|
+
@changed_body = {}
|
246
|
+
@ignore_revs = ignore_revs
|
247
|
+
@wait_for_sync = wait_for_sync
|
248
|
+
assign_collection(collection)
|
249
|
+
end
|
250
|
+
|
251
|
+
def id
|
252
|
+
return @changed_body[:_id] if @changed_body.key?(:_id)
|
253
|
+
@body[:_id]
|
254
|
+
end
|
255
|
+
|
256
|
+
def id=(i)
|
257
|
+
@changed_body[:_id] = i
|
258
|
+
end
|
259
|
+
|
260
|
+
def key
|
261
|
+
return @changed_body[:_key] if @changed_body.key?(:_key)
|
262
|
+
@body[:_key]
|
263
|
+
end
|
264
|
+
|
265
|
+
def key=(k)
|
266
|
+
@changed_body[:_key] = k
|
267
|
+
end
|
268
|
+
|
269
|
+
def revision
|
270
|
+
return @changed_body[:_rev] if @changed_body.key?(:_rev)
|
271
|
+
@body[:_rev]
|
272
|
+
end
|
273
|
+
|
274
|
+
def rev=(r)
|
275
|
+
@changed_body[:_rev] = r
|
276
|
+
end
|
277
|
+
|
278
|
+
def to_h
|
279
|
+
@body.delete_if{|_,v| v.nil?}
|
280
|
+
end
|
281
|
+
|
282
|
+
attr_accessor :ignore_revs, :wait_for_sync
|
283
|
+
|
284
|
+
attr_reader :collection, :graph, :database, :server, :body
|
285
|
+
|
286
|
+
# todo body= -> replace_body, update_body
|
287
|
+
def body=(doc)
|
288
|
+
@changed_body = _body_from_arg(doc)
|
289
|
+
#set_up_from_or_to("from", result[:_from])
|
290
|
+
#set_up_from_or_to("to", result[:_to])
|
291
|
+
end
|
292
|
+
|
293
|
+
def method_missing(name, *args, &block)
|
294
|
+
name_s = name.to_s
|
295
|
+
set_attr = false
|
296
|
+
have_attr = false
|
297
|
+
attribute_name_s = name_s.end_with?('=') ? (set_attr = true; name_s.chop) : name_s
|
298
|
+
attribute_name_y = attribute_name_s.start_with?('attribute_') ? (have_attr = true; attribute_name_s[9..-1].to_sym) : attribute_name_s.to_sym
|
299
|
+
if set_attr
|
300
|
+
return @changed_body[attribute_name_y] = args[0]
|
301
|
+
elsif @changed_body.key?(attribute_name_y)
|
302
|
+
return @changed_body[attribute_name_y]
|
303
|
+
elsif @body.key?(attribute_name_y)
|
304
|
+
return @body[attribute_name_y]
|
305
|
+
elsif have_attr
|
306
|
+
return nil
|
307
|
+
end
|
308
|
+
super(name, *args, &block)
|
309
|
+
end
|
310
|
+
|
311
|
+
request_method :reload do
|
312
|
+
headers = nil
|
313
|
+
headers = { "If-Match": @body[:_rev] } if !@ignore_revs && @body.key?(:_rev)
|
314
|
+
{ get: "_api/document/#{@collection.name}/#{@body[:_key]}", headers: headers,
|
315
|
+
block: ->(result) do
|
316
|
+
@body = _body_from_arg(result)
|
317
|
+
@changed_body = {}
|
318
|
+
self
|
319
|
+
end
|
320
|
+
}
|
321
|
+
end
|
322
|
+
alias refresh reload
|
323
|
+
alias retrieve reload
|
324
|
+
alias revert reload
|
325
|
+
alias batch_refresh batch_reload
|
326
|
+
alias batch_retrieve batch_reload
|
327
|
+
alias batch_revert batch_reload
|
328
|
+
|
329
|
+
request_method :same_revision? do
|
330
|
+
headers = { "If-Match": @body[:_rev] }
|
331
|
+
{ head: "_api/document/#{@collection.name}/#{@body[:_key]}", headers: headers, block: ->(result) { result.response_code == 200 }}
|
332
|
+
end
|
333
|
+
|
334
|
+
request_method :create do
|
335
|
+
query = { returnNew: true }
|
336
|
+
query[:waitForSync] = @wait_for_sync unless @wait_for_sync.nil?
|
337
|
+
@body = @body.merge(@changed_body)
|
338
|
+
@changed_body = {}
|
339
|
+
{ post: "_api/document/#{@collection.name}", body: @body, query: query,
|
340
|
+
block: ->(result) do
|
341
|
+
@body.merge!(result[:new])
|
342
|
+
self
|
343
|
+
end
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
request_method :replace do
|
348
|
+
query = { returnNew: true, ignoreRevs: @ignore_revs }
|
349
|
+
query[:waitForSync] = @wait_for_sync unless @wait_for_sync.nil?
|
350
|
+
headers = nil
|
351
|
+
body = @changed_body
|
352
|
+
body[:_id] = @body[:_id]
|
353
|
+
body[:_key] = @body[:_key]
|
354
|
+
body[:_rev] = @body[:_rev]
|
355
|
+
@body = body
|
356
|
+
@changed_body = {}
|
357
|
+
headers = { "If-Match": @body[:_rev] } if !@ignore_revs && @body.key?(:_rev)
|
358
|
+
{ put: "_api/document/#{@collection.name}/#{@body[:_key]}", body: @body, query: query, headers: headers,
|
359
|
+
block: ->(result) do
|
360
|
+
@body.merge!(result[:new])
|
361
|
+
self
|
362
|
+
end
|
363
|
+
}
|
364
|
+
end
|
365
|
+
|
366
|
+
request_method :save do
|
367
|
+
query = { returnNew: true, ignoreRevs: @ignore_revs }
|
368
|
+
query[:waitForSync] = @wait_for_sync unless @wait_for_sync.nil?
|
369
|
+
headers = nil
|
370
|
+
headers = { "If-Match": @body[:_rev] } if !@ignore_revs && @body.key?(:_rev)
|
371
|
+
changed_body = @changed_body
|
372
|
+
@changed_body = {}
|
373
|
+
{ patch: "_api/document/#{@collection.name}/#{@body[:_key]}", body: changed_body, query: query, headers: headers,
|
374
|
+
block: ->(result) do
|
375
|
+
@body.merge!(result[:new])
|
376
|
+
self
|
377
|
+
end
|
378
|
+
}
|
379
|
+
end
|
380
|
+
alias update save
|
381
|
+
alias batch_update batch_save
|
382
|
+
|
383
|
+
request_method :drop do
|
384
|
+
query = { waitForSync: @wait_for_sync }
|
385
|
+
headers = nil
|
386
|
+
headers = { "If-Match": @body[:_rev] } if !@ignore_revs && @body.key?(:_rev)
|
387
|
+
{ delete: "_api/document/#{@collection.name}/#{@body[:_key]}", query: query, headers: headers, block: ->(_) { nil }}
|
388
|
+
end
|
389
|
+
alias delete drop
|
390
|
+
alias destroy drop
|
391
|
+
alias batch_delete batch_drop
|
392
|
+
alias batch_destroy batch_drop
|
393
|
+
|
394
|
+
# === EDGE ===
|
395
|
+
|
396
|
+
def edges(collection:, direction: nil)
|
397
|
+
satisfy_class?(collection, [Arango::Collection, String])
|
398
|
+
collection = collection.is_a?(Arango::Collection) ? collection.name : collection
|
399
|
+
query = {
|
400
|
+
vertex: @body[:_id],
|
401
|
+
direction: direction
|
402
|
+
}
|
403
|
+
result = @database.request("GET", "_api/edges/#{collection}", query: query)
|
404
|
+
return result if return_directly?(result)
|
405
|
+
result[:edges].map do |edge|
|
406
|
+
collection_name, key = edge[:_id].split("/")
|
407
|
+
collection = Arango::Collection.new(collection_name, database: @database, type: :edge)
|
408
|
+
Arango::Document.new(edge, collection: collection)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def any(collection)
|
413
|
+
edges(collection: collection)
|
414
|
+
end
|
415
|
+
|
416
|
+
def out(collection)
|
417
|
+
edges(collection: collection, direction: "out")
|
418
|
+
end
|
419
|
+
|
420
|
+
def in(collection)
|
421
|
+
edges(collection: collection, direction: "in")
|
422
|
+
end
|
423
|
+
|
424
|
+
private
|
425
|
+
|
426
|
+
def _body_from_arg(arg)
|
427
|
+
case arg
|
428
|
+
when String then { _key: arg }
|
429
|
+
when Hash
|
430
|
+
arg.transform_keys!(&:to_sym)
|
431
|
+
arg[:_id] = arg.delete(:id) if arg.key?(:id) && !arg.key?(:_id)
|
432
|
+
arg[:_key] = arg.delete(:key) if arg.key?(:key) && !arg.key?(:_key)
|
433
|
+
arg[:_rev] = arg.delete(:rev) if arg.key?(:rev) && !arg.key?(:_rev)
|
434
|
+
arg.delete_if{|_,v| v.nil?}
|
435
|
+
arg
|
436
|
+
when Arango::Document then arg.to_h
|
437
|
+
when Arango::Result then arg.to_h
|
438
|
+
else
|
439
|
+
raise "Unknown arg type, must be String, Hash, Arango::Result or Arango::Document"
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|