The maintainers of arangodb provide a java driver for communicating with an arangodb server. clj-arangodb
provides a thin (and incomplete) abstraction.
For the most up to date information it is best to consult the official java documentation. In general functions are lispy versions of their java counterparts (methods).
Options are passed as maps. Keys can be keywords or strings, but should be written using cammelCase
. If an option takes multiple arguments then a vector should be used.
For more information about what constitutes a valid option for a method you must consult the java api documentation.
Assuming that you have created a user
in the arango database...
(ns user
(:require [clj-arangodb.arangodb.core :as a]
[clj-arangodb.arangodb.databases :as d]
[clj-arangodb.arangodb.collections :as c]
[clj-arangodb.arangodb.adapter :as adapter])
(:import [com.arangodb Protocol]
[com.arangodb.entity BaseDocument]
[com.arangodb.velocypack VPackSlice]))
(defonce conn ;; connections are thread safe
(let [config {:useProtocol Protocol/VST
:user "test"
:host ["127.0.0.1" 8529]}]
(a/connect config)))
user> (a/database? conn "testDB")
false
user> (def db (a/create-and-get-database conn "testDB"))
#'user/db
user> db
#object[com.arangodb.internal.ArangoDatabaseImpl 0x38f9457a "com.arangodb.internal.ArangoDatabaseImpl@38f9457a"]
user> (a/database? conn "testDB")
true
user> (a/get-databases conn)
["_system" "testDB"]
user> (d/collection? db "testColl")
false
user> (def coll (d/create-and-get-collection db "testColl"))
#'user/coll
user> (d/collection? db "testColl")
true
user> (def coll-again (d/get-collection db "testColl"))
#'user/coll-again
user> (= coll coll-again)
false
user> coll
#object[com.arangodb.internal.ArangoCollectionImpl 0x23266a4f "com.arangodb.internal.ArangoCollectionImpl@23266a4f"]
user> coll-again
#object[com.arangodb.internal.ArangoCollectionImpl 0x33859f41 "com.arangodb.internal.ArangoCollectionImpl@33859f41"]
user> (= (adapter/from-entity (:info (bean coll)))
(adapter/from-entity (:info (bean coll-again))))
true
By default functions that return a Entity
of some kind are wrapped with adapter/from-entity
.
Entity
results are only data - ie they are not handles.
The default for this is to call bean
and then examines the values under the keys.
In general if the entity contains results, these results are not
desearialzed. all sub classes are - (some are converted to string to give sensible data)
inserting a document
user> (c/insert-document coll {:hello "world"})
{:class com.arangodb.entity.DocumentCreateEntity,
:id "testColl/34730",
:key "34730",
:new nil,
:old nil,
:rev "_bH1Uxmq---"}
By default when retreiving a document the VPackSlice
class is used. This is then parsed using the [cheshire(https://github.com/dakrone/cheshire) json library.
user> (c/get-document coll "34730")
{:_key "34730",
:_id "testColl/34730",
:_rev "_bH1Uxmq---",
:hello "world"}
user> (c/get-document coll "34730" VPackSlice)
{:_key "34730",
:_id "testColl/34730",
:_rev "_bH1Uxmq---",
:hello "world"}
By passing a class as well we can get a different type back.
The BaseDocument
(belonging to ArangoDB) class is converted by calling bean
.
user> (c/get-document coll "34730" BaseDocument)
{:class com.arangodb.entity.BaseDocument,
:id "testColl/34730",
:key "34730",
:properties {"hello" "world"},
:revision "_bH1Uxmq---"}
user> (c/get-document coll "34730" String)
"{\"_key\":\"34730\",\"_id\":\"testColl\\/34730\",\"_rev\":\"_bH1Uxmq---\",\"hello\":\"world\"}"
user> (c/get-document coll "34730" java.util.Map)
{"_key" "34730",
"_id" "testColl/34730",
"_rev" "_bH1Uxmq---",
"hello" "world"}
If you want to use a custom json serializer/deserializer then you can extend the multimethods serialize-doc
and deserialize-doc
for the String
class.
The AQL query syntax can be represented as clojure data structures, there is no EBFN document at the moment so you will have to read the source file, an example taken from one of the tests: In this example the FOR statement is used to execute a graph query
(ns user
(:require [clj-arangodb.arangodb.databases :as d]
[clj-arangodb.arangodb.test-data :as td]
[clj-arangodb.arangodb.helper :as h]))
user> (td/init-game-of-thrones-db)
nil
user> (h/with-db [db td/game-of-thrones-db-label]
(let [query [:FOR ["c" "Characters"]
[:FILTER [:EQ "c.name" "\"Bran\""]]
[:FOR ["v" {:start "c"
:type :outbound
:depth [1 1]
:collections ["ChildOf"]}]
[:RETURN "v.name"]]]]
(println (vec (d/query db query String)))))
[Ned Catelyn]
Have a play - and remeber the multimethods! - if you don't like the data you are getting, change it...