Seraph.Schema.Relationship (Seraph v0.2.4)
Defines a relationship schema.
a Relationship Schema is used to map a Neo4j relationship into an Elixir struct.
relationship/3
is used to map a Neo4j node into an Elixir struct and vice versa.
It allows you to have your application data decoipled from your persisted data and
to manipulate them easily.
Example
# Complete form
defmodule MyApp.Wrote do
use Seraph.Schema.Relationship
@cardinality :one
relationship "WROTE" do
start_node MyApp.User
end_node MyApp.Post
property :views, :integer, default: 0
end
end
# Short form (useful for relationship without properties)
defrelationship("FOLLOWS", MyApp.User, MyApp.User, cardinality: :one)
The start_node
macro defines the node schema from which starts the relationship.
The end_node
macro defines the node schema to which ends the relationship.
The property
macro defines a property in the node schema.
Schemas are regular structs and can be created and manipulated directly using Elixir's struct API:
iex> user = %MyApp.Wrote{views: 1}
iex> %{user | views: 2}
However, most commonly, structs are cast, validated and manipulated with the
Seraph.Changeset
module.
Types
The available types are:
Ecto type | Elixir type | Literal syntax in query |
---|---|---|
:id | integer | 1, 2, 3 |
:binary_id | binary | <<int, int, int, ...>> |
:integer | integer | 1, 2, 3 |
:float | float | 1.0, 2.0, 3.0 |
:boolean | boolean | true, false |
:string | UTF-8 encoded string | "hello" |
:binary | binary | <<int, int, int, ...>> |
{:array, inner_type} | list | [value, value, value, ...] |
:map | map | |
{:map, inner_type} | map | |
:decimal | Decimal | |
:date | Date | |
:time | Time | |
:time_usec | Time | |
:naive_datetime | NaiveDateTime | |
:naive_datetime_usec | NaiveDateTime | |
:utc_datetime | DateTime | |
:utc_datetime_usec | DateTime |
Reflection
Any node schema module will generate the __schema__
function that can be
used for runtime introspection of the schema:
__schema__(:type)
- Returns the type definedrelationship/3
__schema__(:start_node)
- Returns the start_node schema__schema__(:end_node)
- Returns the end_node schema__schema__(:cardinality)
- Returns the cardinality__schema__(:properties)
- Returns the list of properties names
Link to this section Summary
Functions
Allow to define a relationship schema without properties in a quick way.
Defines the end node with its module.
Defines a property on the relationship schema with the given name and type.
Defines a relationship with a type and properties.
An additional field called __meta__
is added to the struct.
Defines the start node with its module.
Link to this section Types
cardinality()
Specs
cardinality() :: [outgoing: :one | :many, incoming: :one | :many]
Specs
t() :: %atom(){ __meta__: Seraph.Schema.Relationship.Metadata.t(), __id__: integer(), type: String.t(), direction: :outgoing | :incoming, start_node: Seraph.Schema.Node.t(), end_node: Seraph.Schema.Node.t(), properties: Ecto.Schema.t(), cardinality: cardinality() }
Link to this section Functions
Allow to define a relationship schema without properties in a quick way.
Will expand in a viable relationship schema without properties.
Module name will be built upon start_node, end_node and relationship type as follows:
[caller_module_name].[start_node]To[end_node].[relationship_type]
.
A free changeset
will be provided with :end_node
and :start_node
as
allowed changes, allowing to easily set them and to have a similar behaviour
as fully-defined relationship
Options:
:cardinality
- Defines the cardinality of the relationship. Can take two values::one
or:many
. Default::many
Example
defmodule MyApp.NoPropsRelationships do
import Seraph.Schema.Relationship
defrelationship("ACTED_IN", MyApp.Person, MyApp.Movie, cardinality: :one)
defrelationship("DIRECTED", MyApp.Person, MyApp.Movie)
end
# Will expand to
defmodule MyApp.NoPropsRelationships do
defmodule PersonToMovie.ActedIn do
use Seraph.Schema.Relationship
@cardinality :one
relationship "ACTED_IN" do
start_node MyApp.Person
end_node MyApp.Movie
end
def changeset(relationship, params \ %{}) do
Seraph.Changeset.cast(relationship, params, [:start_node, :end_node])
end
end
defmodule PersonToMovie.Directed do
use Seraph.Schema.Relationship
@cardinality :many
relationship "DIRECTED" do
start_node MyApp.Person
end_node MyApp.Movie
end
def changeset(relationship, params \ %{}) do
Seraph.Changeset.cast(relationship, params, [:start_node, :end_node])
end
end
end
Defines the end node with its module.
Defines a property on the relationship schema with the given name and type.
Options:
:default
- Sets the default value on the node schema and the struct. The default value is calculated at compilation time, so don't use expressions likeDateTime.utc_now
orEcto.UUID.generate
as they would then be the same for all records.:virtual
- When true, the field is not persisted to the database.
Defines a relationship with a type and properties.
An additional field called __meta__
is added to the struct.
Options:
cardinality
- Defines the cardinality of the relationship. Can take two values::one
or:many
Note:
- type must be uppercased.
- relationship info must match the info given in the start and end node schemas
Defines the start node with its module.