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

Ash attribute type for a typed tensor of rank 1 to 3 (#309), backed by
`Nx.Tensor`.

The flat row-major encoding with a declared shape covers vectors, matrices
and 3-tensors; rank > 3 is not supported this release.

The Elixir-side value is an `Nx.Tensor` — so the value-blind structural ops
(`Nx.transpose/2` (lazy), `Nx.reshape/2`, `Nx.slice/3`, `Nx.stack/2`,
`Nx.concatenate/2`, `Nx.gather/2`, …) come from Nx rather than being
reimplemented here. `cast_input/2` also accepts a nested list
(`[[1, 2], [3, 4]]`) or a flat list with an explicit `shape:` constraint.

## Storage

Neo4j has no nested-list property, so a tensor stores as a **bare flat value**
(row-major), chosen by `store`:

  * `:property` (default) — a native `LIST<INTEGER|FLOAT>` via `Nx.to_flat_list/1`;
    Cypher-visible.
  * `:packed` — a base64 `STRING` of `Nx.to_binary/1`; an opaque operand.

**Neither type nor shape is stored** — both are declared constraints (schema,
like an embedded-JSON attribute's target struct), recovered on read. So the
on-disk form is just the values, and re-declaring `type`/`shape` needs no data
rewrite.

## Constraints

  * `:type` — Nx element type, one of a closed set of shorthands (`:u8`,
    `:s64`, `:f32`, `:f8`, `:c64`, …). Defaults to `:u8`. Declared, never
    inferred — input is cast to it, read reconstructs from it.
  * `:shape` — **required** tensor shape (e.g. `[9, 9]`), rank 1 to 3. Declared
    schema, used on write and read; never stored or inferred (no honest default
    exists).
  * `:store` — `:property` (default) or `:packed`.

## Usage

    attribute :weights, AshNeo4j.Type.NxTensor,
      constraints: [type: :f32, shape: [3, 3]]

# `dump_storage`

```elixir
@spec dump_storage(Nx.Tensor.t(), :property | :packed) :: list() | binary()
```

Encodes a tensor for storage per the `store` codec — a flat `LIST` (`:property`)
or a base64 `STRING` (`:packed`). Used by the data layer's `dump_properties`.
Neither type nor shape is stored — both are declared constraints recovered on
read, so the on-disk form is just the bare value.

# `handle_change?`

# `prepare_change?`

---

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