# `Milvex.Schema`

Builder for Milvus collection schemas.

Provides a fluent API for constructing collection schema definitions with validation.
Schemas define the structure of data stored in Milvus collections, including
fields, primary keys, and vector configurations.

## Examples

    alias Milvex.Schema
    alias Milvex.Schema.Field

    # Using the builder pattern
    schema =
      Schema.new("movies")
      |> Schema.description("Movie embeddings collection")
      |> Schema.add_field(Field.primary_key("id", :int64, auto_id: true))
      |> Schema.add_field(Field.varchar("title", 512))
      |> Schema.add_field(Field.vector("embedding", 128))
      |> Schema.enable_dynamic_field()
      |> Schema.validate!()

    # Using the build/1 helper
    schema = Schema.build(
      name: "movies",
      description: "Movie embeddings collection",
      enable_dynamic_field: true,
      fields: [
        Field.primary_key("id", :int64, auto_id: true),
        Field.varchar("title", 512),
        Field.vector("embedding", 128)
      ]
    )

# `t`

```elixir
@type t() :: %Milvex.Schema{
  description: String.t() | nil,
  enable_dynamic_field: boolean(),
  fields: [Milvex.Schema.Field.t()],
  functions: [Milvex.Function.t()],
  name: String.t()
}
```

# `add_field`

```elixir
@spec add_field(t(), Milvex.Schema.Field.t()) :: t()
```

Adds a field to the schema.

## Examples

    schema
    |> Schema.add_field(Field.new("id", :int64) |> Field.primary_key())
    |> Schema.add_field(Field.vector("embedding", 128))

# `add_fields`

```elixir
@spec add_fields(t(), [Milvex.Schema.Field.t()]) :: t()
```

Adds multiple fields to the schema.

## Examples

    Schema.add_fields(schema, [
      Field.primary_key("id", :int64),
      Field.vector("embedding", 128)
    ])

# `add_function`

```elixir
@spec add_function(t(), Milvex.Function.t()) :: t()
```

Adds a function to the schema.

## Examples

    schema
    |> Schema.add_function(Function.bm25("bm25_fn", input: "content", output: "sparse"))

# `build`

```elixir
@spec build(keyword() | map()) :: {:ok, t()} | {:error, Milvex.Error.t()}
```

Builds a schema from a keyword list or map.

## Options
  - `:name` - Collection name (required)
  - `:description` - Collection description
  - `:fields` - List of Field structs (required)
  - `:enable_dynamic_field` - Enable dynamic fields (default: false)

## Examples

    Schema.build(
      name: "movies",
      fields: [
        Field.primary_key("id", :int64),
        Field.vector("embedding", 128)
      ]
    )

# `build!`

```elixir
@spec build!(keyword() | map()) :: t()
```

Builds a schema from options and raises on error.

# `description`

```elixir
@spec description(t(), String.t()) :: t()
```

Sets the collection description.

# `enable_dynamic_field`

```elixir
@spec enable_dynamic_field(t(), boolean()) :: t()
```

Enables or disables dynamic fields for the collection.

When enabled, the collection can store fields not defined in the schema.

# `field_names`

```elixir
@spec field_names(t()) :: [String.t()]
```

Returns the names of all fields in the schema.

# `from_proto`

```elixir
@spec from_proto(Milvex.Milvus.Proto.Schema.CollectionSchema.t() | nil) :: t() | nil
```

Creates a Schema from a protobuf CollectionSchema struct.

Returns `nil` if the input is `nil`.
Combines regular fields and struct_array_fields into a single fields list.

# `get_field`

```elixir
@spec get_field(t(), String.t()) :: Milvex.Schema.Field.t() | nil
```

Finds a field by name.

Returns `nil` if the field is not found.

# `new`

```elixir
@spec new(String.t()) :: t()
```

Creates a new schema with the given collection name.

## Parameters
  - `name` - Collection name (1-255 characters)

## Examples

    Schema.new("movies")

# `primary_key_field`

```elixir
@spec primary_key_field(t()) :: Milvex.Schema.Field.t() | nil
```

Returns the primary key field from the schema.

Returns `nil` if no primary key is defined.

# `scalar_fields`

```elixir
@spec scalar_fields(t()) :: [Milvex.Schema.Field.t()]
```

Returns all scalar fields from the schema.

# `struct_array_fields`

```elixir
@spec struct_array_fields(t()) :: [Milvex.Schema.Field.t()]
```

Returns all array_of_struct fields from the schema.

# `to_proto`

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

Converts the schema to a protobuf CollectionSchema struct.

Splits fields into regular fields and struct_array_fields as required
by the Milvus proto schema.

# `validate`

```elixir
@spec validate(t()) :: {:ok, t()} | {:error, Milvex.Error.t()}
```

Validates the schema configuration.

Checks:
- Collection name is valid (1-255 chars, alphanumeric + underscore)
- At least one field is defined
- Exactly one primary key field exists
- All field names are unique
- All individual fields pass validation

Returns `{:ok, schema}` if valid, `{:error, error}` otherwise.

# `validate!`

```elixir
@spec validate!(t()) :: t()
```

Validates the schema and raises on error.

# `vector_fields`

```elixir
@spec vector_fields(t()) :: [Milvex.Schema.Field.t()]
```

Returns all vector fields from the schema.

---

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