Convenience helpers for creating the Neo4j VECTOR indexes that back
AshNeo4j.Types.Vector attributes.
Requires Cypher 25 (Neo4j ≥ 2025.06). Operations against an older server
raise AshNeo4j.Error.RequiresCypher25.
# Create the index for a vector attribute
AshNeo4j.Vector.create_index(Item, :embedding)
# Rebuild after a dimension or similarity-function change
AshNeo4j.Vector.create_index(Item, :embedding, recreate: true)
# Euclidean distance instead of the default cosine
AshNeo4j.Vector.create_index(Item, :embedding, similarity_function: :euclidean)Consistent with AshNeo4j's "no automatic migrations" stance — this is an
ergonomic tool you call (e.g. from a start-up task). create_index/3 uses
IF NOT EXISTS, so it is safe to run repeatedly.
Naming
The index is named <base>_vector where base defaults to
<label_lower>_<property> — e.g. item_embedding_vector. Pass :name to
override the base.
Dry run
index_statements/3 returns the CREATE Cypher without touching the
database — useful for review or testing.
Summary
Functions
Creates the VECTOR index for attr on resource.
Drops the VECTOR index for attr. Uses IF EXISTS, so it is a no-op when absent.
Returns {:ok, statement} — the CREATE VECTOR INDEX Cypher that
create_index/3 would run — without touching the database.
Functions
@spec create_index(Ash.Resource.t(), atom(), keyword()) :: {:ok, Bolty.Response.t()} | {:error, term()}
Creates the VECTOR index for attr on resource.
Returns {:ok, %Bolty.Response{}} or {:error, reason}.
Options
:recreate—DROP INDEX ... IF EXISTSbeforeCREATE. Use after changing:dimensionsor:similarity_function. Defaults tofalse.:name— override the auto-derived base name._vectoris still appended.:similarity_function—:cosine(default) or:euclidean.
@spec drop_index(Ash.Resource.t(), atom(), keyword()) :: {:ok, Bolty.Response.t()} | {:error, term()}
Drops the VECTOR index for attr. Uses IF EXISTS, so it is a no-op when absent.
@spec index_statements(Ash.Resource.t(), atom(), keyword()) :: {:ok, String.t()} | {:error, term()}
Returns {:ok, statement} — the CREATE VECTOR INDEX Cypher that
create_index/3 would run — without touching the database.
AshNeo4j.Vector.index_statements(Item, :embedding)
#=> {:ok, "CREATE VECTOR INDEX item_embedding_vector IF NOT EXISTS FOR (n:Item) ON (n.embedding) OPTIONS {indexConfig: {`vector.dimensions`: 1536, `vector.similarity_function`: 'cosine'}}"}