View Source ArangoXEcto.Schema (ArangoX Ecto v2.0.0)

An ArangoDB specific implementation of the Ecto.Schema module.

The primary key is the Arango _key field and is mapped to :id. The _id field is also provided in the :__id__ field. The :__id__ field is primarily used for graph associations but is available in all structs.

Schema modules should use this module by adding use ArangoXEcto.Schema to the module. The only exception to this is if the collection is an edge collection, in that case refer to ArangoXEcto.Edge.

This module works, for the most part, the same as the Ecto.Schema module. Where the two modules differ is that this module sets the primary key and adds the :__id__ field, as described above. In addition, additional functionality for ArangoDB is available, such as outgoing and incoming relations and collection indexes & options.

Example

defmodule MyProject.Accounts.User do
  use ArangoXEcto.Schema
  import Ecto.Changeset

  schema "users" do
    field :first_name, :string
    field :last_name, :string

    outgoing :posts, Post

    timestamps()
  end

  @doc false
  def changeset(app, attrs) do
    app
    |> cast(attrs, [:first_name, :last_name])
    |> validate_required([:first_name, :last_name])
  end
end

Summary

Functions

Defines an incoming relationship

Defines indexes for collection dynamic creation

Defines collection options for dynamic creation

Defines an outgoing relationship to many objects

Defines an ArangoDB schema.

Functions

incoming(name, source, opts \\ [])

(macro)

Defines an incoming relationship

This is almost exactly the same as outgoing/3 except it defines that the relationship is incoming. This means that on the edge the from and to order is swapped. It will work exactly the same if you used an incoming/3 or an outgoing/3.

One thing to keep in mind is that this function will not automaticallly define an edge module and will require an outbound/3 definition. This doesn't matter when supplying an edge schema as the options.

For more information and available options see outgoing/3.

Example

defmodule MyProject.Post do
  use ArangoXEcto.Schema

  schema "posts" do
    field :title, :string

    # Will use the automatically generated edge
    incoming :users, MyProject.User

    # Will use the UserPosts edge
    incoming :users, MyProject.User, edge: MyProject.UserPosts

    # Creates a multi relation
    incoming :entities, %{
      MyProject.User => [:first_name],
      MyProject.Company => [:name]
    }, edge: MyProject.Entities
  end
end

For the multi relation example, the following could be the edge definition.

defmodule MyProject.Entities do
  use ArangoXEcto.Edge,
    from: [MyProject.User, MyProject.Company],
    to: MyProject.Post

  schema "entities" do
    edge_fields()
  end
end

indexes(indexes)

(macro)

Defines indexes for collection dynamic creation

When using dynamic mode for collection creation this will add indexes after the collection is created. If in static mode, this will simply be ignored.

This accepts a list of keyword lists that are the indexes. The available options can be found in the ArangoXEcto.Migration.Index module.

This function also works in edge collections.

Example

To create a generic hash index you don't need to pass the type.

indexes [
  [fields: [:email, :username]]
]

To create a geoJson index set the type to geo and set geoJson to true.

indexes [
  [fields: [:point], type: :geo, geoJson: true]
]

To create a two separate indexes just supply them separately.

indexes [
  [fields: [:email]],
  [fields: [:username]]
]

options(options)

(macro)

Defines collection options for dynamic creation

When using dynamic mode for collection creation this will add options for when the collection is created. If in static mode, this will simply be ignored.

This accepts a keyword list of options. The available options can be found in the ArangoXEcto.Migration.Collection module.

This function also works in edge collections.

Example

To specify a UUID as the collection key type you just supply it as the key option type.

options [
  keyOptions: %{type: :uuid}
]

outgoing(name, target, opts \\ [])

(macro)

Defines an outgoing relationship to many objects

While not strictly required, you can add an incoming/3 definition in the other target node so that the reverse can be queried also.

If in static mode you still have to have a migration, even for the dynamically generated edges. You can use the rules of how edges are named from ArangoXEcto.edge_module/3 for the name of the edge or if you want to be explicit (and it often is good practice to do so) you can create an edge module and pass the edge.

Parameters

  • name - The name of the relation
  • target - The target of the relation, can either be another schema or a mapper (see below for
          more info)
  • opts - See below

Options

  • :edge - The edge schema to use, default will generate a new edge
  • :on_replace - The action taken on the association when the record is
                replaced when casting or manipulating the parent changeset.
  • :where - A filter for the association. See "Filtering associations" in
          `Ecto.Schema.has_many/3`.

Mapping a target

In ArangoDB you can have multiple different types of collections related through an edge. To represent this we use a map to represent the target. The keys of the map is the schema that we want to use and the value is a list of field names. When Ecto maps a result to a struct it will use the list of fields to determine which schema to use. If any of the fields in the list are present then that schema will be chosen. If two match, then the first will be selected.

outgoing :content, %{
  MyProject.Post => [:title],
  MyProject.Comment => [:text]
}, edge: MyProject.Content

You can specify an incoming/3 relationship in, for example, the MyProject.Post and the MyProject.Comment schemas seperatley. The only requirement would be to ensure the same edge is used.

The edge definition would look something like the following. Take note of the list supplied for the :to option.

defmodule MyProject.Content do
  use ArangoXEcto.Edge,
    from: MyProject.User,
    to: [MyProject.Post, MyProject.Comment]

  schema "content" do
    edge_fields()
  end
end

Example

defmodule MyProject.User do
  use ArangoXEcto.Schema

  schema "users" do
    field :name, :string

    # Will use the automatically generated edge
    outgoing :posts, MyProject.Post

    # Will use the UserPosts edge
    outgoing :posts, MyProject.Post, edge: MyProject.UserPosts

    # Creates a multi relation
    outgoing :content, %{
      MyProject.Post => [:title],
      MyProject.Comment => [:text]
    }, edge: MyProject.Content
  end
end

schema(source, list)

(macro)

Defines an ArangoDB schema.

A wrapper around the Ecto.Schema.schema/2 to add the :__id__ field. For more info, see the docs for Ecto.Schema.schema/2.