### Install AshNeo4j with Igniter Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/setup.md If your project utilizes Igniter, run this command to automatically install and configure AshNeo4j. ```bash mix igniter.install ash_neo4j ``` -------------------------------- ### Setup for Test Isolation Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/testing.md Starts the Bolty helper once for the test suite and checks out a sandbox connection for each test. The rollback is optional but recommended for clarity. ```elixir setup_all do AshNeo4j.BoltyHelper.start() end setup do AshNeo4j.Sandbox.checkout() on_exit(&AshNeo4j.Sandbox.rollback/0) end ``` -------------------------------- ### Parallel Test Execution Setup Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/testing.md Configures ExUnit to run tests asynchronously, leveraging the sandbox for isolation. Each test checks out a sandbox connection and sets up an optional rollback. ```elixir use ExUnit.Case, async: true setup do AshNeo4j.Sandbox.checkout() on_exit(&AshNeo4j.Sandbox.rollback/0) end ``` -------------------------------- ### Example Combination Query: Customers Served by NBN but not by Peer SIP Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/combination-queries.md Demonstrates a combination query to find customers served by NBN but not by any peer SIP. It uses a base query and an except operation. ```elixir require Ash.Query require Ash.Expr import Ash.Expr # Customers served by NBN but not by any peer SIP Customer |> Ash.Query.combination_of([ Ash.Query.Combination.base(filter: expr(in_csa)), Ash.Query.Combination.except(filter: expr(in_nsa)) ]) |> Ash.read!() ``` -------------------------------- ### Docker Compose for Running Neo4j Instances Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md Starts and manages multiple Neo4j instances (community, Cypher-25, APOC) using Docker Compose. Use this to set up the necessary database environments for the full test suite. ```sh docker compose up -d --wait # bolt5 → 7687, bolt6 → 7689, apoc → 7691 mix test # default suite (7687 only) mix test --include cypher25 --include bolt6 --include apoc # full suite docker compose down # tear down ``` -------------------------------- ### Define Comment Resource with Neo4j Configuration Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md An example of a Comment resource using AshNeo4j.DataLayer, including Neo4j specific configurations for labels and relationships. The neo4j configuration block is often optional if defaults are acceptable. ```elixir defmodule Blog.Comment do use Ash.Resource, data_layer: AshNeo4j.DataLayer neo4j do label :Comment relate [{:post, :BELONGS_TO, :outgoing, :Post}] end actions do default_accept :* defaults [:create, :read, :update, :destroy] end attributes do uuid_primary_key :id attribute :title, :string, public?: true attribute :date_created, :date, source: :dateCreated end relationships do belongs_to :post, Post, public?: true end end ``` -------------------------------- ### Get Spatial Index Statements Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/CHANGELOG.md Returns the exact Cypher statements for creating a spatial index without executing them. Useful for review or dry runs. ```Elixir AshNeo4j.Spatial.index_statements(Place, [:pet, :home]) ``` ```Elixir AshNeo4j.Spatial.index_statements(Place, [:pet, :home], recreate: true, name: "custom_index_name") ``` -------------------------------- ### Spatial Queries with Ash Neo4j Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md Illustrates how to perform spatial queries using Ash Neo4j's integration with ash_geo and Neo4j's spatial functions. Examples include checking containment and proximity. ```elixir require Ash.Query # Service qualification: which Places contain the customer point? Place |> Ash.Query.filter(st_contains(bounds, ^customer_point)) |> Ash.read!() # POIs within 5 km Place |> Ash.Query.filter(st_dwithin(location, ^customer_point, 5_000)) |> Ash.read!() ``` -------------------------------- ### Set Difference Query with AshNeo4j Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md Example of performing a set difference operation (e.g., customers in one group but not another) using AshNeo4j's combination query API. Requires importing Ash.Query and Ash.Expr. ```elixir require Ash.Query require Ash.Expr import Ash.Expr # Set difference at a common resource — e.g. "customers in some CSA but not in any NSA" Customer |> Ash.Query.combination_of([ Ash.Query.Combination.base(filter: expr(in_csa)), Ash.Query.Combination.except(filter: expr(in_nsa)) ]) |> Ash.read!() ``` -------------------------------- ### Finding Nearby POIs with st_dwithin Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Use `st_dwithin` to find entities within a specified distance. This example finds Places within 5,000 meters (5 km) of the customer's point, leveraging Cypher pushdown for Point attributes. ```elixir # "Near me" — POIs within 5 km Place |> Ash.Query.filter(st_dwithin(location, ^customer_point, 5_000)) |> Ash.read!() ``` -------------------------------- ### Graph Traversal with Projection Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md The second argument of `traverse/2` (default `:node`) selects what to pull from the reached set. Examples include spatial queries, membership checks, and field aggregates. ```elixir # compose with spatial — "services whose site is within 5 km of a point", one query Service |> Ash.Query.filter(st_dwithin(traverse(^chain, :location), ^point, 5_000)) ``` ```elixir # membership / cardinality over the reached set (#334) Service |> Ash.Query.filter(traverse(^chain, :exists) == true) # reaches a node Service |> Ash.Query.filter(traverse(^chain, :exists) == false) # reaches none Service |> Ash.Query.filter(traverse(^chain, :count) > 0) ``` ```elixir # field aggregates over the reached set (#338) Party |> Ash.Query.filter(traverse(^chain, {:min, :population}) > 5_200_000) ``` -------------------------------- ### Define a Guard for Resource Destruction Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md Use the `guard` DSL to prevent the destruction of a resource if specific relationships exist. This example guards against deleting a :Post resource if it has outgoing relationships labeled :WRITTEN_BY. ```elixir neo4j do guard [{:WRITTEN_BY, :outgoing, :Post}] end ``` -------------------------------- ### Ash Read Action with Vector Similarity Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/vectors.md Demonstrates a composite `read` action that works across data layers by using `vector_cosine_distance`. This example shows how to generate embeddings for a query, filter, and sort results, ensuring interoperability between Ash Neo4j and other data layers like AshPostgres/pgvector. ```elixir read :search do argument :query, :string, allow_nil?: false prepare before_action(fn query, _ctx -> {:ok, [v]} = MyApp.Embeddings.generate([query.arguments.query], []) query |> Ash.Query.filter(vector_cosine_distance(embedding, ^v) < 0.5) |> Ash.Query.sort({calc(vector_cosine_distance(embedding, ^v), type: :float), :asc}) |> Ash.Query.limit(10) end) end ``` -------------------------------- ### Defining Spatial Attributes with Ash Neo4j Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md Shows how to define attributes for spatial data using AshGeo.GeoJson with specific geo_types and SRID constraints. This setup is necessary for using spatial functions. ```elixir attributes do attribute :location, AshGeo.GeoJson, constraints: [geo_types: [:point], force_srid: 4326] attribute :bounds, AshGeo.GeoJson, constraints: [geo_types: [:polygon], force_srid: 4326] end ``` -------------------------------- ### Distance Comparison with st_distance Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Use `st_distance` for distance comparisons, which can be pushed down to Neo4j's native `point.distance` for Point attributes. This example filters Places where the distance to the customer's point is less than 5,000 meters. ```elixir # Distance comparison (pushed down for Point attributes) Place |> Ash.Query.filter(st_distance(location, ^customer_point) < 5_000) |> Ash.read!() ``` -------------------------------- ### Publish to Hex.pm Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Publish the package to Hex.pm from the `main` branch. This is a manual step and also publishes HexDocs. ```bash mix hex.publish ``` -------------------------------- ### Defining a TypedStruct with Nested GeoJSON Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Example of defining a TypedStruct in Elixir that includes a nested GeoJSON field. This field will be automatically promoted for indexing. ```elixir defmodule MyApp.Characteristic do use Ash.TypedStruct typed_struct do field :name, :string field :location, AshGeo.GeoJson, constraints: [geo_types: [:point], force_srid: 4326] end end attribute :characteristic, MyApp.Characteristic, public?: true ``` -------------------------------- ### Run Geospatial Benchmarks Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/bench/README.md Execute spatial containment benchmarks with different dataset sizes. Use MIX_ENV=test to set the environment and optionally BENCH_N to specify the number of items. ```shell MIX_ENV=test mix run bench/spatial_containment.exs # N = 1000 BENCH_N=10000 MIX_ENV=test mix run bench/spatial_containment.exs ``` -------------------------------- ### Running the full test suite Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Execute the complete test suite for AshNeo4j. This command excludes tests tagged with :show_neo4j, :bolt6, and :cypher25 by default. ```sh mix test ``` -------------------------------- ### Running tests for a specific file Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Execute tests located within a particular file. Replace 'test/blog_test.exs' with the actual path to your test file. ```sh mix test test/blog_test.exs ``` -------------------------------- ### Run Git Ops Release Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Use this command to initiate the release process. It bumps the version, updates the changelog, commits, and creates an annotated tag. ```elixir mix git_ops.release --yes ``` -------------------------------- ### Create GitHub Release Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Create a GitHub release using the pushed tag. The release notes should include a link to the full changelog and the specific version's changelog entry. ```bash gh release create vX.Y.Z --title vX.Y.Z --notes-file ``` -------------------------------- ### Configure AshNeo4j Data Layer Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md Configure a resource to use the AshNeo4j DataLayer by specifying it in the `use Ash.Resource` macro. ```elixir use Ash.Resource, domain: MyApp.Blog, data_layer: AshNeo4j.DataLayer ``` -------------------------------- ### Create Spatial Index Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/CHANGELOG.md Builds and runs the POINT index Cypher for spatial pushdown. Supports nested geometries using a path. Can recreate the index or override its name. ```Elixir AshNeo4j.Spatial.create_index(Place, [:pet, :home]) ``` ```Elixir AshNeo4j.Spatial.create_index(Place, [:pet, :home], recreate: true, name: "custom_index_name") ``` -------------------------------- ### Sync AI Coding Assistant Rules Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md Add 'ash_neo4j' to your :usage_rules config and run this command to merge the rules into your AGENTS.md or CLAUDE.md file. ```bash mix usage_rules.sync ``` -------------------------------- ### Running a specific test by line number Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Execute a single test case identified by its line number within a file. Adjust 'test/blog_test.exs:LINE' to target the desired test. ```sh mix test test/blog_test.exs:LINE ``` -------------------------------- ### Fuzzy Text Match with APOC Levenshtein Distance Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/cypher-fragments.md Use `fragment(...)` to integrate an APOC function for fuzzy text matching within an AshNeo4j filter. This example demonstrates a Levenshtein distance check against a 'title' attribute. ```elixir require Ash.Query # Fuzzy, typo-tolerant text match with an APOC function Post |> Ash.Query.filter(fragment("apoc.text.levenshteinDistance(?, ?) <= ?", title, "John Smith", 2)) |> Ash.read!() ``` -------------------------------- ### Configure Bolty Connection Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/setup.md Add this configuration to your `config/runtime.exs` file. Ensure sensitive credentials are not placed in `config/config.exs`. The `name: Bolt` option is mandatory. ```elixir config :bolty, Bolt, uri: "bolt://localhost:7687", auth: [username: "neo4j", password: "password"], pool_size: 10, name: Bolt ``` -------------------------------- ### Service Qualification with st_contains Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Use `st_contains` to filter entities based on whether they contain a given point. This example finds all Places that contain the customer's point, utilizing indexed bbox prefiltering and exact topo refinement. ```elixir require Ash.Query # Service-qualification: which Places contain the customer? Place |> Ash.Query.filter(st_contains(bounds, ^customer_point)) |> Ash.read!() ``` -------------------------------- ### Analyze Containment Index Behavior Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/bench/README.md Examine the difference between the old and new containment query forms using EXPLAIN. This helps understand the transition from NodeByLabelScan to NodeIndexSeekByRange. ```elixir bench/bbox_index_probe.exs ``` -------------------------------- ### Generating a Node with Domain and Module Labels Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md This snippet demonstrates how to generate a Cypher node pattern using `Cypher.node` with both domain and module labels. This is the recommended way to identify a specific resource type for MATCH operations. ```Elixir Cypher.node(:s, [:Servo, :ShelfInstance]) ``` -------------------------------- ### Verify Tagged Commit SHA Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md After pushing the tag to origin, use this command to verify that the tag points to the correct merge commit SHA on the `main` branch. ```bash git rev-parse "vX.Y.Z^{commit}" ``` -------------------------------- ### Projecting Node Worlds with AshNeo4j Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md Demonstrates how to use AshNeo4j.worlds/1 to project the domain and resource labels of a Neo4j node back to Ash resource modules. This helps in recovering the outer type of a polymorphic node. ```elixir record = Ash.get!(SomeBaseInstance, id) {domain, resource} = hd(AshNeo4j.worlds(record)) # outermost (most-nuanced) world ``` -------------------------------- ### Create Spatial Indexes with Raw Cypher Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Use `AshNeo4j.Cypher.run/2` to send raw Cypher queries for creating spatial indexes. The `IF NOT EXISTS` clause ensures idempotency, making it suitable for application startup tasks. This method is useful when you need direct control over the Cypher statement. ```elixir property = AshNeo4j.Resource.Info.translations(Place) |> Keyword.get(:location) AshNeo4j.Cypher.run( "CREATE POINT INDEX place_location IF NOT EXISTS FOR (p:Place) ON (p.`#{property}.point`)" ) # nested — the :characteristic attribute's `location` field char_property = AshNeo4j.Resource.Info.translations(Place) |> Keyword.get(:characteristic) AshNeo4j.Cypher.run( "CREATE POINT INDEX place_char_location IF NOT EXISTS FOR (p:Place) ON (p.`#{char_property}.location.point`)" ) ``` -------------------------------- ### Project 3D Point to 2D for Query Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Evaluate a spatial query in 2D by projecting a 3D point attribute to its 2D footprint using `AshNeo4j.Geo.force_2d/1`. This is necessary when mixing 3D attributes with 2D geometries or operations. ```elixir Place |> Ash.Query.filter(st_contains(coverage_area, ^AshNeo4j.Geo.force_2d(antenna))) |> Ash.read!() ``` -------------------------------- ### Manual Cypher for Spatial Indexes Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Directly write Cypher statements to create Neo4j spatial indexes. This demonstrates the underlying structure that `AshNeo4j.Spatial.create_index` generates, including specific index types and property referencing. ```cypher CREATE POINT INDEX FOR (p:Place) ON (p.`location.point`); CREATE POINT INDEX FOR (p:Place) ON (p.`bounds.bbSW`); CREATE POINT INDEX FOR (p:Place) ON (p.`bounds.bbNE`); ``` ```cypher CREATE POINT INDEX FOR (p:Place) ON (p.`characteristic.location.point`); ``` -------------------------------- ### Neo4j DSL Configuration Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/dsl.md Configure Neo4j node labels, relationships, guards, and fields to skip. All options are optional. ```elixir neo4j do label :Comment relate [{:post, :BELONGS_TO, :outgoing, :Post}] guard [{:WRITTEN_BY, :outgoing, :Author}] skip [:transient_field] end ``` -------------------------------- ### Generating a Node with Only Instance Label Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md This snippet shows generating a Cypher node pattern using only the instance label. This approach is discouraged for MATCH operations as it can lead to scanning across multiple resource types that share the same fragment. ```Elixir Cypher.node(:s, [:Instance]) ``` -------------------------------- ### Add AshNeo4j Dependency Manually Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md Manually add the AshNeo4j dependency to your project's mix.exs file. Ensure you also follow the Bolty configuration steps. ```elixir def deps do [ {:ash_neo4j, "~> 0.10"}, ] end ``` -------------------------------- ### Generating Index Creation Statements Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Use `AshNeo4j.Spatial.index_statements/3` to retrieve the exact Cypher statements for creating spatial indexes without executing them. This is useful for review, dry runs, or integration into migration files. ```elixir AshNeo4j.Spatial.index_statements(Place, :bounds) #=> {:ok, [ #=> "CREATE POINT INDEX place_bounds_bbSW IF NOT EXISTS FOR (n:Place) ON (n.`bounds.bbSW`)", #=> "CREATE POINT INDEX place_bounds_bbNE IF NOT EXISTS FOR (n:Place) ON (n.`bounds.bbNE`)" #=> ]} ``` -------------------------------- ### Generate Vector Index Statements (Dry Run) Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/vectors.md Generates the Cypher statements for creating a vector index without modifying the database. Useful for inspection. ```elixir # Dry run — the CREATE Cypher without touching the database AshNeo4j.Vector.index_statements(Note, :embedding) #=> {:ok, "CREATE VECTOR INDEX note_embedding_vector IF NOT EXISTS " <> #=> "FOR (n:Note) ON (n.embedding) " <> #=> "OPTIONS {indexConfig: {`vector.dimensions`: 1536, `vector.similarity_function`: 'cosine'}} "} ``` -------------------------------- ### Create Neo4j Uniqueness Constraints Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/identities.md Manually create all uniqueness constraints for identities defined on a resource. Statements are safe to run repeatedly. ```elixir # Create the uniqueness constraint(s) for every identity on a resource AshNeo4j.Constraint.create_constraints(AssignmentRelationship) ``` -------------------------------- ### Atomic Updates and Bulk Operations in Ash Neo4j Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules.md Demonstrates atomic updates for single records, bulk atomic updates for multiple records, bulk atomic destroys, and atomic upserts using Ash Neo4j. These operations translate directly to Cypher for efficiency. ```elixir require Ash.Query import Ash.Expr # atomic update — changeset.atomics render to a Cypher SET (numeric, string # concat/trim, enum/atom forms) post |> Ash.Changeset.for_update(:update) |> Ash.Changeset.atomic_update(:score, expr(score + 1)) |> Ash.update!() # bulk atomic update — one UPDATE query, not N round-trips Post |> Ash.Query.filter(draft == true) |> Ash.bulk_update!(:publish, %{}, strategy: :atomic) # bulk atomic destroy — "delete what matches"; a guarded node is skipped, not deleted Specification |> Ash.bulk_destroy!(:destroy, %{}, strategy: :atomic) # atomic upsert — create-or-update keyed on an identity renders a Cypher MERGE, # so concurrent upserts converge on one node Ash.create!(Upsert, %{first_name: "Donald", surname: "Duck", field: "two"}, upsert?: true, upsert_identity: :full_name) ``` -------------------------------- ### Configure AshNeo4j Data Layer Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md Set AshNeo4j.DataLayer as the data_layer within Ash.Resource options. This is the primary step to integrate Neo4j with your Ash resources. ```elixir use Ash.Resource, data_layer: AshNeo4j.DataLayer ``` -------------------------------- ### Generating a Node with Only Module Label Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md This snippet illustrates generating a Cypher node pattern using only the module label. This is also discouraged for MATCH operations as it scopes to the module but not the domain, potentially leading to unintended matches. ```Elixir Cypher.node(:s, [:ShelfInstance]) ``` -------------------------------- ### Tag Merge Commit on Main Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Manually tag the `dev` to `main` merge commit on the `main` branch with an annotated tag and push it to origin. ```bash git tag -a vX.Y.Z -m "vX.Y.Z" git push origin vX.Y.Z ``` -------------------------------- ### Running Cypher 25 vector tests Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Include and execute tests specifically designed for Cypher 25 compatibility. This requires the Bolt6 pool to be configured and available. ```sh mix test --include cypher25 ``` -------------------------------- ### Cypher Pushdown for Vector Similarity Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/vectors.md Shows how `vector_similarity` and `vector_cosine_distance` translate to Cypher queries. These functions are pushed down to the `WHERE` and `ORDER BY` clauses in Cypher, with the query embedding bound as a `LIST` parameter. ```cypher -- vector_similarity(embedding, $q) vector.similarity.cosine(s.embedding, $q) -- vector_cosine_distance(embedding, $q) (2.0 * (1.0 - vector.similarity.cosine(s.embedding, $q))) ``` -------------------------------- ### Creating Spatial Indexes with AshNeo4j Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md Use `AshNeo4j.Spatial.create_index/2` to automatically generate and apply Cypher statements for creating Neo4j spatial indexes. This function handles attribute translation and companion suffixing for Point and other geometry types, including nested structures. ```elixir # Point attribute → one `.point` index AshNeo4j.Spatial.create_index(Place, :location) ``` ```elixir # Non-Point geometry → both bbSW and bbNE corner indexes in one call AshNeo4j.Spatial.create_index(Place, :bounds) ``` ```elixir # Nested geometry — [attribute, field...] path into a TypedStruct AshNeo4j.Spatial.create_index(Place, [:pet, :home]) ``` ```elixir # Rebuild after a storage-shape change (DROP IF EXISTS + CREATE) AshNeo4j.Spatial.create_index(Place, :location, recreate: true) ``` -------------------------------- ### Create a Record with a Vector Embedding Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/vectors.md Create a new record (e.g., a `Note`) and assign a vector embedding to its `:embedding` attribute. The embedding is represented as a list of floats. ```elixir note = Note |> Ash.create!(%{body: "…", embedding: [0.12, -0.04, 0.98, ...]}) ``` -------------------------------- ### Create HNSW Vector Index Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/vectors.md Use this to create an HNSW vector index for a specified attribute on a resource. Ensure the attribute has a dimensions constraint. ```elixir AshNeo4j.Vector.create_index(Note, :embedding) ``` ```elixir AshNeo4j.Vector.create_index(Note, :embedding, similarity_function: :euclidean) ``` ```elixir AshNeo4j.Vector.create_index(Note, :embedding, recreate: true) ``` -------------------------------- ### Routing Test Queries to a Specific Neo4j Pool Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/README.md Overrides the default Neo4j connection pool for a process using `with_pool/2`. This is useful for testing against different Neo4j versions or configurations. ```elixir AshNeo4j.BoltyHelper.current_pool/0 ``` ```elixir with_pool/2 ``` ```elixir Process.put(:ash_neo4j_pool, Pool) ``` -------------------------------- ### Creating Records with Geo.Point and Geo.Polygon Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/spatial.md When creating records, use `%Geo.Point{}` and `%Geo.Polygon{}` structs for spatial attributes. The `srid` should be set to `4326` for WGS-84 coordinates. `AshGeo.GeoJson` also accepts GeoJSON-shaped maps. ```elixir Place |> Ash.create!(%{ name: "Sydney CBD", location: %Geo.Point{coordinates: {151.2093, -33.8688}, srid: 4326} }) ``` ```elixir Place |> Ash.create!(%{ name: "Sydney bbox", bounds: %Geo.Polygon{ coordinates: [[{151.0, -34.0}, {151.5, -34.0}, {151.5, -33.5}, {151.0, -33.5}, {151.0, -34.0}]], srid: 4326 } }) ``` -------------------------------- ### Configure Bolt6 Pool for Cypher 25 Testing Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/vectors.md This snippet configures the test environment to use the Bolt6 pool, which supports Cypher 25 features. It's essential for running vector-related tests. ```elixir use ExUnit.Case, async: false # the pool is small and the sandbox holds a connection @describetag :cypher25 # excluded from the default run setup do Process.put(:ash_neo4j_pool, Bolt6) # route this process's queries + capability checks AshNeo4j.Sandbox.checkout() on_exit(&AshNeo4j.Sandbox.rollback/0) end ``` -------------------------------- ### Traversal Existence and Count Filters Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/usage-rules/traverse.md Filters services based on the existence or count of reached nodes via a traversal chain. Use 'traverse(^chain, :exists) == true' for existence and 'traverse(^chain, :count) > 0' for cardinality. ```elixir # membership / cardinality (#334) Service |> Ash.Query.filter(traverse(^chain, :exists) == true) Service |> Ash.Query.filter(traverse(^chain, :count) > 0) ``` -------------------------------- ### Running tests with a maximum failure count Source: https://github.com/diffo-dev/ash_neo4j/blob/dev/AGENTS.md Stop the test suite execution early after a specified number of failures. This is useful for quickly identifying critical issues. ```sh mix test --max-failures 5 ```