# AshNeo4j v0.10.1 - Table of Contents

> Ash DataLayer for Neo4j

## Pages

- [Home](readme.md)
- [License](mit.md)

- How To
  - [AshNeo4j Livebook](ash_neo4j_datalayer.md)
  - [Managing Neo4j Schema](managing_schema.md)

- DSLs
  - [AshNeo4j.DataLayer](dsl-ashneo4j-datalayer.md)

- About AshNeo4j
  - [Change Log](changelog.md)

## Modules

- AshNeo4j
  - [AshNeo4j](AshNeo4j.md): Top-level helpers for the AshNeo4j data layer.
  - [AshNeo4j.DataLayer](AshNeo4j.DataLayer.md): Ash DataLayer for Neo4j.
  - [AshNeo4j.Sandbox](AshNeo4j.Sandbox.md): Test sandbox for AshNeo4j, analogous to `Ecto.Adapters.SQL.Sandbox`.

- Introspection
  - [AshNeo4j.DataLayer.Info](AshNeo4j.DataLayer.Info.md): Introspection helpers for AshNeo4j.DataLayer
  - [AshNeo4j.EdgeDescriptor](AshNeo4j.EdgeDescriptor.md): Describes a single graph edge from a resource's perspective.
  - [AshNeo4j.Resource.Info](AshNeo4j.Resource.Info.md): Resource information for AshNeo4j.DataLayer
  - [AshNeo4j.ResourceMapping](AshNeo4j.ResourceMapping.md): A compile-time description of how an Ash resource maps to the Neo4j graph.

- Cypher
  - [AshNeo4j.Cypher](AshNeo4j.Cypher.md): AshNeo4j Cypher
Functions for converting Elixir data structures to Cypher query components and running Cypher queries against a Neo4j database.
Ideally has no specific knowledge of Ash
  - [AshNeo4j.Cypher.Call](AshNeo4j.Cypher.Call.md): `CALL { … }` block joining pre-rendered branch cyphers with `UNION` or
`UNION ALL`. Used for native combination-query pushdown (`:union`,
`:union_all`).
  - [AshNeo4j.Cypher.CallSubquery](AshNeo4j.Cypher.CallSubquery.md): `CALL { … }` subquery block holding a pre-rendered inner query body, e.g. a
scoped aggregate `CALL { WITH s MATCH (s)<path>(d) RETURN min(d.p) AS agg_v }`.
Distinct from `Call`, which joins branches with `UNION`/`UNION ALL`.

  - [AshNeo4j.Cypher.Create](AshNeo4j.Cypher.Create.md): CREATE clause. `pattern` is a Cypher pattern string, e.g. `"(n:Actor {name: $n_name})"`.
  - [AshNeo4j.Cypher.Delete](AshNeo4j.Cypher.Delete.md): DELETE clause. `items` is a list of variables to delete, e.g. `["r"]`.
  - [AshNeo4j.Cypher.DetachDelete](AshNeo4j.Cypher.DetachDelete.md): DETACH DELETE clause.
  - [AshNeo4j.Cypher.Limit](AshNeo4j.Cypher.Limit.md): LIMIT clause.
  - [AshNeo4j.Cypher.Match](AshNeo4j.Cypher.Match.md): MATCH clause. `pattern` is a Cypher pattern string, e.g. `"(s:Actor)"`.
  - [AshNeo4j.Cypher.Merge](AshNeo4j.Cypher.Merge.md): MERGE clause. `pattern` is a Cypher pattern string.
  - [AshNeo4j.Cypher.OnCreateSet](AshNeo4j.Cypher.OnCreateSet.md): ON CREATE SET clause (MERGE). `expression` is the full SET expression, e.g. `"n += {born: $nc_born}"`.
  - [AshNeo4j.Cypher.OnMatchSet](AshNeo4j.Cypher.OnMatchSet.md): ON MATCH SET clause (MERGE). `expression` is the full SET expression, e.g. `"n += {touched: $nm_touched}"`.
  - [AshNeo4j.Cypher.OptionalMatch](AshNeo4j.Cypher.OptionalMatch.md): OPTIONAL MATCH clause.
  - [AshNeo4j.Cypher.OrderBy](AshNeo4j.Cypher.OrderBy.md): ORDER BY clause. Each term is a `{property_expression, :asc | :desc}` pair.
  - [AshNeo4j.Cypher.Query](AshNeo4j.Cypher.Query.md): Typed representation of a Cypher query, and builders for constructing common patterns.
  - [AshNeo4j.Cypher.Remove](AshNeo4j.Cypher.Remove.md): REMOVE clause. `items` is a list of property references, e.g. `["n.born"]`.
  - [AshNeo4j.Cypher.Return](AshNeo4j.Cypher.Return.md): RETURN clause.
  - [AshNeo4j.Cypher.Set](AshNeo4j.Cypher.Set.md): SET clause. `expression` is the full SET expression, e.g. `"n += {born: $n_born}"`.
  - [AshNeo4j.Cypher.Skip](AshNeo4j.Cypher.Skip.md): SKIP clause.
  - [AshNeo4j.Cypher.Where](AshNeo4j.Cypher.Where.md): WHERE clause. Each entry in `conditions` is ANDed together.
  - [AshNeo4j.Cypher.With](AshNeo4j.Cypher.With.md): WITH clause.

- Utilities
  - [AshNeo4j.BoltyHelper](AshNeo4j.BoltyHelper.md): AshNeo4j BoltyHelper

  - [AshNeo4j.Mermaid](AshNeo4j.Mermaid.md): Render a graph query result as a [Mermaid flowchart](https://mermaid.js.org/syntax/flowchart.html)
string.
  - [AshNeo4j.Neo4jHelper](AshNeo4j.Neo4jHelper.md): AshNeo4j DataLayer Neo4j Helper

  - [AshNeo4j.QueryHelper](AshNeo4j.QueryHelper.md): AshNeo4j DataLayer QueryHelper

  - [AshNeo4j.Util](AshNeo4j.Util.md): AshNeo4j Util

- Internals
  - [AshNeo4j.Calculations.ProjectedTraversal](AshNeo4j.Calculations.ProjectedTraversal.md): Read-time projection of a graph traversal (#329): follows a hop `chain` from
each record to the reached node and returns it as a value — late-binding the
reached node's concrete type at read time via `AshNeo4j.worlds/1`.
  - [AshNeo4j.Constraint](AshNeo4j.Constraint.md): Convenience helpers for creating the Neo4j uniqueness constraints that enforce a
resource's **primary key** (#32) and its `identities` (#20) at the database level.
  - [AshNeo4j.DataLayer.Cast](AshNeo4j.DataLayer.Cast.md): Casting for AshNeo4j.DataLayer
  - [AshNeo4j.DataLayer.Domain](AshNeo4j.DataLayer.Domain.md): Domain-level DSL extension for AshNeo4j.
  - [AshNeo4j.DataLayer.Domain.Info](AshNeo4j.DataLayer.Domain.Info.md): Introspection helpers for AshNeo4j.DataLayer.Domain
  - [AshNeo4j.DataLayer.Dump](AshNeo4j.DataLayer.Dump.md): Dumping for AshNeo4j.DataLayer
  - [AshNeo4j.DataLayer.TypeClassifier](AshNeo4j.DataLayer.TypeClassifier.md): Type Classifier for AshNeo4j.DataLayer
  - [AshNeo4j.Error.GeoDimensionMismatch](AshNeo4j.Error.GeoDimensionMismatch.md): Returned (never raised) when a spatial operation combines geometries of
different coordinate dimensions (2D vs 3D) — e.g. a 3D `%Geo.PointZ{}` against
a 2D attribute, or vice versa. Neo4j silently returns `null` for mixed-CRS
operations (which then drops rows in a `WHERE`), so AshNeo4j refuses up front
(#270) by returning `{:error, error}`.
  - [AshNeo4j.Error.Internal](AshNeo4j.Error.Internal.md): **Returned** (never raised) for an internal invariant the data layer couldn't
satisfy — an input shape it didn't expect, or a relationship/aggregate path it
couldn't resolve (#372). Distinct from the `Unsupported*` / `Requires*` family
(deliberate refusals, `:invalid`) and from `Neo4j` (server errors): this is "we
reached a state we shouldn't have", so its class is `:unknown`.
  - [AshNeo4j.Error.Neo4j](AshNeo4j.Error.Neo4j.md): Wraps a Neo4j server error surfaced from `AshNeo4j.Cypher.run/1` (a
`%Bolty.Error{}`), preserving its Neo4j status code and message and classifying
it by `:category` (#358) — so a failure surfaces as the actual error, not a
generic string. The server-side complement to the returned-error work (#350).
  - [AshNeo4j.Error.RequiresCypher25](AshNeo4j.Error.RequiresCypher25.md): Returned (never raised) when a Cypher 25 operation is attempted against a Neo4j
server older than 2025.06. Upgrade to Neo4j 2025.06 or later to use this feature.

  - [AshNeo4j.Error.RequiresDynamicLabels](AshNeo4j.Error.RequiresDynamicLabels.md): Returned (never raised) when a dynamic label/type operation (`MATCH (n:$(expr))`,
`-[r:$(expr)]->`) is attempted against a Neo4j server older than 5.26. This is
the **server-feature axis** — dynamic labels run under plain `CYPHER 5` and are
unrelated to the `CYPHER 25` selector (`AshNeo4j.Error.RequiresCypher25`).
Upgrade to Neo4j 5.26 or later to use this feature.

  - [AshNeo4j.Error.UnresolvableTraversal](AshNeo4j.Error.UnresolvableTraversal.md): **Returned** (never raised) when a `traverse(^chain, …)` filter predicate can't
be formed because the current graph view can't resolve part of it — a reached
node whose label resolves to no loaded resource, or a field that isn't a
mapped property of the reached resource.
  - [AshNeo4j.Error.Unsupported3DGeometry](AshNeo4j.Error.Unsupported3DGeometry.md): Returned (never raised) when a 3D areal or linear geometry (`%Geo.PolygonZ{}`,
`%Geo.LineStringZ{}`, …) is written. #270 Phase 1 supports 3D **points**
(`%Geo.PointZ{}`) only; 3D areal/linear geometries are deferred to Phase 2,
because exact 3D containment/distance needs a model the 2D `topo` refinement
cannot provide. Storing 2D bbox companions would silently drop the z.

  - [AshNeo4j.Error.UnsupportedAtomic](AshNeo4j.Error.UnsupportedAtomic.md): **Returned** (never raised) when a `changeset.atomics` expression can't be
rendered into the update Cypher `SET` (#361). The renderer covers arithmetic
(`+ - * /`), comparisons, `if/3` (⇒ `CASE`), string concat / `string_trim`
(Ash's string cast), attribute refs and scalar literals; an expression using any
other Ash function is refused rather than mis-written.
  - [AshNeo4j.Error.UnsupportedChangesetFilter](AshNeo4j.Error.UnsupportedChangesetFilter.md): **Returned** (never raised) when a `changeset.filter` guard (the "only-update-if"
predicate) can't be honoured (#361). We refuse rather than apply the write
**unguarded**: silently dropping the guard would write when the predicate says
not to (the write-side analogue of the traverse synthesis leaks, #342).
  - [AshNeo4j.Error.UnsupportedFilterFragment](AshNeo4j.Error.UnsupportedFilterFragment.md): **Returned** (never raised) when a `fragment(...)` filter (the Cypher escape
hatch, #33) can't be pushed down — and, because raw Cypher can't be evaluated in
Elixir, it can't fall back to in-memory filtering either, so the data layer
refuses rather than silently return wrong results.
  - [AshNeo4j.Error.UnsupportedIdentity](AshNeo4j.Error.UnsupportedIdentity.md): **Returned** (never raised) when an `identity` can't be enforced as a Neo4j
uniqueness constraint (#20), so it can't be created by `AshNeo4j.Constraint` —
and is refused rather than skipped, since silently leaving it unenforced would
permit the duplicate/split records the constraint exists to prevent.
  - [AshNeo4j.Error.UnsupportedManyToMany](AshNeo4j.Error.UnsupportedManyToMany.md): **Returned** (never raised) when a relationship write resolves to a many-to-many
modelled as **back-to-back `has_many`** — two resources each declaring a
`has_many` to the other over one edge (#127). Ash anchors a `has_many` by an
attribute on the *related* resource; with a `has_many` on both sides there is no
to-one side to anchor the connect, so the data layer can't determine which node
to relate. The edge itself already represents the many-to-many; the model just
needs a to-one side on each hop to anchor the connect.
  - [AshNeo4j.Functions.StClosestPoint](AshNeo4j.Functions.StClosestPoint.md): `st_closest_point(collection, point)` — returns the closest vertex from
a multi-vertex geometry to a target point. Mirrors ash_geo / PostGIS
`ST_ClosestPoint`. v1 supports
  - [AshNeo4j.Functions.StContains](AshNeo4j.Functions.StContains.md): Spatial containment — true if the first geometry contains the second.
  - [AshNeo4j.Functions.StDistance](AshNeo4j.Functions.StDistance.md): Geodesic distance between two geometries, in meters. Mirrors ash_geo /
PostGIS `ST_Distance`. Post #274 every geometry arrives as a
`%Geo.*{}` struct.
  - [AshNeo4j.Functions.StDistanceInMeters](AshNeo4j.Functions.StDistanceInMeters.md): Alias for `st_distance`. PostGIS distinguishes the two because PostGIS
`ST_Distance` returns degrees for geographic types unless cast; Neo4j's
`point.distance` is always meters for WGS-84, so the distinction is
cosmetic for us. This module exists for API parity with ash_geo so
consumer code reads identically across data layers.
  - [AshNeo4j.Functions.StDwithin](AshNeo4j.Functions.StDwithin.md): True if two geometries are within a given distance of each other.
Mirrors ash_geo / PostGIS `ST_DWithin`. v1 supports point-point only,
with the threshold in meters (geodesic, WGS-84).
  - [AshNeo4j.Functions.StIntersects](AshNeo4j.Functions.StIntersects.md): `st_intersects(a, b)` — true if two geometries share any space. Mirrors
ash_geo / PostGIS `ST_Intersects`. Exact, via
[`topo`](https://hex.pm/packages/topo) on the `%Geo.*{}` geometries
(#267) — handles any combination of Point / LineString / Polygon /
Multi* directly, including segment-edge crossings.
  - [AshNeo4j.Functions.StWithin](AshNeo4j.Functions.StWithin.md): `st_within(a, b)` — true if `a` is contained by `b`. Argument-flipped
`st_contains`. Mirrors ash_geo / PostGIS `ST_Within`.
  - [AshNeo4j.Functions.Traverse](AshNeo4j.Functions.Traverse.md): A multi-hop graph traversal as an `Ash.Expr` value, pushed down to a Cypher
path pattern (#321).
  - [AshNeo4j.Functions.VectorCosineDistance](AshNeo4j.Functions.VectorCosineDistance.md): Cosine *distance* between a stored vector attribute and a query embedding —
the ash_ai-compatible counterpart to `AshNeo4j.Functions.VectorSimilarity`.
  - [AshNeo4j.Functions.VectorMath](AshNeo4j.Functions.VectorMath.md): Shared in-memory cosine maths for the vector query functions.
  - [AshNeo4j.Functions.VectorSimilarity](AshNeo4j.Functions.VectorSimilarity.md): Normalised cosine similarity between a stored vector attribute and a query
embedding, matching Neo4j's `vector.similarity.cosine/2`.
  - [AshNeo4j.Geo](AshNeo4j.Geo.md): Geodesic geometry primitives for the in-memory side of AshNeo4j's
spatial predicates.
  - [AshNeo4j.GeoJson](AshNeo4j.GeoJson.md): RFC 7946 GeoJSON encoder/decoder over the `:geo` library.
  - [AshNeo4j.Spatial](AshNeo4j.Spatial.md): Convenience helpers for creating the Neo4j POINT indexes that back
AshNeo4j's spatial pushdown (#275).
  - [AshNeo4j.Type.NxTensor](AshNeo4j.Type.NxTensor.md): Ash attribute type for a typed tensor of rank 1 to 3 (#309), backed by
`Nx.Tensor`.
  - [AshNeo4j.Type.Vector](AshNeo4j.Type.Vector.md): Ash attribute type for vector embeddings, stored as a Neo4j `LIST<FLOAT>`.
  - [AshNeo4j.Unknown](AshNeo4j.Unknown.md): A sentinel value for *"the data layer tried to determine this and couldn't, in
its current view of the graph"* — complementary to `Ash.NotLoaded`.
  - [AshNeo4j.Vector](AshNeo4j.Vector.md): Convenience helpers for creating the Neo4j VECTOR indexes that back
`AshNeo4j.Type.Vector` attributes.
  - [AshNeo4j.Verifiers.VerifyAttributeType](AshNeo4j.Verifiers.VerifyAttributeType.md): Verifies that attribute types are supported by AshNeo4j.DataLayer
  - [AshNeo4j.Verifiers.VerifyEnrichable](AshNeo4j.Verifiers.VerifyEnrichable.md): Verifies that relate is unique so relationships are enrichable
  - [AshNeo4j.Verifiers.VerifyGuard](AshNeo4j.Verifiers.VerifyGuard.md): Verifies that each guard is a node relationship meeting Neo4j conventions
  - [AshNeo4j.Verifiers.VerifyIdentities](AshNeo4j.Verifiers.VerifyIdentities.md): Refuses, at compile time, any `identity` that can't be enforced as a Neo4j
uniqueness constraint (#20) — so an unenforceable identity is caught loudly here
rather than silently leaving a gap that permits duplicate/split records.
  - [AshNeo4j.Verifiers.VerifyLabelsPascalCase](AshNeo4j.Verifiers.VerifyLabelsPascalCase.md): Verifies that Neo4j labels are PascalCase
  - [AshNeo4j.Verifiers.VerifyPropertiesCamelCase](AshNeo4j.Verifiers.VerifyPropertiesCamelCase.md): Verifies that Neo4j properties are camelCase
  - [AshNeo4j.Verifiers.VerifyRelate](AshNeo4j.Verifiers.VerifyRelate.md): Verifies that each relate relates to a relationship, and that the edge labels meets Neo4j conventions

## Mix Tasks

- Internals
  - [mix ash_neo4j.install](Mix.Tasks.AshNeo4j.Install.md): Installs AshNeo4j

