ArangoXEcto (ArangoX Ecto v0.6.4) View Source

Methods for interacting with ArangoDB that aren't through Ecto.

This allows for easy interaction with graph functions of Arango. Using Ecto's relations for edge relations was tried but it was found to be too much of a 'hacky' solution. Using separate functions that still utilise Ecto document queries was found to be the optimal solution.

Link to this section Summary

Functions

Runs a raw AQL query on the database.

Creates an edge between two modules

Same as create_edge/4 but specific for custom edge and fields.

Deletes all edges matching matching the query

Generates a edge schema dynamically

Gets an ID from a module and a key

Gets an ID from a schema struct

Converts raw output of a query into a struct

Link to this section Types

Link to this section Functions

Link to this function

aql_query(repo, query, vars \\ [], opts \\ [])

View Source

Specs

aql_query(Ecto.Repo.t(), query(), vars(), [DBConnection.option()]) ::
  {:ok, map()} | {:error, any()}

Runs a raw AQL query on the database.

This will create a transaction and cursor on Arango and run the raw query.

If there is an error in the query such as a syntax error, an Arangox.Error will be raised.

Parameters

  • repo - The Ecto repo module to use for queries
  • query - The AQL query string to execute
  • vars - A keyword list or a map with the values for variables in the query
  • opts - Options to be passed to DBConnection.transaction/3

Examples

iex> ArangoXEcto.aql_query(
      Repo,
      "FOR var in users FILTER var.first_name == @fname AND var.last_name == @lname RETURN var",
      fname: "John",
      lname: "Smith"
    )
{:ok,
[
  %{
    "_id" => "users/12345",
    "_key" => "12345",
    "_rev" => "_bHZ8PAK---",
    "first_name" => "John",
    "last_name" => "Smith"
  }
]}
Link to this function

create_edge(repo, from, to, opts \\ [])

View Source

Specs

create_edge(Ecto.Repo.t(), mod(), mod(), keyword()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}

Creates an edge between two modules

This can create an edge collection dynamically if no additional fields are required, otherwise an edge schema needs to be specified.

The collection name can be passed as an option or is obtained from the provided schema, otherwise it is generated dynamically.

Parameters

  • repo - The Ecto repo module to use for queries
  • from - The Ecto Schema struct to use for the from vertex
  • to - The Ecto Schema struct to use for the to vertex
  • opts - Options to use

Options

Accepts the following options:

  • :edge - A specific edge module to use for the edge. This is required for any additional fields on the edge. Overrides collection_name.
  • :fields - The values of the fields to set on the edge. Requires edge to be set otherwise it is ignored.
  • :collection_name - The name of the collection to use.

Examples

iex> ArangoXEcto.create_edge(Repo, user1, user2)
%ArangoXEcto.Edge{_from: "users/12345", _to: "users/54321"}

Create an edge with a specific edge collection name

iex> ArangoXEcto.create_edge(Repo, user1, user2, collection_name: "friends")
%ArangoXEcto.Edge{_from: "users/12345", _to: "users/54321"}

Create a edge schema and use it to create an edge relation

defmodule UserPosts do
  use ArangoXEcto.Edge
  import Ecto.Changeset

  schema "user_posts" do
    edge_fields()

    field(:type, :string)
  end

  def changeset(edge, attrs) do
    edges_changeset(edge, attrs)
    |> cast(attrs, [:type])
    |> validate_required([:type])
  end
end

iex> ArangoXEcto.create_edge(Repo, user1, user2, edge: UserPosts, fields: %{type: "wrote"})
%ArangoXEcto.Edge{_from: "users/12345", _to: "users/54321"}
Link to this function

create_edge(repo, from, to, edge, fields, opts \\ [])

View Source

Specs

create_edge(Ecto.Repo.t(), mod(), mod(), mod(), map(), keyword()) ::
  {:ok, Ecto.Schema.t()} | {:error, Ecto.Changeset.t()}

Same as create_edge/4 but specific for custom edge and fields.

Link to this function

delete_all_edges(repo, from, to, opts \\ [])

View Source

Specs

delete_all_edges(Ecto.Repo.t(), mod(), mod(), keyword()) :: :ok

Deletes all edges matching matching the query

If the :conditions option is set then those conditions must be true to delete.

To just delete one edge do so like any other Ecto Schema struct, i.e. using Ecto.Repo methods.

Options

Accepts the following options:

  • :edge - A specific edge module to use for the edge. This is required for any additional fields on the edge. Overrides collection_name.
  • :fields - The values of the fields to set on the edge. Requires edge to be set otherwise it is ignored.
  • :collection_name - The name of the collection to use.
  • :conditions - A keyword list of conditions to filter for edge deletion

Parameters

  • repo - The Ecto repo module to use for queries
  • from - The Ecto Schema struct to use for the from vertex
  • to - The Ecto Schema struct to use for the to vertex
  • opts - Options to use

Examples

iex> ArangoXEcto.create_edge(Repo, user1, user2)
%ArangoXEcto.Edge{_from: "users/12345", _to: "users/54321"}

Create an edge with a specific edge collection name

iex> ArangoXEcto.create_edge(Repo, user1, user2, collection_name: "friends")
%ArangoXEcto.Edge{_from: "users/12345", _to: "users/54321"}

Create a edge schema and use it to create an edge relation

defmodule UserPosts do
  use ArangoXEcto.Edge
  import Ecto.Changeset

  schema "user_posts" do
    edge_fields()

    field(:type, :string)
  end

  def changeset(edge, attrs) do
    edges_changeset(edge, attrs)
    |> cast(attrs, [:type])
    |> validate_required([:type])
  end
end

iex> ArangoXEcto.create_edge(Repo, user1, user2, edge: UserPosts, fields: %{type: "wrote"})
%ArangoXEcto.Edge{_from: "users/12345", _to: "users/54321"}
Link to this function

edge_module(from_module, to_module, opts \\ [])

View Source

Specs

edge_module(mod(), mod(), keyword()) :: atom()

Generates a edge schema dynamically

If no collection name is passed in the options, then one is generated using the passed modules.

This will create the Ecto Module in the environment dynamically. It will create it under the closest common parent module of the passed modules plus the Edges alias. For example, if the modules were MyApp.Apple.User and MyApp.Apple.Banana.Post then the edge would be created at MyApp.Apple.Edges.UsersPosts. This assumes that the edge collection name was generated and not passed in, if it was UsersPosts would be replaced with the camelcase of that collection name.

Returns the Edge Module name as an atom.

Parameters

  • from_module - Ecto Schema Module for the from part of the edge
  • to_module - Ecto Schema Module for the to part of the edge
  • opts - Options passed for module generation

Options

  • :collection_name - The name of collection to use instead of generating it

Examples

iex> ArangoXEcto.edge_module(MyProject.User, MyProject.Company, [collection_name: "works_for"])
MyProject.WorksFor

iex> ArangoXEcto.edge_module(MyProject.User, MyProject.Company)
MyProject.UsersCompanies
Link to this function

get_id_from_module(module, key)

View Source

Specs

get_id_from_module(Ecto.Schema.t(), binary()) :: binary()

Gets an ID from a module and a key

Parameters

  • module - Module to get the collection name from
  • key - The _key to use in the id

Example

iex> ArangoXEcto.get_id_from_module(User, "123456")
"users/123456"
Link to this function

get_id_from_struct(struct)

View Source

Specs

get_id_from_struct(mod()) :: binary()

Gets an ID from a schema struct

Parameters

  • struct - The Ecto struct

Example

If the User schema's collection name is users the following would be:

iex> user = %User{id: "123456"}
%User{id: "123456"}

iex> ArangoXEcto.get_id_from_struct(user)
"users/123456"
Link to this function

raw_to_struct(map, module)

View Source

Specs

raw_to_struct(map() | [map()], Ecto.Schema.t()) :: struct()

Converts raw output of a query into a struct

Transforms string map arguments into atom key map, adds id key and drops _id, _key and _rev keys. Then it creates a struct from filtered arguments using module.

If a list of maps are passed then the maps are enumerated over.

Parameters

  • maps - List of maps or singular map to convert to a struct
  • module - Module to use for the struct

Example

iex> {:ok, users} = ArangoXEcto.aql_query(
      Repo,
      "FOR user IN users RETURN user"
    )
{:ok,
[
  %{
    "_id" => "users/12345",
    "_key" => "12345",
    "_rev" => "_bHZ8PAK---",
    "first_name" => "John",
    "last_name" => "Smith"
  }
]}

iex> ArangoXEcto.raw_to_struct(users, User)
[
  %User{
    id: "12345",
    first_name: "John",
    last_name: "Smith"
  }
]