Project

arangorb

0.02
No commit activity in last 3 years
No release in over 3 years
Ruby driver for ArangoDB's HTTP API
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

~> 2.2.2, >= 2.2.2
~> 0.14, >= 0.14.0
~> 3.6.11, >= 3.6.11
 Project Readme

ArangoRB Gem Version

UNMANTAINED: This project is not mantained anymore. A new Ruby ArangoDB driver project is in development here: arango-driver. Thank you a lot for your support in these years.

ArangoDatabase is a native multi-model database with flexible data models for document, graphs, and key-values. ArangoRB is a Gem to use ArangoDatabase with Ruby. ArangoRB is based on the HTTP API of ArangoDB.

ArangoRB 0.1.0 - 1.3.0 have been tested with ArangoDB 3.0 with Ruby 2.3.1
ArangoRB 1.4.0 has been tested with ArangoDB 3.1 with Ruby 2.3.3
ArangoRB 2.0.0 has been tested with ArangoDB 3.4 with Ruby 2.3.3

It requires the gems "HTTParty", "Oj" and "connection_pool"

To install ArangoRB: gem install arangorb

To use it in your application: require "arangorb"

Support

This is a project managed by one single person. ArangoDB is a wonderful project that it is hard to cover completely alone. For this reason all your supports is more than welcome. Any pull request, issue, suggestions and ideas are more than welcome. Do not be shy to contact me, create issues on Github or pushing changes.

Here something the community can help on:

  • Replication example in example/replication_year.rb is a work in progress. Any found bugs and advice to improve it will be great. I removed the IPs in the examples to make clear that it is only an example that needs work.
  • Add test and correct bugs for replication, clustering, foxx and other.
  • Improve AQL instance to implement in Rails.
  • Improve Documentation.

If you like this project, please star it. It will remind me that my work has been useful for somebody.

For the differences between version 1.4.0 and 2.0.0: Click here.

For testing: Click here.

Classes used

ArangoRB has the two type of classes.

Classes relative to ArangoDB elements:

  • Arango::Server: to manage a Server
  • Arango::Database: to manage a Database
  • Arango::Collection: to manage a Collection
  • Arango::Document: to manage a Document
  • Arango::Vertex: to manage a Vertex
  • Arango::Edge: to manage an Edge
  • Arango::Graph: to manage a Graph
  • Arango::Traversal: to manage a Traversal operation
  • Arango::AQL: to manage an AQL instances
  • Arango::User: to manage an User
  • Arango::Index: to manage an Index
  • Arango::Task: to manage a Task
  • Arango::Transaction: to manage a Transaction
  • Arango::Replication: to manage a Replication
  • Arango::Batch: to manage a Batch of multiple requests
  • Arango::Foxx: to manage a Foxx instance
  • Arango::View: to manage a View instance

Classes relative to the Gem ArangoRB

  • Arango::Cache: to manage internal Cache
  • Arango::Error: to handle ArangoRB errors

All the instances of these classes can be transformed in Hash with the method to_h.

Many methods can have multiple attributes not mentioned in this documentation. Keep in mind that if an attribute is defined in the ArangoDB documentation, then it is easy that it is an attribute for the relative method too. Please refer to the ArangoDB documentation, the rubydoc documentation or open an issue for this missing attributes.

Arango::Server

Arango::Server is used to manage a single server by managing the connection with ArangoDB. You can provide your login credentials and it is a mandatory step to start your database.

To setup a server use the following way:

server = Arango::Server.new username: "MyUsername", password: "MyPassword",
  server: "localhost", port: "8529", tls: false
server.username = "MyOtherUsername" # Default "root"
server.password = "other_password"  
server.server   = "127.0.0.1"       # Default "localhost"
server.port     = "8765"            # Default "8529"
server.tls      = true   # Default false, to do https requests instead of http

Password is a mandatory field.

Returning results

ArangoRB try always to store the information obtained from ArangoDB in an instance. If you need to receive the output, you can return it with:

server.return_output = true # Default false

Verbose and warnings

For Debugging reasons the user can print out the request and response to ArangoDB by setting verbose to true.

server.verbose = true # Default false

Remember that verbose is only for testing reason: to work efficiently verbose should be false.

Some deprecated methods will return a warning. To silence these warnings use:

server.warning = false # Default true

Connection Pool

ArangoRB supports connection pool, to activate it you can setup pool to true during the initialization or the proceedings. To do so use:

server = Arango::Server.new username: "MyUsername", password: "MyPassword",
  server: "localhost", port: "8529", pool: true, size: 5, timeout: 5, tls: false
server.pool = true  # Defult false
server.size = 7     # Default 5
server.timeout = 10 # Default 5
server.restartPool  # Restart pool with new size and timeout

NB: ConnectionPool is not heavily tested.

Cache

Often ArangoRB returns multiple time the same object (for example for lists or for retrieving). It can happens thus that a document instance updated somewhere in your code, it is not update somewhere even if you are refering the same ArangoDB document. To avoid this, ArangoRB provides its own cache.

You can activate the ArangoRB cache by using:

server.active_cache = true # Default false

If active_cache is true, then a previous document or collection instance will be stored in the ArangoRB cache. In case a new instance of the same document is created, then a new instance will NOT be created but, instead, the old one will be returned.

With an example:

server.active_cache = false
a = Arango::Document.new name: "test", collection: my_collection
b = Arango::Document.new name: "test", collection: my_collection
# In this case a and b are two different instances
server.active_cache = true
a = Arango::Document.new name: "test", collection: my_collection
b = Arango::Document.new name: "test", collection: my_collection
# In this case a and b are the same instance

Note that if you set server.active_cache to false, then the stored Cache will be emptied. For more information about the cache, look at the section about Arango::Cache.

Information

Basic information can be retrieved with these command.

server.to_h      # Return an hash of the instances
server.endpoint  # Check address used to connect with the server
server.username  # Check name used to connect with the server
server.verbose   # Check if verbose is true or false
server.async     # Check the status of async

To retrieve lists

server.databases # Lists of available databases
server.endpoints # Lists of endpoints used
server.users     # Lists of available users
server.tasks     # Lists of available tasks

To monitoring the server you can use the following commands

server.log # Return log files
server.loglevel
server.updateLoglevel body: body
server.available?    # Reloads the routing information from the collection routing.
server.reload        # Reloads the routing information from the collection routing.
server.statistics    # Returns the statistics information
server.statisticsDescription # Fetch descriptive info of statistics
server.status     # Status of the server
server.role       # Get to know whether this server is a Coordinator or DB-Server
server.serverData # Get server data
server.mode       # Get server mode
server.updateMode(mode: "default") # Change mode of the server

Manage Async

With Arango::Server you can manage Async results. It can be useful to use async for heavy requests (like the one in example/year.rb).

server.async = false  # default
server.async = true   # fire and forget
server.async = :store # fire and store

If Async is "store", then the commands of ArangoRB will return the id of the Async requests. Arango::Server provides different methods to manage these Async requests.

server.fetchAsync    id: id # Fetches a job result and removes it from the queue
server.cancelAsync   id: id # Cancels an async job
server.destroyAsync  id: id # Deletes an async job result
server.retrieveAsync id: id # Returns the status of a specific job
server.retrieveAsyncByType type: type # Returns the ids of job results with a specific
# status. Type can be "done" or "pending"
server.retrieveDoneAsync       # Equivalent to server.retrieveAsync type: "done"
server.retrievePendingAsync    # Equivalent to server.retrieveAsync type: "pending"
server.destroyAsync type: type # Deletes async jobs with a specific status
                               # Type can be "all" or "expired"
server.destroyAllAsync         # Equivalent to server.destroyAsync type: "all"
server.destroyExpiredAsync     # Equivalent to server.destroyAsync type: "expired"

Miscellaneous

server.version           # Returns the server version number
server.engine            # Returns the server engine
server.flushWAL          # Flushes the write-ahead log
server.propertyWAL       # Retrieves the configuration of the write-ahead log
server.changePropertyWAL # Configures the write-ahead log
server.transactions      # Returns information about the currently running transactions
server.time              # Get the current time of the system
server.echo              # Return current request
server.databaseVersion   # Return the required version of the database
server.shutdown          # Initiate shutdown sequence

UNTESTED

server.test body: body    # Runs tests on server
server.execute body: body # Execute a script on the server.

Cluster (UNTESTED)

ArangoDB permits the sharding of the database. Although these methods has not been tested with ArangoRB.

server.clusterHealth port: port # Allows to check whether a given port is usable
server.serverId                 # Returns the id of a server in a cluster.
server.clusterStatistics dbserver: dbserver # Allows to query the statistics of a
                                            # DBserver in the cluster

Arango::Database

Arango::Database is used to manage a Database. You can create an instance in one of the following ways:

myDatabase = server.database name: "MyDatabase"
myDatabase = server["MyDatabase"]
myDatabase = Arango::Database.new database: "MyDatabase", server: server

Main methods

myDatabase.create   # Create a new Database
myDatabase.retrieve # Retrieve database
myDatabase.destroy   # Delete the selected Database

Retrieve information

server.databases       # Obtain an Array with the available databases in the server
myDatabase.to_h        # Hash of the instance
myDatabase.info        # Obtain general info about the databases
myDatabase.sever       # Return the server connected with the database
myDatabase.collections # Obtain an Array with the available collections in the selected Database
myDatabase.graphs       #  Obtain an Array with the available graphs in the selected Database
myDatabase.aqlFunctions #  Obtain an Array with the available functions in the selected Database
myDatabase.foxxes # Return all the foxx available in the database
myDatabase.views  # Return all the views available in the database
myDatabase.tasks  # Return all the tasks available in the database

Arango::AQL

An AQL instance can be created by using one of the following way:

query = "FOR v,e,p IN 1..6 ANY 'Year/2016' GRAPH 'MyGraph' FILTER p.vertices[1].num == 6 && p.vertices[2].num == 22 && p.vertices[6]._key == '424028e5-e429-4885-b50b-007867208c71' RETURN [p.vertices[4].value, p.vertices[5].data]"
myQuery = myDatabase.aql query: query
myQuery = ArangoAQL.new database: myDatabase, query: query

To execute it use:

myQuery.execute

If the query is too big, you can divide the fetching in pieces, for example:

myQuery.size = 10
myQuery.execute # First 10 documents
myQuery.next    # Next 10 documents
myQuery.next    # Next 10 documents

Other useful methods are the following

myQuery.destroy # Destroy cursor to retrieve documents
myQuery.kill    # Kill query request (if requires too much time)
myQuery.explain # Show data query
myQuery.parse   # Parse query

Query Properties

It is possible to handle generic properties of query by Arango::Database.

myQuery.to_h                                # Return an hash version of the instance
myQuery.properties                          # Check Query properties
myQuery.current                             # Retrieve current running Query
myQuery.changeProperties maxSlowQueries: 65 # Change Properties
myQuery.slow                                # Retrieve slow Queries
myQuery.stopSlowQueries                     # Stop slow Queries

The cache of the query can handle in the following way:

myDatabase.retrieveQueryCache                      # Retrieve Query Cache
myDatabase.clearQueryCache                         # Clear Query Cache
myDatabase.propertyQueryCache                      # Check properties Cache
myDatabase.changePropertyQueryCache maxResults: 30 # Change properties Cache

AQL Functions

AQL queries can be potentiate by providing javascript function as supports.

myDatabase.createAqlFunction code: "function(){return 1+1;}", name: "myFunction" # Create a new AQL Function
myDatabase.deleteFunction name: "myFunction" # Delete an AQL function
myDatabase.aqlFunctions # Retrieve a list of the available aql functions

Arango::Collection

Arango::Collection is used to manage your Collections. You can create an Arango::Collection instance in one of the following way:

myCollection = myDatabase.collection name: "MyCollection"
myCollection = myDatabase["MyCollection"]
myCollection = Arango::Collection.new database: myDatabase, collection: "MyCollection"

A Collection can be of two types: "Document" and "Edge". If you want to specify it, uses:

myCollectionA = ArangoCollection.new collection: "MyCollectionA", type: :document # Default
myEdgeCollection = ArangoCollection.new collection: "MyCollectionB", type: :edge

Main methods

myCollection.create   # Create collection
myCollection.destroy  # Delete collection from database
myCollection.truncate # Delete all the Documents inside the selected Collection
myCollection.retrieve # Retrieve the selected Collection

Info methods

myCollection.database   # Return database of the collection
myCollection.server     # Returm server of the collection
myCollection.indexes    # Return a list of all used Indexes in the Collection
myCollection.rotate     # Rotate the collection
myCollection.data       # Returns the whole content of one collection
myCollection.properties # Properties of the Collection
myCollection.count      # Number of Documents in the Collection
myCollection.stats      # Statistics of the Collection
myCollection.revision   # Return collection revision id
myCollection.checksum   # Return checksum for the Collection

Modify the Collection

myCollection.load   # Load the collection (preparing for retrieving documents)
myCollection.unload # Unload the collection (if you stop to work with it)
myCollection.loadIndexesIntoMemory            # Load indexes in memory
myCollection.change(waitForSync: true)        # Change some properties
myCollection.rename(newName: "myCollection2") # Change name (NB: This is not Arango::Cache compatible)
myCollection.rotate # Rotate journal of a collection

Handle documents

To retrieve all the documents of a Collection you can use:

myCollection.documents
myCollection.allDocuments

These two functions are similar except for the fact that you can assign different variables.

myCollection.documents type: "path"
myCollection.next # Retrieve other documents if the first request is not finished

Type can be "path", "id" or "key" in relation what we wish to have. If not specified ArangoRB will return an array of Arango::Document instances.

myCollection.allDocuments skip: 3, limit: 100, batchSize: 10

It means that we skip the first three Documents, we can retrieve the next 100 Documents but we return only the first ten.

To retrieve specific Document you can use:

myCollection.documentsMatch match: {"value":  4}   # All Documents of the Collection with value equal to 4
myCollection.documentMatch match: {"value":  4}    # The first Document of the Collection with value equal to 4
myCollection.documentByKeys keys: ["4546", "4646"] # Documents of the Collection with the keys in the Array
myCollection.documentByName names: ["4546", "4646"] # Documents of the Collection with the name in the Array
myCollection.random # A random Document of the Collection

Modifying multiple documents

From a collection is it possible to create, remove and modify multiple documents.

myCollection.createDocuments document: [myDocumentA, myDocumentB, {"value":  17}] # Array of Arango::Document instances and Hashes
myCollection.removeByKeys keys: ["4546", "4646"] # Documents of the Collection with the keys in the Array will be removed
myCollection.removeMatch match: {"value":  4} # All Documents of the Collection with value equal to 4 will be removed
myCollection.replaceMatch match: {"value":  4}, newValue: {"value":  6} # All Documents of the Collection with value equal to 4 will be replaced with the new Value
myCollection.updateMatch match: {"value":  4}, newValue: {"value":  6} # All Documents of the Collection with value equal to 4 will be updated with the new Value

Create multiple Edges at once

We have the possibility to create different combination of Edges in only one line of code.

One-to-one with one Edge class

  • [myDocA] --(myEdge)--> [myDocB]
myEdgeCollection.createEdges document: myEdge, from: myDocA, to: myDocB

One-to-more with one Edge class (and More-to-one with one Edge class)

  • [myDocA] --(myEdge)--> [myDocB]
  • [myDocA] --(myEdge)--> [myDocC]
myEdgeCollection.createEdges document: myEdge, from: myDocA, to: [myDocB, myDocC]

More-to-More with one Edge class

  • [myDocA] --(myEdge)--> [myDocC]
  • [myDocB] --(myEdge)--> [myDocC]
  • [myDocA] --(myEdge)--> [myDocD]
  • [myDocB] --(myEdge)--> [myDocD]
myEdgeCollection.createEdges document: myEdge, from: [myDocA, myDocB], to: [myDocC, myDocD]

More-to-More with more Edge classes

  • [myDocA] --(myEdge)--> [myDocC]
  • [myDocB] --(myEdge)--> [myDocC]
  • [myDocA] --(myEdge)--> [myDocD]
  • [myDocB] --(myEdge)--> [myDocD]
  • [myDocA] --(myEdge2)--> [myDocC]
  • [myDocB] --(myEdge2)--> [myDocC]
  • [myDocA] --(myEdge2)--> [myDocD]
  • [myDocB] --(myEdge2)--> [myDocD]
myEdgeCollection.createEdges document: [myEdge, myEdge2], from: [myDocA, myDocB], to: [myDocC, myDocD]

Import and Export Documents

Another way to create multiple documents in a Collection with only one request is by using the method import.

Import one Document with Array

We can import one document with the following structure {"value": "uno", "num": 1, "name": "ONE"}.

attributes = ["value", "num", "name"]
values     = ["uno",1,"ONE"]
myCollection.import attributes: attributes, values: values

Import more Documents with Array

We can import three Documents with the following structure {"value": "uno", "num": 1, "name": "ONE"}, {"value": "due", "num": 2, "name": "TWO"}, {"value": "tre", "num": 3, "name": "THREE"}.

attributes = ["value", "num", "name"]
values     = [["uno",1,"ONE"],["due",2,"TWO"],["tre",3,"THREE"]]
myCollection.import attributes: attributes, values: values

Import more Documents with JSON

I import two Documents with the following structure {"value": "uno", "num": 1, "name": "ONE"}, {"value": "due", "num": 2, "name": "TWO"}.

body = [{"value": "uno", "num": 1, "name": "ONE"}, {"value": "due", "num": 2, "name": "DUE"}]
myCollection.importJSON body: body

Export files

As it is possible to import files, it is possible to export all the Document of a Collection with the following command.

myCollection.export

Alternatively it is possible to retrieve all the Documents in a Collection gradually.

myCollection.export batchSize: 3 # First three Documents of the Collection
myCollection.exportNext # Next three Documents
myCollection.exportNext # Next three Documents

Arango::Document

An Arango::Document is an element of a Arango::Collection. Edges are Arango documents with "_from" and "_to" in their body. You can create an ArangoCollection instance in one of the following way:

myDocument = myCollection.document name: "MyDocument"
myDocument = myCollection["MyDocument"]
myDocument = Arango::Document.new collection: myCollection, name: "MyDocument"

In the case you want to define a Edge, it is convenient to introduce the parameters "from" and "to" in the instance.

myEdge = Arango::Document.new name: "MyEdge", from: myDocA, to: myDocB

where myDocA and myDocB are the IDs of two Documents or are two Arango::Document instances.

During the creation of an Arango::Document instance, it is possible to define the body for the Document.

myDocument = Arango::Document.new body: {"value":  17}, name: "MyDocument"

Main methods

ArangoRB provides several way to create a single Document.

myDocument.create                      # Create a new document
myDocument.retrieve                    # Retrieve Document
myDocument.update body: {"value":  3}  # We update or add a value
myDocument.replace body: {"value":  3} # We replace a value
myDocument.destroy                     # Destroy document

Retrieve information

myDocument.collection # Retrieve Collection of the Document
myDocument.database   # Retrieve Database of the Document
myDocument.server     # Retrieve Server of the Document
myDocument.edges collection: myEdgeCollection  # Retrieve all myEdgeCollection edges connected with the Document
myDocument.any(myEdgeCollection) # Retrieve all myEdgeCollection edges connected with the Document
myDocument.in(myEdgeCollection)  # Retrieve all myEdgeCollection edges coming in the Document
myDocument.out(myEdgeCollection) # Retrieve all myEdgeCollection edges going out the Document
myEdge.from # Retrieve the document at the begin of the edge
myEdge.to   # Retrieve the document at the end of the edge

Example: how to navigate the edges

It is possible to navigate between edges and vertexes of a graph database.

Think for example that we have the following schema:

  • A --[class: a, name: aa]--> B
  • A --[class: a, name: bb]--> C
  • A --[class: b, name: cc]--> D
  • B --[class: a, name: dd]--> E

Then we have:

  • A.retrieve is A
  • A.edges(collection: a) is [aa, bb]
  • B.in(a) is [aa]
  • B.out(a) is [dd]
  • B.any(a) is [aa, dd] (aa in entry, dd in exit)
  • aa.from is A
  • aa.to is B

We can even do some combinations: for example A.out(a)[0].to.out(a)[0].to is E since:

  • A.out(a) is [aa]
  • A.out(a)[0] is aa
  • A.out(a)[0].to is B
  • A.out(a)[0].to.out(a) is [dd]
  • A.out(a)[0].to.out(a)[0] is dd
  • A.out(a)[0].to.out(a)[0].to is E

Arango::Graph

ArangoGraph are used to manage Graphs. You can create an Arango::Graph instance in one of the following way.

myGraph = myDatabase.graph name: "MyGraph"
myGraph = Arango::Graph.new name: "MyGraph", database: myDatabase

Main methods

myGraph.create   # create a new Graph
myGraph.retrieve # retrieve the Graph
myGraph.database # retrieve database of the Graph
myGraph.destroy  # destroy the Graph

Manage Vertex Collections

myGraph.getVertexCollections # Retrieve all the vertexCollections of the Graph
myGraph.addVertexCollection collection: "myCollection"  # Add a Vertex Collection to our Graph
myGraph.removeVertexCollection collection: "myCollection"  # Remove a Vertex Collection to our Graph

Manage Edge Collections

myGraph.edgeCollections # Retrieve all the edgeCollections of the Graph
myGraph.addEdgeCollections collection: "myEdgeCollection", from: "myCollectionA", to: "myCollectionB"  # Add an Edge Collection to our Graph
myGraph.replaceEdgeCollections collection: "myEdgeCollection", from: "myCollectionA", to: "myCollectionB"  # Replace an Edge Collection to our Graph
myGraph.removeEdgeCollections collection: "myEdgeCollection"  # Remove an Edge Collection to our Graph

Arango::Vertex and Arango::Edge

Both these two classes inherit the class Arango::Document. These two classes have been created since Arango::Database offers, in connection of the chosen graph, different HTTP requests to manage Vertexes and Edges. We recommend the reader to read carefully the section on Arango::Document instances before to start to use Arango::Vertex and Arango::Edge instances.

Arango::Vertex methods

Arango::Vertex inherit all the methods of Arango::Document class. The following one works similar to the one of Arango::Document Class but use different HTTP requests. For this reason the performance could be different. To use Arango::Vertex, the Collection of the Vertex needs to be added either to the VertexCollections or to the EdgeCollections of the chosen Graph. And the Collection needs to have assigned the graph.

myCollection.graph = myGraph # Be sure that the collection is assigned to a Graph
myVertex = myCollection.vertex name: "newVertex", body: {"value":  3} # If graph is not assigned, an Arango::Document will be created
myVertex = Arango::Vertex.new name: "newVertex", body: {"value":  3},
  collection: myCollection # create a new instance
myVertex.create    # create a new Document in the Graph
myVertex.retrieve  # retrieve a Document
myVertex.graph     # retrieve Graph of the Document
myVertex.replace body: {"value":  6} # replace the Document
myVertex.update  body: {"value":  6} # update the Document
myVertex.destroy   # delete the Document

Arango::Edge methods

Arango::Edge inherit all the methods of Arango::Document class. The following one works similar to the one of Arango::Document Class but use a different HTTP request. For this reason the performance could be different. To use Arango::Edge, the Collection of the Edge needs to be added to the EdgeCollections of the chosen Graph.

myEdgeCollection.graph = myGraph
myEdge = myCollection.edge name: "newEdge", body: {"value":  3}, from: myArangoDocument1, to: myArangoDocument2 # If graph is not assigned, an Arango::Document will be created
myEdge.create   # create a new Document of type Edge in the Graph
myEdge.retrieve # retrieve a Document
myEdge.graph    # Retrieve Graph  of the Document
myEdge.replace body: {"value":  6} # replace the Document
myEdge.update  body: {"value":  6} # update the Document
myEdge.destroy  # delete the Document

Arango::Traversal

Arango::Traversal is used to administrate the traversals. Arango::Traversal needs to know the vertex from where the traversal starts, the direction the traversal is going and either the Graph or the EdgeCollection we want to analyze.

myTraversal = myVertex.traversal   # Start traversal from myVertex
myTraversal = myDocument.traversal # Start traversal from myDocument
myTraversal = ArangoTraversal.new database: myDatabase, startVertex: myVertex # create instance
myTraversal.vertex = myVertex # define starting Vertex
myTraversal.edgeCollection = myEdgeCollection # define used Edge
myTraversal.in      # Direction is in
myTraversal.out     # Direction is out
myTraversal.any     # Direction is in and out
myTraversal.min = 1 # Define how minimum deep we want to go with the traversal
myTraversal.max = 3 # Define how maximum deep we want to go with the traversal

After the traversal is setup, you can execute it:

myTraversal.execute

Arango::User

Arango::User manages the users. To initialize an user:

myUser = server.user name: "MyUser", password: "password"
myUser = Arango::User.new user: "MyUser", password: "password", server: server

User management

myUser.retrieve               # Retrieve User
myUser["MyDatabase"]          # Retrieve database if the user can access it
myUser.database("MyDatabase") # Retrieve database if the user can access it
myUser.create                 # Create a new User
myUser.replace active: false  # Replace User
myUser.update active: false   # Update User
myUser.destroy               # Delete User

Database management

myUser.databases # List of databases can access
myUser.addDatabaseAccess grant: "rw", database: myDatabase
myUser.grant          database: myDatabase # Grant access to a database
myUser.revoke         database: myDatabase # Revoke access to a database
myUser.databaseAccess database: myDatabase # Check permission level of an User
myUser.addCollectionAccess grant: "rw", database: myDatabase, collection: myCollection
myUser.revokeCollectionAccess database: myDatabase, collection: myCollection
myUser.collectionAccess database: myDatabase, collection: myCollection

You can manage the user permissions from the database or from the collection too.

myDatabase.check_user(myUser)
myDatabase.addUserAccess(grant: "rw", user: myUser)
myDatabase.revokeUserAccess(user: myUser)
myDatabase.userAccess(user: myUser)
myCollection.check_user(myUser)
myCollection.addUserAccess(grant: "rw", user: myUser)
myCollection.revokeUserAccess(user: myUser)
myCollection.userAccess(user: myUser)

Arango::Index

Arango::Index manages the indexes. To initialize an index:

myIndex = myCollection.index fields: "num", unique: false, id: "myIndex"
myIndex = Arango::Index.new  fields: "num", unique: false, id: "myIndex", collection: myCollection

Index management

myIndex.retrieve # Retrieve Index
myIndex.create # Create a new Index
myIndex.destroy # Delete Index

Arango::Transaction

Transactions are managed by Arango::Transaction.

action = "function(){ var db = require('@arangodb').db; db.MyCollection.save({}); return db.MyCollection.count(); }"
myTransaction = myDatabase.transaction action: action
myTransaction = Arango::Transaction.new action: action, database: myDatabase
myTransaction.addWrite(myCollection) # Add write collection
myTransaction.addRead(myCollection) # Add read collection
myArangoTransaction.execute # Return the result of the execution

Arango::Task

Tasks are managed by ArangoTask.

command = "(function(params) { require('@arangodb').print(params); })(params)"
myTask = myDatabase.task id: "mytaskid", name: "MyTaskID", command: command, params: {"foo":  "bar", "bar":  "foo"}, period: 2
myTask = Arango::Task.new id: "mytaskid", name: "MyTaskID", command: command, params: {"foo":  "bar", "bar":  "foo"}, period: 2, database: myDatabase
myArangoTask.create   # Create a new Task
myArangoTask.retrieve # Retrieve a Task
myArangoTask.destroy  # Delete a Task

Arango::Replication

Replication is useful to create back up copy of your database or to have a master-slave relationship between two databases.

Remember: the used database is the one where the data will be written (the slave) and the remote database will be the master one.

Use with caution since the data in the slave database will be deleted.

To setup our Slave Server and Master Database use a similar command.

myReplication = slaveDatabase.replication(master: masterDatabase)
myReplication = masterDatabase.replication_as_master(slave: slaveDatabase)
myReplication = Arango::Replication.new master: masterDatabase, slave: slaveDatabase

Than to do a simple syncronization uses;

myReplication.sync    # Sync master - slave database

To retrieve other information ArangoRB provides the following methods:

myReplication.logger       # Returns the current state of the server's replication logger
myReplication.loggerFollow # Returns data from the server's replication log.
myReplication.firstTick    # Return the first available tick value from the server
myReplication.rangeTick # Returns the currently available ranges of tick values for all currently available WAL logfiles.
myReplication.serverId  # Returns the servers id.

Relation Master-Slave

To enslave a Server in relation to another Database use the following command:

myReplication.enslave

To manage the Configuration of a Master-Slave Replication you can use the following commands:

myReplication.start   # Start replication
myReplication.configuration # check the Configuration of the Replication
myReplication.state   # check the status of the Replication
myReplication.stop    # stop the Replication
myReplication.modify  # modify the Configuration of the Replication (you can modify only a stopped Replication)

Arango::Batch

To create a batch request, you can use ArangoRB::Batch object. This permit to do multiple requests with one single call to the API.

To create a batch use one of the following way:

batch = server.batch
batch = Arango::Batch.new(server: server)

To add a queries to the batch request you can use the brutal way:

batch.queries = [
  {
    "type": "POST",
    "address": "/_db/MyDatabase/_api/collection",
    "body": {"name": "newCOLLECTION"},
    "id": "1"
  },
  {
    "type": "GET",
    "address": "/_api/database",
    "id": "2"
  }
]

Or the Ruby way (the id will be handled by the system, if not specified):

batch = server.batch
batch.addQuery(method: "POST", address: "/_db/MyDatabase/_api/collection",
  body: {"name": "newCOLLECTION"})
batch.addQuery(method: "GET", address: "/_api/database")

In both the cases the queries will be stored in an hash with key the id of the query and as value the query. This query can be handled with the following methods:

batch.to_h # Retrieve an hash version of the instance
batch.modifyQuery(id: "1", method: "GET", address: "/_db/MyDatabase/_api/collection/newCOLLECTION") # Modify the Query with id "1"
batch.removeQuery(id: "1") # Remove query

To execute the query use:

batch.execute

To manage how the server handle the batch, Arango::Server offers the following functions:

server.createDumpBatch ttl: 10 # Create a new dump batch with 10 second time-to-live (return id of the dumpBatch)
server.prolongDumpBatch id: idDumpBatch, ttl: 20 # Prolong the life of a batch for 20 seconds
server.destroyDumpBatch id: idDumpBatch # Delete a selected batch

Arango::View

Views are managed by Arango::View.

myView = myDatabase.view name: "MyView"
myView = Arango::View.new name: "MyView", database: myDatabase
myView.addLink(collection: myCollection) # Add a collection to the link
myView.retrieve               # Retrieve view
myView.create                 # Create a view
myView.replaceProperties      # Replace properties
myView.updateProperties       # Update properties
myView.rename name: "MyView2" # Change name
myView.properties             # Check properties
myView.destroy                # Delete view

Arango::Foxx

Views are managed by Arango::Foxx. This instance of Foxx is untested.

myFoxx = myDatabase.foxx mount: address
myFoxx = Arango::Foxx.new mount: address, database: myDatabase
myFoxx.retrieve # Retrieve foxx
myView.create   # Create a foxx
myFoxx.update   # Update foxx
myFoxx.replace  # Replace foxx
myFoxx.destroy  # Delete foxx

Other methods

myFoxx.retrieveConfiguration
myView.updateConfiguration body: body
myFoxx.replaceConfiguration body: body
myFoxx.retrieveDependencies
myFoxx.updateDependencies body: body
myFoxx.replaceDependencies body: body
myFoxx.scripts
myFoxx.run_script name: "test"
myFoxx.tests
myFoxx.enableDevelopment
myFoxx.disableDevelopment
myFoxx.readme
myFoxx.swagger
myFoxx.download path: path
myFoxx.commit body: body

Arango::Cache

Arango::Cache is to manage ArangoRB Cache (NOT ArangoDB cache) and it helps you to manage your documents around your code. In this way if you update an Arango::Document in your code, it will updated everywhere. An Arango::Cache instance is created together with the initialization of a server instance with active_cache true.

cache = server.cache # Arango::Cache instance
cache.max            # Max number of variable stored in the cache
cache.updateMax(type: :document, val: 400) # Update how many documents store in the cache
cache.clear          # Clear cache
cache.to_h           # Hash of the cache

NB: If you insert a max value higher than the quantity of elements in the Cache, then the first elements in excess will be removed from the Cache.

If the limit of the Cache for one type is reached, then the first element cached of that type will be deleted from the Cache.

Arango::Error

Error from ArangoRB are managed by Arango::Error. Each ArangoRB error is provided of a code and a message. The list of code can be find in the file lib/Error.rb

begin
  Arango::Collection.new name: "Test", database: not_a_database
rescue Arango::Error => e
  e.message # Message of the error
  e.code    # ArangoRB code, each ArangoRB errors provides a list of errors
  e.data    # More information about the error
  e.to_h    # Hash version of the error
end

Arango::Error has a children class called Arango::ErrorDB to handle Errors coming from wrong HTTP requests.

begin
  Arango::Collection.new(name: "DuplicateCollection", database: myDatabase).create
rescue Arango::Error => e
  e.message  # Message of the error
  e.code     # HTTP error code
  e.data     # More information about the error
  e.errorNum # ArangoDB errorNum code
  e.action   # Type of request done to ArangoDB (POST, GET, ...)
  e.url      # URL requested to ArangoDB
  e.request  # Request made to ArangoDB
  e.to_h     # Hash version of the error
end

Testing

To test ArangoRB you can use:

rspec spec/arangoRB_helper.rb
ruby examples/year.rb
ruby examples/year2.rb

Remember however the following:

  • Setup the correct server in lib/spec_helper.rb and in the examples
  • The test examples/year2.rb should run much after the test examples/year.rb, since the last test is dependent from the conclusion of the first test (that is running in async).

Differences between version 1.4 and 2.0

ArangoRB 1.4 and ArangoRB 2.0 are not compatible. The new version provide different improvements.

  • Now all the instances are in a module Arango. This means that previous classes like ArangoServer will become Arango::Server.
  • Arango::Server is now an instance. This means that ArangoRB 2.0 will permits to use different servers.
  • ArangoRB has implemented connection_pool.
  • ArangoRB has now a better implementation of Cache.
  • The returned values are returned with symbols as keys.
  • Oj is used for parsing instead of JSON.
  • Add supports for View and Foxx. The least is untested.
  • Better hierarchy handling between the different instances. For example now myDocument.database will return the database instance that includes the document.
  • Better handling of replication (untested).
  • Clean in general the code (for future maintainer).
  • Now errors are handled by Arango::Error.