AshNeo4j.Neo4jHelper (AshNeo4j v0.10.1)

Copy Markdown View Source

AshNeo4j DataLayer Neo4j Helper

Summary

Functions

Bulk destroy (#361): deletes every node of label matching conditions that isn't protected by a preservation guard. Returns {:ok, %Bolty.Response{}} — with captured pre-delete node data when return?.

Creates a neo4j node with labels and properties

Delete all neo4j nodes and relationships

Single filtered + guarded destroy (#361): deletes the id-matched node when it satisfies filter_conditions (optimistic lock) and isn't guard-protected. {:ok, _} when deleted, {:error, :nothing_deleted} otherwise.

Merges a neo4j node with label and properties

The optimistic-lock existence check (#361): does the id-matched node satisfy filter_conditions? Returns {:ok, %Bolty.Response{}}.

Tests if two nodes are related by traversal ## Examples

Reads limited nodes from Neo4j, given label, limit and optionally properties

Reads nodes from Neo4j, given label, and optionally properties

Reads nodes from Neo4j, returning any related nodes

Creates source neo4j node with label, properties and relationships to existing nodes

Relates two nodes with a relationship type, merging relationship ## Examples

Relates two nodes, honouring exclusivity and an optional changeset.filter guard.

Relates two nodes unrelating the destination node from any similar relationships ## Examples

Relates two nodes unrelating the source node from any similar relationships ## Examples

Relates two nodes unrelating the source and destination node from any similar relationships ## Examples

Safely delete neo4j nodes, delete is guarded by relationships

Adds and/or removes labels on an existing node (matched by label + properties).

Atomic upsert (#379): MERGE on merge_props (the identity), ON CREATE SET the rest (create_props), ON MATCH SET the set_on_upsert fields (match_props).

Functions

bulk_detach_delete(label, conditions, guards, return?)

Bulk destroy (#361): deletes every node of label matching conditions that isn't protected by a preservation guard. Returns {:ok, %Bolty.Response{}} — with captured pre-delete node data when return?.

create_node(labels, properties)

Creates a neo4j node with labels and properties

Examples

iex> {result, _} = AshNeo4j.Neo4jHelper.create_node([:Cinema, :Actor], %{name: "Bill Nighy"})
iex> result
:ok

delete_all()

@spec delete_all() ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Delete all neo4j nodes and relationships

Examples

iex> {result, _} = AshNeo4j.Neo4jHelper.delete_all()
iex> result
:ok

delete_node_filtered(label, id_props, filter_conditions, guards)

Single filtered + guarded destroy (#361): deletes the id-matched node when it satisfies filter_conditions (optimistic lock) and isn't guard-protected. {:ok, _} when deleted, {:error, :nothing_deleted} otherwise.

delete_nodes(label, properties \\ %{})

Delete neo4j nodes

Examples

iex> {result, _} = AshNeo4j.Neo4jHelper.delete_nodes(:Actor)
iex> result
:ok
iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy"})
iex> {result, _} = AshNeo4j.Neo4jHelper.delete_nodes(:Actor, %{name: "Bill Nighy"})
iex> result
:ok

merge_node(label, properties)

@spec merge_node(atom(), map()) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Merges a neo4j node with label and properties

Examples

iex> {result, _} = AshNeo4j.Neo4jHelper.merge_node(:Actor, %{name: "Bill Nighy", born: 1949})
iex> result
:ok

node_matching(label, id_props, filter_conditions)

The optimistic-lock existence check (#361): does the id-matched node satisfy filter_conditions? Returns {:ok, %Bolty.Response{}}.

nodes_relate_how?(source_label, source_properties, dest_label, dest_properties, edges)

@spec nodes_relate_how?(atom(), map(), atom(), map(), [tuple()]) ::
  :error | false | true

Tests if two nodes are related by traversal ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Keira Knightley"})
iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Keira Knightley"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Bill Nighy"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
iex> AshNeo4j.Neo4jHelper.nodes_relate_how?(:Actor, %{name: "Bill Nighy"}, :Actor, %{name: "Keira Knightley"}, [ACTED_IN: :outgoing, ACTED_IN: :incoming])
true

nodes_relate_how?(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction)

@spec nodes_relate_how?(atom(), map(), atom(), map(), atom(), atom()) ::
  :error | false | true

Tests if two nodes are directly related ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy", born: 1949})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Bill Nighy"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
iex> AshNeo4j.Neo4jHelper.nodes_relate_how?(:Actor, %{name: "Bill Nighy"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
true

read_limited(label, limit, properties \\ %{})

Reads limited nodes from Neo4j, given label, limit and optionally properties

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy", born: 1949})
iex> {:ok, %{records: records}} = AshNeo4j.Neo4jHelper.read_limited(:Actor, 1)
iex> length(records)
1

read_nodes(label, properties \\ %{})

Reads nodes from Neo4j, given label, and optionally properties

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy", born: 1949})
iex> {:ok, %{records: records}} = AshNeo4j.Neo4jHelper.read_nodes(:Actor, %{name: "Bill Nighy"})
iex> length(records)
1

read_nodes_related(label, properties \\ %{})

Reads nodes from Neo4j, returning any related nodes

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy", born: 1949})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> :ok = AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Bill Nighy"}, [{:Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing, false}])
iex> {:ok, %{records: records}} = AshNeo4j.Neo4jHelper.read_nodes_related(:Actor, %{name: "Bill Nighy"})
iex> length(records)
1

relate_nodes(label, properties, relationships)

@spec relate_nodes(atom() | [atom()], map(), list()) :: {:error, Exception.t()} | :ok

Creates source neo4j node with label, properties and relationships to existing nodes

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{title: "Bill Nighy"})
iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{title: "Keira Knightley"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Bend it Like Beckham"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "The Immitation Game"})

iex> :ok = AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Bill Nighy"}, [{:Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing, false}])
iex> :ok = AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Keira Knightley"}, [{:Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing, false}, {:Movie, %{title: "Bend it Like Beckham"}, :ACTED_IN, :outgoing, false}])

relate_nodes(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction)

@spec relate_nodes(atom() | [atom()], map(), atom() | [atom()], map(), atom(), atom()) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Relates two nodes with a relationship type, merging relationship ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy", born: 1949})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> {result, _} = AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Bill Nighy"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
iex> result
:ok

relate_nodes(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction, opts)

@spec relate_nodes(
  atom() | [atom()],
  map(),
  atom() | [atom()],
  map(),
  atom(),
  atom(),
  keyword()
) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Relates two nodes, honouring exclusivity and an optional changeset.filter guard.

opts:

  • :exclusive{source_exclusive?, destination_exclusive?} (default {false, false}), selecting the plain / unrelate-source / unrelate-destination / unrelate-both render.
  • :guard — a changeset.filter condition list (#368) gating the attach on the live source node; a guard miss yields zero rows ⇒ the caller raises StaleRecord.

relate_nodes_unrelating_destination(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction, guard \\ [])

@spec relate_nodes_unrelating_destination(
  atom(),
  map(),
  atom(),
  map(),
  atom(),
  atom(),
  list()
) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Relates two nodes unrelating the destination node from any similar relationships ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Fan], %{name: "Matt"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Bend it Like Beckham"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Fan, %{name: "Matt"}, :Movie, %{title: "Love Actually"}, :FAVOURITE, :outgoing)
iex> {result, _} = AshNeo4j.Neo4jHelper.relate_nodes_unrelating_destination(:Movie, %{title: "Bend it Like Beckham"}, :Fan, %{name: "Matt"}, :FAVOURITE, :incoming)
iex> result
:ok

relate_nodes_unrelating_source(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction, guard \\ [])

@spec relate_nodes_unrelating_source(
  atom(),
  map(),
  atom(),
  map(),
  atom(),
  atom(),
  list()
) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Relates two nodes unrelating the source node from any similar relationships ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Fan], %{name: "Matt"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Bend it Like Beckham"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Fan, %{name: "Matt"}, :Movie, %{title: "Love Actually"}, :FAVOURITE, :outgoing)
iex> {result, _} = AshNeo4j.Neo4jHelper.relate_nodes_unrelating_source(:Fan, %{name: "Matt"}, :Movie, %{title: "Bend it Like Beckham"}, :FAVOURITE, :outgoing)
iex> result
:ok

relate_nodes_unrelating_source_and_destination(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction, guard \\ [])

@spec relate_nodes_unrelating_source_and_destination(
  atom(),
  map(),
  atom(),
  map(),
  atom(),
  atom(),
  list()
) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Relates two nodes unrelating the source and destination node from any similar relationships ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Person], %{name: "Marlo"})
iex> AshNeo4j.Neo4jHelper.create_node([:Person], %{name: "Harry"})
iex> AshNeo4j.Neo4jHelper.create_node([:Person], %{name: "Marion"})
iex> AshNeo4j.Neo4jHelper.create_node([:Person], %{name: "Robin"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Person, %{name: "Marlo"}, :Person, %{name: "Harry"}, :PARTNER, :outgoing)
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Person, %{name: "Marion"}, :Person, %{name: "Robin"}, :PARTNER, :outgoing)
iex> {result, _} = AshNeo4j.Neo4jHelper.relate_nodes_unrelating_source_and_destination(:Person, %{name: "Marlo"}, :Person, %{name: "Robin"}, :PARTNER, :outgoing)
iex> result
:ok

safe_delete_nodes(label, properties, relationships)

Safely delete neo4j nodes, delete is guarded by relationships

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Keira Knightley"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Bend it Like Beckham"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Keira Knightley"}, [{:Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing, false},
...> {:Movie, %{title: "Bend it Like Beckham"}, :ACTED_IN, :outgoing, false}])
iex> {result, _} = AshNeo4j.Neo4jHelper.safe_delete_nodes(:Actor, %{name: "Keira Knightley"}, [{:ACTED_IN, :outgoing, :Movie}, {:LIVES_AT, :outgoing, :Place}])
iex> result
:error
iex> {result, _} = AshNeo4j.Neo4jHelper.safe_delete_nodes(:Actor, %{name: "Keira Knightley"}, [{:LIVES_AT, :outgoing, :Place}])
iex> result
:ok

unrelate_nodes(source_label, source_properties, dest_label, dest_properties, edge_label, edge_direction, guard \\ [])

@spec unrelate_nodes(
  atom() | [atom()],
  map(),
  atom() | [atom()],
  map(),
  atom(),
  atom(),
  list()
) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Unrelates two nodes with a relationship type ## Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy", born: 1949})
iex> AshNeo4j.Neo4jHelper.create_node([:Movie], %{title: "Love Actually"})
iex> AshNeo4j.Neo4jHelper.relate_nodes(:Actor, %{name: "Bill Nighy"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
iex> {result, _} = AshNeo4j.Neo4jHelper.unrelate_nodes(:Actor, %{name: "Bill Nighy"}, :Movie, %{title: "Love Actually"}, :ACTED_IN, :outgoing)
iex> result
:ok

update_node(label, match_properties, set_properties, remove_properties \\ [], opts \\ [])

Updates neo4j node properties

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:Actor], %{name: "Bill Nighy"})
iex> {result, _} = AshNeo4j.Neo4jHelper.update_node(:Actor, %{name: "Bill Nighy"}, %{born: 1949})
iex> result
:ok

update_node_labels(label, match_properties, add_labels, remove_labels \\ [])

@spec update_node_labels(atom() | [atom()], map(), [atom()], [atom()]) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Adds and/or removes labels on an existing node (matched by label + properties).

A node's label set drives AshNeo4j.worlds/1, so this places a node in — or strips it of — a resolvable world. Useful in tests: create a node via Ash, then mutate its labels to set up a chosen world (or an unresolvable one).

Examples

iex> AshNeo4j.Neo4jHelper.create_node([:SRM, :Place], %{name: "Sydney"})
iex> {result, _} = AshNeo4j.Neo4jHelper.update_node_labels(:Place, %{name: "Sydney"}, [], [:SRM])
iex> result
:ok

upsert_node(label, merge_props, create_props, match_props, create_labels \\ [])

@spec upsert_node(atom() | [atom()], map(), map(), map(), [atom()]) ::
  {:error,
   %{:__exception__ => true, :__struct__ => atom(), optional(atom()) => any()}}
  | {:ok, any()}

Atomic upsert (#379): MERGE on merge_props (the identity), ON CREATE SET the rest (create_props), ON MATCH SET the set_on_upsert fields (match_props).

create_labels (#392) are extra labels added with ON CREATE SET n:Label so an upserted node carries the same full label set a plain create writes.