Modules
Top-level helpers for the AshNeo4j data layer.
AshNeo4j BoltyHelper
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.
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 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
CALL { … } block joining pre-rendered branch cyphers with UNION or
UNION ALL. Used for native combination-query pushdown (:union,
:union_all).
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.
CREATE clause. pattern is a Cypher pattern string, e.g. "(n:Actor {name: $n_name})".
DELETE clause. items is a list of variables to delete, e.g. ["r"].
DETACH DELETE clause.
LIMIT clause.
MATCH clause. pattern is a Cypher pattern string, e.g. "(s:Actor)".
MERGE clause. pattern is a Cypher pattern string.
ON CREATE SET clause (MERGE). expression is the full SET expression, e.g. "n += {born: $nc_born}".
ON MATCH SET clause (MERGE). expression is the full SET expression, e.g. "n += {touched: $nm_touched}".
OPTIONAL MATCH clause.
ORDER BY clause. Each term is a {property_expression, :asc | :desc} pair.
Typed representation of a Cypher query, and builders for constructing common patterns.
REMOVE clause. items is a list of property references, e.g. ["n.born"].
RETURN clause.
SET clause. expression is the full SET expression, e.g. "n += {born: $n_born}".
SKIP clause.
WHERE clause. Each entry in conditions is ANDed together.
WITH clause.
Ash DataLayer for Neo4j.
Casting for AshNeo4j.DataLayer
Domain-level DSL extension for AshNeo4j.
Introspection helpers for AshNeo4j.DataLayer.Domain
Dumping for AshNeo4j.DataLayer
Introspection helpers for AshNeo4j.DataLayer
Type Classifier for AshNeo4j.DataLayer
Describes a single graph edge from a resource's perspective.
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}.
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.
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).
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.
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.
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.
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.
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.
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).
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.
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.
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.
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
Spatial containment — true if the first geometry contains the second.
Geodesic distance between two geometries, in meters. Mirrors ash_geo /
PostGIS ST_Distance. Post #274 every geometry arrives as a
%Geo.*{} struct.
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.
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).
st_intersects(a, b) — true if two geometries share any space. Mirrors
ash_geo / PostGIS ST_Intersects. Exact, via
topo on the %Geo.*{} geometries
(#267) — handles any combination of Point / LineString / Polygon /
Multi* directly, including segment-edge crossings.
st_within(a, b) — true if a is contained by b. Argument-flipped
st_contains. Mirrors ash_geo / PostGIS ST_Within.
A multi-hop graph traversal as an Ash.Expr value, pushed down to a Cypher
path pattern (#321).
Cosine distance between a stored vector attribute and a query embedding —
the ash_ai-compatible counterpart to AshNeo4j.Functions.VectorSimilarity.
Shared in-memory cosine maths for the vector query functions.
Normalised cosine similarity between a stored vector attribute and a query
embedding, matching Neo4j's vector.similarity.cosine/2.
Geodesic geometry primitives for the in-memory side of AshNeo4j's spatial predicates.
RFC 7946 GeoJSON encoder/decoder over the :geo library.
Render a graph query result as a Mermaid flowchart string.
AshNeo4j DataLayer Neo4j Helper
AshNeo4j DataLayer QueryHelper
Resource information for AshNeo4j.DataLayer
A compile-time description of how an Ash resource maps to the Neo4j graph.
Test sandbox for AshNeo4j, analogous to Ecto.Adapters.SQL.Sandbox.
Convenience helpers for creating the Neo4j POINT indexes that back AshNeo4j's spatial pushdown (#275).
Ash attribute type for a typed tensor of rank 1 to 3 (#309), backed by
Nx.Tensor.
Ash attribute type for vector embeddings, stored as a Neo4j LIST<FLOAT>.
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 Util
Convenience helpers for creating the Neo4j VECTOR indexes that back
AshNeo4j.Type.Vector attributes.
Verifies that attribute types are supported by AshNeo4j.DataLayer
Verifies that relate is unique so relationships are enrichable
Verifies that each guard is a node relationship meeting Neo4j conventions
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.
Verifies that Neo4j labels are PascalCase
Verifies that Neo4j properties are camelCase
Verifies that each relate relates to a relationship, and that the edge labels meets Neo4j conventions
Mix Tasks
Installs AshNeo4j