iqdb-index 1.0.0

The Index trait unifying flat, HNSW, and IVF vector indexes - part of the iQDB family.
Documentation
  • IndexCore trait — the object-safe operational surface (insert, delete, search, len, dim, metric, flush, stats). The engine holds indexes as Box<dyn IndexCore>.
  • Index trait — typed construction: an associated Config and a new(dim, metric, config). Split out from IndexCore because a Self-returning constructor is not object-safe.
  • Associated Config — each index exposes its own parameter struct, not a god-config enum.
  • Default batch shimsinsert_batch / search_batch ship for free and are overridable when a backend has a vectorized fast path.
  • IndexStats — uniform, allocation-light introspection across index types.
  • Documented contracts — best-first ordering (with the DotProduct negation rule), deletion visibility, and the Send + Sync concurrency model live on the trait, so every backend agrees.

Installation

[dependencies]
iqdb-index = "1.0"

Quick Start

Implement the two traits for your index, then construct, insert, and search through one uniform surface. The full runnable version is in examples/custom_index.rs.

use std::sync::Arc;
use iqdb_index::{Index, IndexCore};
use iqdb_types::{DistanceMetric, SearchParams, VectorId};

// `FlatIndex` implements `IndexCore` + `Index` (see the example).
let mut index = FlatIndex::new(3, DistanceMetric::Euclidean, FlatConfig)?;

index.insert_batch(vec![
    (VectorId::from(1u64), Arc::from([1.0, 0.0, 0.0].as_slice()), None),
    (VectorId::from(2u64), Arc::from([0.0, 1.0, 0.0].as_slice()), None),
])?;

let hits = index.search(&[1.0, 0.0, 0.0], &SearchParams::new(1, DistanceMetric::Euclidean))?;
assert_eq!(hits[0].id, VectorId::U64(1)); // best-first

// Hold any backend behind the object-safe trait:
let engine: Vec<Box<dyn IndexCore>> = vec![Box::new(index)];
assert_eq!(engine[0].len(), 2);

The three tiers

Tier Surface When
Tier 1 Index::new + the IndexCore operations Build an index and use it.
Tier 2 Index::Config Tune a specific backend.
Tier 3 implement IndexCore + Index Add a new index strategy.

Examples

Runnable, each covering a distinct facet of the surface (cargo run --example <name>):

Example Shows
custom_index Implement IndexCore + Index by hand — the Tier-3 seam.
polymorphic_engine Hold several index kinds as Box<dyn IndexCore> and dispatch over them.
dot_product_ordering The DotProduct negation contract — store -dot so "most similar" sorts first.
batch_and_stats The default insert_batch / search_batch shims and IndexStats::extra.

Status

v1.0.0stable. The public API is committed under SemVer for the 1.x series (no breaking changes until 2.0; the frozen surface is recorded in the ROADMAP). IndexCore, Index, IndexStats, and the default batch shims are property-tested (best-first ordering, deletion visibility, batch == loop) and documented with four runnable examples and a complete API reference. The surface is validated against the live iqdb-flat (brute-force, true removal), iqdb-hnsw (graph, tombstone), and iqdb-ivf (clustered, true removal) implementations — each implements the traits verbatim with its own Config — and a consumer-simulation proves all three coexist behind Box<dyn IndexCore> (DIRECTIVES §8). Synchronous by design; empty, frozen feature set; cargo audit + cargo deny clean; verified on Windows + Linux across stable and the 1.87 MSRV.

Where It Fits

iqdb-index is the interface every index speaks. It is implemented by:

  • iqdb-types — the only dependency
  • iqdb-flat / iqdb-hnsw / iqdb-ivf — implement this trait
  • iqdb-build / iqdb-eval / iqdb — are generic over it

Designing this trait so flat, HNSW, and IVF all fit cleanly is the crate's whole job.

Contributing

See dev/DIRECTIVES.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.