# `Milvex.Collection`

Declarative DSL for defining Milvus collection schemas.

This module provides a Spark-based DSL for declaring collection schemas
in a declarative, compile-time validated way.

## Basic Example

    defmodule MyApp.Movies do
      use Milvex.Collection

      collection do
        name "movies"
        description "Movie embeddings collection"

        fields do
          primary_key :id, :int64, auto_id: true
          varchar :title, 512
          scalar :year, :int32
          vector :embedding, 128
        end
      end
    end

## Field Types

### Primary Key

Every collection must have exactly one primary key field:

    primary_key :id, :int64                    # Integer primary key
    primary_key :id, :int64, auto_id: true     # Auto-generated IDs
    primary_key :pk, :varchar, max_length: 64  # String primary key

### Vector Fields

Vector fields store embeddings:

    vector :embedding, 128                              # Float vector (default)
    vector :embedding, 768, type: :float16_vector       # Half-precision
    vector :binary_emb, 256, type: :binary_vector       # Binary vector
    sparse_vector :sparse_embedding                      # Sparse vector (no dimension)

### Varchar Fields

Variable-length string fields:

    varchar :title, 256                         # Basic varchar
    varchar :description, 1024, nullable: true  # Nullable
    varchar :category, 64, default: "general"   # With default

### Scalar Fields

Numeric, boolean, and JSON fields:

    scalar :count, :int32
    scalar :score, :float, nullable: true
    scalar :is_active, :bool
    scalar :metadata, :json

### Array Fields

Arrays of scalar types:

    array :tags, :varchar, max_capacity: 100, max_length: 64
    array :scores, :float, max_capacity: 10

## Converting to Schema

The DSL modules can be converted to the existing `Milvex.Schema` format
for use with the Milvex client:

    schema = Milvex.Collection.to_schema(MyApp.Movies)

## Introspection

You can inspect a collection's configuration at runtime:

    Milvex.Collection.collection_name(MyApp.Movies)
    Milvex.Collection.fields(MyApp.Movies)
    Milvex.Collection.primary_key(MyApp.Movies)

### Options

* `:extensions` (list of module that adopts `Spark.Dsl.Extension`) - A list of DSL extensions to add to the `Spark.Dsl`

* `:otp_app` (`t:atom/0`) - The otp_app to use for any application configurable options

* `:fragments` (list of `t:module/0`) - Fragments to include in the `Spark.Dsl`. See the fragments guide for more.

# `collection_name`

```elixir
@spec collection_name(module()) :: String.t()
```

Returns the collection name for the given module.

If a prefix is configured, it will be prepended to the base name.
Function prefixes are evaluated at call time.

# `description`

```elixir
@spec description(module()) :: String.t() | nil
```

Returns the collection description for the given module.

# `enable_dynamic_field?`

```elixir
@spec enable_dynamic_field?(module()) :: boolean()
```

Returns whether dynamic fields are enabled for the collection.

# `fields`

```elixir
@spec fields(module()) :: [Milvex.Collection.Dsl.Field.t()]
```

Returns all field definitions for the given module.

# `functions`

```elixir
@spec functions(module()) :: [Milvex.Collection.Dsl.BM25Function.t()]
```

Returns all function definitions for the given module.

# `prefix`

```elixir
@spec prefix(module()) :: String.t() | (-&gt; String.t()) | nil
```

Returns the raw prefix configuration for the given module.

Returns the prefix as configured: a string, a 0-arity function, or nil if not set.
Use `collection_name/1` to get the resolved collection name with prefix applied.

# `primary_key`

```elixir
@spec primary_key(module()) :: Milvex.Collection.Dsl.Field.t() | nil
```

Returns the primary key field for the given module.

# `scalar_fields`

```elixir
@spec scalar_fields(module()) :: [Milvex.Collection.Dsl.Field.t()]
```

Returns all scalar fields (non-vector, non-array, non-varchar) for the given module.

Note: Varchar fields are treated separately in Milvex. Use `fields/1` and filter
by type if you need to include them.

# `to_proto`

```elixir
@spec to_proto(module()) :: Milvex.Milvus.Proto.Schema.CollectionSchema.t()
```

Converts the collection DSL definition directly to a protobuf CollectionSchema.

This delegates to `to_schema/1` and then uses `Milvex.Schema.to_proto/1` to ensure
proper handling of struct_array_fields and other special field types.

## Example

    proto = Milvex.Collection.to_proto(MyApp.Movies)

# `to_schema`

```elixir
@spec to_schema(module()) :: Milvex.Schema.t()
```

Converts the collection DSL definition to a `Milvex.Schema` struct.

This allows using DSL-defined collections with the existing Milvex API.

## Example

    schema = Milvex.Collection.to_schema(MyApp.Movies)
    Milvex.create_collection(conn, schema)

# `vector_fields`

```elixir
@spec vector_fields(module()) :: [Milvex.Collection.Dsl.Field.t()]
```

Returns all vector fields for the given module.

---

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