MarcoPolo
Main API for interfacing with OrientDB.
This module provides functions to connect to a running OrientDB server and to perform commands on it.
A connection to OrientDB can be established using the start_link/1
function and stoppped with stop/1
.
Connection type
OrientDB makes a distinction between server operations and database operations. Server operations are operations that are performed at server level: examples of these operations are checking if a database exists or creating a new database. Database operations have to be performed inside a database: examples of such operations are inserting a new record or getting the number of records in the database.
Server and database operations can only be performed by the appropriate connection: a connection to the server can perform only server operations, while a connection to a database can perform only database operations. The connection type is chosen when the connection is started via start_link/1
.
Examples
conn_type = {:db, "GratefulDeadConcerts", :document}
{:ok, conn} = MarcoPolo.start_link(user: "admin", password: "admin", connection: conn_type)
MarcoPolo.command(conn, "SELECT FROM OUser")
#=> {:ok, [...users...]}
Summary
Execute the given query
in the database to which conn
is connected
Creates a database on the server
Creates a record in the database to which conn
is connected
Returns the number of records in the database to which conn
is connected
Tells if the database called name
with the given type
exists
Reloads the database to which conn
is connected
Returns the size of the database to which conn
is connected
Deletes a record from the database to which conn
is connected
Drop a database on the server
Subscribes to a Live Query for the given query
Unsubscribes from the live query identified by token
Loads a record from the database to which conn
is connected
Executes a script in the given language
on the database conn
is connected to
Starts the connection with an OrientDB server
Closes the connection (asynchronously), doing the required cleanup work
Runs operations inside a transaction on the database to which conn
is connected
Updates the given record in the databse to which conn
is connected
Types
db_type :: :document | :graph
storage_type :: :plocal | :memory
tx_operation :: {:create | :update | :delete, rec}
Functions
Specs
command(pid, String.t, Keyword.t) ::
{:ok, %{response: term, linked_records: linked_records}} |
{:error, term}
Execute the given query
in the database to which conn
is connected.
OrientDB makes a distinction between idempotent queries and non-idempotent queries (it calls the former queries and the latter commands). In order to provide a clean interface for performing operations on the server, MarcoPolo
provides only a command/3
function both for idempotent as well as non-idempotent operations. Whether an operation is idempotent is inferred by the text in query
. As of now, SELECT
and TRAVERSE
operations are idempotent while all other operations are non-idempotent.
Options
The options that this function accepts depend in part on the type of the operation.
The options shared by both idempotent and non-idempotent operations are the following:
:params
- a map of params with atoms or strings as keys and any encodable term as values. These parameters are used by OrientDB to build prepared statements as you can see in the examples below. Defaults to%{}
.:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
The additional options for idempotent (e.g., SELECT
) queries are:
:fetch_plan
: a string specifying the fetch plan. Mandatory forSELECT
queries.
Return value
If the query is successful then the return value is an {:ok, values}
tuple. values
is a map with the following keys:
:response
- depends on the performed query. For example aSELECT
query will return a list of records, while aCREATE CLUSTER
command will return a cluster id.:linked_records
- it's a set of additional records that have been fetched by OrientDB. This can be controlled using a fetch plan in the query. You're not supposed to manipulate this value directly (so that the implementation can stay flexible); use the functions in theMarcoPolo.FetchPlan
module to work with linked records.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Examples
The following is an example of an idempotent command:
iex> opts = [params: %{name: "jennifer"}, fetch_plan: "*:-1"]
iex> query = "SELECT FROM User WHERE name = :name AND age > 18"
iex> {:ok, %MarcoPolo.Document{} = doc} = MarcoPolo.command(conn, query, opts)
iex> doc.fields["name"]
"jennifer"
iex> doc.fields["age"]
45
The following is an example of a non-idempotent command:
iex> query = "INSERT INTO User(name) VALUES ('meg', 'abed')"
iex> {:ok, [meg, abed]} = MarcoPolo.command(conn, query)
iex> meg.fields["name"]
"meg"
iex> abed.fields["name"]
"abed"
Specs
create_db(pid, String.t, db_type, storage_type, Keyword.t) ::
:ok |
{:error, term}
Creates a database on the server.
name
is used as the database name, type
as the database type (:document
or :graph
) and storage
as the storage type (:plocal
or :memory
).
This operation can only be performed on connections to the server. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> MarcoPolo.create_db(conn, "MyCoolDatabase", :document, :plocal)
:ok
Specs
create_record(pid, non_neg_integer, rec, Keyword.t) ::
{:ok, {MarcoPolo.RID.t, non_neg_integer}} |
{:error, term}
Creates a record in the database to which conn
is connected.
cluster_id
specifies the cluster to create the record in, while record
is the MarcoPolo.Document
struct representing the record to create.
The return value in case of success is {:ok, {rid, version}}
where rid
is the rid of the newly created record and version
is the version of the newly created record.
Options
This function accepts the following options:
:no_response
- iftrue
, send the request to the OrientDB server without waiting for a response. This performs a fire and forget operation, returning:ok
every time.:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Examples
iex> record = %MarcoPolo.Document{class: "MyClass", fields: %{"foo" => "bar"}}
iex> MarcoPolo.create_record(conn, 15, record)
{:ok, {%MarcoPolo.RID{cluster_id: 15, position: 10}, 1}}
Specs
db_countrecords(pid, Keyword.t) ::
{:ok, non_neg_integer} |
{:error, term}
Returns the number of records in the database to which conn
is connected.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> MarcoPolo.db_countrecords(conn)
{:ok, 7931}
Specs
db_exists?(pid, String.t, storage_type, Keyword.t) ::
{:ok, boolean} |
{:error, term}
Tells if the database called name
with the given type
exists.
This operation can only be performed on connections to the server. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> MarcoPolo.db_exists?(conn, "GratefulDeadConcerts", :plocal)
{:ok, true}
Reloads the database to which conn
is connected.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> MarcoPolo.db_reload(conn)
:ok
Specs
db_size(pid, Keyword.t) ::
{:ok, non_neg_integer} |
{:error, term}
Returns the size of the database to which conn
is connected.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> MarcoPolo.db_size(conn)
{:ok, 1158891}
Specs
delete_record(pid, MarcoPolo.RID.t, non_neg_integer, Keyword.t) ::
{:ok, boolean} |
{:error, term}
Deletes a record from the database to which conn
is connected.
The record to delete is identified by rid
; version version
is deleted. Returns {:ok, deleted?}
where deleted?
is a boolean that tells if the record has been deleted.
Options
This function accepts the following options:
:no_response
- iftrue
, send the request to the OrientDB server without waiting for a response. This performs a fire and forget operation, returning:ok
every time.:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Examples
iex> rid = %MarcoPolo.RID{cluster_id: 76, position: 12}
iex> MarcoPolo.delete_record(conn, rid, 1)
{:ok, true}
Specs
drop_db(pid, String.t, storage_type, Keyword.t) ::
:ok |
{:error, term}
Drop a database on the server.
This function drops the database identified by the name name
and the storage type type
(either :plocal
or :memory
).
This operation can only be performed on connections to the server. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> MarcoPolo.drop_db(conn, "UselessDatabase", :memory)
:ok
Subscribes to a Live Query for the given query
.
This function subscribes to a Live Query for the given query
. Every time a change happens in the given query, a message will be sent to receiver
.
If the subscription is successful, this function returns {:ok, token}
where token
is a unique identifier for the subscription to the give live query. It's important to keep it around as it's needed to unsubscribe from the live query (see live_query_unsubscribe/2
).
The messages sent to receiver
each time there's a change in the live query has the following structure:
{:orientdb_live_query, token, {operation, record}}
where:
token
is the token mentioned aboveoperation
is one of:create
,:update
, or:delete
, based on the operation happened on the serverrecord
is the subject of the operation happened on the server
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
{:ok, token} = MarcoPolo.live_query(conn, "LIVE SELECT FROM Language", self())
Now, another client performs this query:
INSERT INTO Language(name, creators) VALUES ('Elixir', 'José Valim')
Back to the process that started the live query:
receive do
{:orientdb_live_query, ^token, {operation, record}} ->
operation #=> :create
record.fields["name"] #=> "Elixir"
end
Specs
live_query_unsubscribe(pid, integer) :: :ok
Unsubscribes from the live query identified by token
.
This function unsubscribes from the live query identified by token
(see live_query/4
). Once an unsubscription from a live query happens, no more messages will be sent to the receiver specified when the live query had been started.
This operation happens asynchronously, hence it always returns :ok
.
Examples
iex> MarcoPolo.live_query_unsubscribe(conn, token)
:ok
Specs
load_record(pid, MarcoPolo.RID.t, Keyword.t) ::
{:ok, {rec, linked_records}} |
{:error, term}
Loads a record from the database to which conn
is connected.
The record to load is identified by rid
.
Options
This function accepts the following options:
:fetch_plan
- the fetching strategy used to fetch the record from the database.:ignore_cache
- iftrue
, the cache is ignored, iffalse
it's not. Defaults totrue
.:load_tombstones
- iftrue
, information about deleted records is loaded, iffalse
it's not. Defaults tofalse
.:if_version_not_latest
- iftrue
, only load the given record if the version specified in the:version
option is not the latest. If this option is present, the:version
option is required. This functionality is supported in OrientDB >= 2.1.:version
- see the:if_version_not_latest
option.:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Return value
This function returns {:ok, resp}
in case of a successful request or {:error, reason}
otherwise. In case of success, resp
will be a two-element tuple with the loaded record as the first elemen, and with a set of records linked to it as the second element. This set of linked records can be controlled via the :fetch_plan
options. You're not supposed to manipulate this value directly (so that the implementation can stay flexible); use the functions in the MarcoPolo.FetchPlan
module to work with linked records.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Examples
iex> rid = %MarcoPolo.RID{cluster_id: 10, position: 184}
iex> {:ok, {record, linked_records}} = MarcoPolo.load_record(conn, rid)
iex> record.fields
%{"foo" => "bar"}
Executes a script in the given language
on the database conn
is connected to.
The text of the script is passed as text
. opts
is a list of options.
Note: for this to work, scripting must be enabled in the server configuration. You can read more about scripting in the OrientDB docs.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Options
This function accepts the following options:
:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> script = "for (i = 0; i < 3; i++) db.command('INSERT INTO Foo(idx) VALUES (' + i + ')');"
iex> {:ok, last_record} = MarcoPolo.script(conn, "Javascript", script)
iex> last_record.fields["idx"]
2
Specs
start_link(Keyword.t) :: GenServer.on_start
Starts the connection with an OrientDB server.
This function accepts the following options:
:user
- (string) the OrientDB user. This option is required.:password
- (string) the OrientDB password. This option is required.:connection
- specifies the connection type. This option is required. To learn more about the connection type, refer to the docs for theMarcoPolo
module (there's a "Connection type" section). It can be::server
- connects to the server to perform server operations{:db, db_name, db_type}
- connects to a database to perform database operations.db_type
can be either:document
or:graph
.
:host
- (string or charlist) the host where the OrientDB server is running. Defaults to"localhost"
.:port
- (integer) the port where the OrientDB server is running. Defaults to2424
.
It also accepts all options that GenServer.start_link/3
accepts (e.g., :name
for registering the new process or :timeout
for providing a connection timeout).
Examples
Connecting to the server:
iex> {:ok, conn} = MarcoPolo.start_link user: "admin", password: "admin", connection: :server
iex> is_pid(conn)
true
Connecting to a database:
iex> connection = {:db, "MyDatabase", :document}
iex> {:ok, conn} = MarcoPolo.start_link user: "admin", password: "admin", connection: connection
iex> is_pid(conn)
true
Specs
stop(pid) :: :ok
Closes the connection (asynchronously), doing the required cleanup work.
It always returns :ok
as soon as it's called (regardless of the operation being successful) since it is asynchronous.
Examples
iex> MarcoPolo.stop(conn)
:ok
Specs
transaction(pid, [tx_operation], Keyword.t) ::
{:ok, %{created: [{MarcoPolo.RID.t, non_neg_integer}], updated: [{MarcoPolo.RID.t, non_neg_integer}]}} |
{:error, term}
Runs operations inside a transaction on the database to which conn
is connected.
This function will run a list of operations
inside a server-side transaction. Operations can be creations, updates and deletions of records. Each operation has the form:
{op_type, record}
where op_type
can be one of :create
, :update
or :delete
.
Options
This function accepts the following options:
:using_tx_log
- tells the server whether to use the transaction log to recover the transaction or not. Defaults totrue
. Note: disabling the log could speed up the execution of the transaction, but it makes impossible to rollback the transaction in case of errors. This could lead to inconsistencies in indexes as well, since in case of duplicated keys the rollback is not called to restore the index status.:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
Examples
iex> ops = [{:create, %MarcoPolo.Document{class: "Foo", fields: %{"foo" => "bar"}}},
...> {:delete, %MarcoPolo.Document{rid: %MarcoPolo.RID{cluster_id: 1, position: 2}}]
iex> {:ok, %{created: [created], updated: []} = MarcoPolo.transaction(conn, ops)
iex> created
%MarcoPolo.Document{class: "Foo", fields: %{"foo" => "bar"}, rid: %MarcoPolo.RID{...}}
Specs
update_record(pid, MarcoPolo.RID.t, non_neg_integer, MarcoPolo.Document.t, boolean, Keyword.t) ::
{:ok, non_neg_integer} |
{:error, term}
Updates the given record in the databse to which conn
is connected.
The record to update is identified by its rid
; version
is the version to update. new_record
is the updated record. update_content?
can be:
true
- the content of the record has been changed and should be updated in the storage.false
- the record was modified but its own content has not changed: related collections (e.g. RidBags) have to be updated, but the record version and its contents should not be updated.
When the update is successful, {:ok, new_version}
is returned; otherwise, {:error, reason}
.
Options
This function accepts the following options:
:no_response
- iftrue
, send the request to the OrientDB server without waiting for a response. This performs a fire and forget operation, returning:ok
every time.:timeout
- operation timeout in milliseconds. If this timeout expires, an exit signal will be sent to the calling process.
This operation can only be performed on connections to a database. To learn more about the connection type, look at the "Connection type" section in the docs for the MarcoPolo
module.
Examples
iex> rid = %MarcoPolo.RID{cluster_id: 1, position: 10}
iex> new_record = %MarcoPolo.Document{class: "MyClass", fields: %{foo: "new value"}}
iex> MarcoPolo.update_record(conn, rid, 1, new_record, true)
{:ok, 2}