# `AshNeo4j.QueryHelper`
[🔗](https://github.com/diffo-dev/ash_neo4j/blob/v0.10.1/lib/query_helper.ex#L5)

AshNeo4j DataLayer QueryHelper

# `guard_conditions`

```elixir
@spec guard_conditions(AshNeo4j.ResourceMapping.t(), Ash.Filter.t() | nil) ::
  {:ok, list()} | {:error, struct()}
```

Renders an update's `changeset.filter` guard (the "only-update-if" predicate,
#361) to `{:ok, conditions}` for the update `WHERE`, or
`{:error, %AshNeo4j.Error.UnsupportedUpdateFilter{}}` when it can't be rendered
**in full**.

Stance: never under-guard. The guard is only pushed down when the filter is a
conjunction (`and`-only — no `or`/`not`) of supported attribute predicates that
each render; a calculation ref or any predicate the pushdown drops makes the
whole guard unsupported, so the data layer returns rather than applies the
update unguarded. `nil` (no guard) is `{:ok, []}`.

# `query_nodes`

```elixir
@spec query_nodes(struct()) :: {:error, any()} | {:ok, any()}
```

Queries nodes, using Ash.Query

# `render_atomic_sets`

```elixir
@spec render_atomic_sets(module(), AshNeo4j.ResourceMapping.t(), keyword()) ::
  {:ok, {[binary()], map()}} | {:error, struct()}
```

Renders `changeset.atomics` (a keyword of `{field, Ash.Expr}`, #361) into
`{:ok, {set_expressions, params}}` for the update `SET`, where each entry is
`"n.<prop> = <cypher>"` evaluated against the **live** node — or
`{:error, %AshNeo4j.Error.UnsupportedAtomic{}}` when an expression can't be
rendered.

Renders: arithmetic (`+ - * /`), comparisons, `if/3` (⇒ `CASE`), string concat
(`<>` ⇒ `+`) and `string_trim` (⇒ `trim`, Ash's string cast), attribute refs
(`n.<prop>`) and scalar literals — numbers/strings/booleans/nil, and atoms (e.g.
`Ash.Type.Atom` enum values) bound as their stored string form. An expression
node it doesn't cover (e.g. another Ash function) is refused rather than
mis-written (stance a). Param keys are `am_`-prefixed and threaded across all
atomics so they stay unique.

# `resolve_chain`

```elixir
@spec resolve_chain(module(), list()) ::
  {:ok, {[{atom(), atom(), atom() | nil}], module() | nil}}
  | {:error, {:unresolved_hop, term()}}
```

Resolves a hop chain to `{:ok, {[{edge_label, direction, dest_label}], reached_resource}}`,
threading the current resource so relationship-name hops resolve at each step.
`reached_resource` is `nil` once an explicit-edge hop breaks the resource chain.

Returns `{:error, {:unresolved_hop, hop}}` when a relationship-name hop names no
declared `relate` edge (so it can't be a Cypher edge label) — instead of
silently using the name as the label (#342). Public so read-time consumers
(e.g. the projection calculation) can turn a `chain` opt into Cypher path
segments for `Cypher.Query.related_nodes/4`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
