arango-driver 3.5.0.alpha0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|