# `Milvex.Index`

Builder for Milvus index configurations.

Provides a fluent API for constructing index definitions with validation.
Supports vector indexes, sparse indexes, and scalar field indexes.

## Vector Index Examples

    index = Index.new("embedding", :hnsw, :cosine)
            |> Index.name("my_index")
            |> Index.params(%{M: 16, efConstruction: 256})

    Index.flat("embedding", :l2)
    Index.ivf_flat("embedding", :ip, nlist: 1024)
    Index.hnsw("embedding", :cosine, m: 16, ef_construction: 256)
    Index.autoindex("embedding", :l2)

## Scalar Index Examples

    Index.inverted("category")
    Index.stl_sort("price")
    Index.trie("username")
    Index.bitmap("status")

# `index_type`

```elixir
@type index_type() :: vector_index_type() | scalar_index_type()
```

# `inverted_index_algo`

```elixir
@type inverted_index_algo() :: :daat_maxscore | :daat_wand | :taat_naive
```

# `metric_type`

```elixir
@type metric_type() ::
  :l2
  | :ip
  | :cosine
  | :hamming
  | :jaccard
  | :max_sim_cosine
  | :max_sim_ip
  | :bm25
```

# `scalar_index_type`

```elixir
@type scalar_index_type() :: :inverted | :stl_sort | :trie | :bitmap
```

# `t`

```elixir
@type t() :: %Milvex.Index{
  field_name: String.t(),
  index_type: index_type(),
  metric_type: metric_type() | nil,
  name: String.t() | nil,
  params: map()
}
```

# `vector_index_type`

```elixir
@type vector_index_type() ::
  :flat
  | :ivf_flat
  | :ivf_sq8
  | :ivf_pq
  | :hnsw
  | :autoindex
  | :diskann
  | :gpu_ivf_flat
  | :gpu_ivf_pq
  | :scann
  | :sparse_inverted_index
```

# `autoindex`

```elixir
@spec autoindex(String.t(), metric_type(), keyword()) :: t()
```

Creates an AUTOINDEX.

Lets Milvus automatically choose the best index type and parameters
based on data characteristics.

## Options
  - `:name` - Index name (optional)

## Examples

    Index.autoindex("embedding", :l2)

# `bitmap`

```elixir
@spec bitmap(
  String.t(),
  keyword()
) :: t()
```

Creates a BITMAP index for low-cardinality scalar fields.

Supports BOOL, INT8, INT16, INT32, INT64, VARCHAR, and ARRAY fields.
Not supported for FLOAT, DOUBLE, or JSON types.

## Options
  - `:name` - Index name (optional)

## Examples

    Index.bitmap("status")
    Index.bitmap("is_active", name: "active_bitmap_idx")

# `diskann`

```elixir
@spec diskann(String.t(), metric_type(), keyword()) :: t()
```

Creates a DiskANN index.

Disk-based ANN index for very large datasets that don't fit in memory.

## Options
  - `:name` - Index name (optional)

## Examples

    Index.diskann("embedding", :l2)

# `flat`

```elixir
@spec flat(String.t(), metric_type()) :: t()
```

Creates a FLAT index (brute-force search).

FLAT provides 100% recall but is slower for large datasets.
Best for small datasets or when perfect accuracy is required.

## Examples

    Index.flat("embedding", :l2)
    Index.flat("embedding", :cosine)

# `hnsw`

```elixir
@spec hnsw(String.t(), metric_type(), keyword()) :: t()
```

Creates an HNSW index.

Hierarchical Navigable Small World graph. Excellent performance
for high-dimensional vectors with good recall.

## Options
  - `:m` - Maximum number of connections per node (default: 16)
  - `:ef_construction` - Search depth during index building (default: 256)
  - `:name` - Index name (optional)

## Examples

    Index.hnsw("embedding", :cosine)
    Index.hnsw("embedding", :l2, m: 32, ef_construction: 512)

# `index_types`

```elixir
@spec index_types() :: [index_type()]
```

Returns list of all supported index types.

# `inverted`

```elixir
@spec inverted(
  String.t(),
  keyword()
) :: t()
```

Creates an INVERTED index for scalar fields.

Supports all scalar field types: BOOL, INT8, INT16, INT32, INT64,
FLOAT, DOUBLE, VARCHAR, JSON, and ARRAY.

## Options
  - `:name` - Index name (optional)

## Examples

    Index.inverted("category")
    Index.inverted("category", name: "category_idx")

# `ivf_flat`

```elixir
@spec ivf_flat(String.t(), metric_type(), keyword()) :: t()
```

Creates an IVF_FLAT index.

Inverted File index with flat quantization. Good balance of
speed and accuracy for medium-sized datasets.

## Options
  - `:nlist` - Number of cluster units (default: 1024)
  - `:name` - Index name (optional)

## Examples

    Index.ivf_flat("embedding", :l2)
    Index.ivf_flat("embedding", :ip, nlist: 2048)

# `ivf_pq`

```elixir
@spec ivf_pq(String.t(), metric_type(), keyword()) :: t()
```

Creates an IVF_PQ index.

IVF with product quantization. Very memory-efficient but with
lower accuracy. Best for very large datasets.

## Options
  - `:nlist` - Number of cluster units (default: 1024)
  - `:m` - Number of subquantizers (default: 8)
  - `:nbits` - Bits per subquantizer (default: 8)
  - `:name` - Index name (optional)

## Examples

    Index.ivf_pq("embedding", :l2)
    Index.ivf_pq("embedding", :ip, nlist: 2048, m: 16)

# `ivf_sq8`

```elixir
@spec ivf_sq8(String.t(), metric_type(), keyword()) :: t()
```

Creates an IVF_SQ8 index.

IVF with scalar quantization. More memory-efficient than IVF_FLAT
with slight accuracy trade-off.

## Options
  - `:nlist` - Number of cluster units (default: 1024)
  - `:name` - Index name (optional)

## Examples

    Index.ivf_sq8("embedding", :l2)
    Index.ivf_sq8("embedding", :ip, nlist: 2048)

# `metric_types`

```elixir
@spec metric_types() :: [metric_type()]
```

Returns list of all supported metric types.

# `name`

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

Sets the index name.

If not set, Milvus will auto-generate a name.

# `new`

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

Creates a new scalar index configuration.

Scalar indexes do not require a metric type.

## Parameters
  - `field_name` - Name of the scalar field to index
  - `index_type` - Type of scalar index (`:inverted`, `:stl_sort`, `:trie`, `:bitmap`)

## Examples

    Index.new("category", :inverted)
    Index.new("age", :stl_sort)
    Index.new("name", :trie)
    Index.new("status", :bitmap)

# `new`

```elixir
@spec new(String.t(), index_type(), metric_type()) :: t()
```

Creates a new vector index configuration.

## Parameters
  - `field_name` - Name of the vector field to index
  - `index_type` - Type of index to create
  - `metric_type` - Distance metric to use

## Examples

    Index.new("embedding", :hnsw, :cosine)
    Index.new("vectors", :ivf_flat, :l2)

# `params`

```elixir
@spec params(t(), map()) :: t()
```

Sets or merges additional index parameters.

Parameters are index-type specific. Common parameters include:
- IVF indexes: `nlist` (number of cluster units)
- HNSW: `M` (max connections), `efConstruction` (search depth during build)
- IVF_PQ: `m` (number of subquantizers), `nbits` (bits per subquantizer)

# `scalar_index_types`

```elixir
@spec scalar_index_types() :: [scalar_index_type()]
```

Returns list of scalar index types.

# `scann`

```elixir
@spec scann(String.t(), metric_type(), keyword()) :: t()
```

Creates a SCANN index.

Google's ScaNN (Scalable Nearest Neighbors) implementation.
Good balance of speed and accuracy.

## Options
  - `:nlist` - Number of cluster units (default: 1024)
  - `:name` - Index name (optional)

## Examples

    Index.scann("embedding", :l2)
    Index.scann("embedding", :cosine, nlist: 2048)

# `sparse_bm25`

```elixir
@spec sparse_bm25(
  String.t(),
  keyword()
) :: t()
```

Creates a SPARSE_INVERTED_INDEX for BM25 full-text search.

Used for SPARSE_FLOAT_VECTOR fields that receive BM25 function output.
Supports inverted index algorithms optimized for sparse vectors.

## Options
  - `:inverted_index_algo` - Algorithm to use (default: `:daat_maxscore`)
    - `:daat_maxscore` - Document-at-a-time with MaxScore optimization
    - `:daat_wand` - Document-at-a-time with WAND optimization
    - `:taat_naive` - Term-at-a-time naive approach
  - `:bm25_k1` - BM25 k1 parameter (default: 1.2)
  - `:bm25_b` - BM25 b parameter (default: 0.75)
  - `:drop_ratio_build` - Drop ratio during index build (default: 0.2)
  - `:name` - Index name (optional)

## Examples

    Index.sparse_bm25("text_sparse")
    Index.sparse_bm25("text_sparse", inverted_index_algo: :daat_wand)
    Index.sparse_bm25("text_sparse", bm25_k1: 1.5, bm25_b: 0.8)
    Index.sparse_bm25("text_sparse", drop_ratio_build: 0.1)

# `stl_sort`

```elixir
@spec stl_sort(
  String.t(),
  keyword()
) :: t()
```

Creates an STL_SORT index for numeric scalar fields.

Supports numeric types: INT8, INT16, INT32, INT64, FLOAT, DOUBLE.

## Options
  - `:name` - Index name (optional)

## Examples

    Index.stl_sort("price")
    Index.stl_sort("timestamp", name: "ts_idx")

# `to_extra_params`

```elixir
@spec to_extra_params(t()) :: [Milvex.Milvus.Proto.Common.KeyValuePair.t()]
```

Converts the index configuration to protobuf extra_params.

Returns a list of KeyValuePair structs for use in CreateIndexRequest.

# `trie`

```elixir
@spec trie(
  String.t(),
  keyword()
) :: t()
```

Creates a Trie index for VARCHAR fields.

Optimized for prefix matching queries on string fields.

## Options
  - `:name` - Index name (optional)

## Examples

    Index.trie("username")
    Index.trie("email", name: "email_trie_idx")

# `validate`

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

Validates the index configuration.

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

# `validate!`

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

Validates the index and raises on error.

# `vector_index_types`

```elixir
@spec vector_index_types() :: [vector_index_type()]
```

Returns list of vector index types.

---

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