Rust · Retrieval and Streaming

Retrieval and Streaming

use usearch::DenseBatch;use usearch::DenseCursor;use usearch::DenseSampleConfig;use usearch::DenseSearchStream;use usearch::DenseSearchStreamInitConfig;use usearch::DenseVectors;use usearch::Sample; 3.0.0-rc.1 · 4c3e5023

get lands every vector stored under a key in an arena, converted to the scalar type you name, one row per entry in insertion order; an absent key yields no rows.

let mut arena = Arena::new_in(&executor)?;
let vectors = index.on(&executor).get::<f32>(key, &mut arena)?;
println!("{:?}", vectors.view()?.shape());
let vectors = index.on(&executor).get::<f32>(key, &mut arena)?;    // rewinds it, so the vectors above are gone

A cursor walks the index contents, reading each shard’s publication watermark as it enters that shard, so an entry once passed is never revisited. Without start keys it yields every entry as stored; with them, the starts’ own entries first, then the entries those link to breadth-first, each once. next_keys walks the key column alone, and next_links copies the keys each entry links to beside it, both into an arena; the vectors themselves come from get.

let mut arena = Arena::new_in(&executor)?;
let mut cursor = index.on(&executor).cursor(&[])?;
loop {
    let batch = cursor.next_links(1024, &mut arena)?;
    if batch.written() == 0 { break; }
    println!("{} keys, the first linking to {:?}", batch.keys()?.len(), batch.links(0)?);
}

A search stream is a resumable best-first traversal, so callers that post-filter aggressively pull until satisfied instead of guessing “k” upfront. It walks exactly one query row, and each pull lands up to wanted more matches in an arena as the one query of Matches, empty once the walk is drained. No residency implements the stream yet, so the engine answers Status::Unsupported.

let mut arena = Arena::new_in(&executor)?;
let mut stream = index.on(&executor).search_stream(rows(&query, 768)?)?;
'pulls: loop {
    let pulled = stream.next(64, &mut arena)?;
    let found = pulled.query(0)?;
    if found.keys.is_empty() { break; }
    for (key, distance) in found.keys.iter().zip(found.distances) {
        if *distance > 0.3 { break 'pulls; }
        println!("{key} at {distance}");
}
}

§ Sampling

sample draws keys around a focus, each hanging from a shown or earlier draw, and places them in three dimensions beside the keys already shown, so a view grows one connected sample as it zooms.

let drawn = index.on(&executor).sample(
    256,
    &mut arena,
    DenseSampleConfig { shown: &shown, shown_coordinates: &xyz, focus: &near, seed: 42, ..Default::default() },
)?;
let (keys, places) = (drawn.keys()?, drawn.coordinates()?);

API

StructDenseBatchOne cursor pull exported into the arena it borrows: the keys, and beside them the keys each entry links to when the pull asked; the vectors themselves come from DenseVerbs::get.3
dense_index.rs:1387 ↗
pub struct DenseBatch<'arena>

Rust-only.

writtenEntries the pull wrote; zero means the walk is exhausted.
dense_index.rs:1396 ↗
pub fn written(&self) -> usize
keysThe keys of the entries, refused with Status::Device over device memory.
dense_index.rs:1399 ↗
pub fn keys(&self) -> Result<&'arena [Key]>
StructDenseCursorA walk over the index contents; see DenseVerbs::cursor.2
dense_index.rs:3003 ↗
pub struct DenseCursor<'index>

The walk is a sequential scan, so it stays a batch operation: export, migration, and visualization all move whole slabs.

Dropping it waits for every deferred call naming the cursor, then releases it.

Implements

Debug, Drop
next_keysCopies up to wanted next keys into arena; an empty batch means the walk is exhausted.
dense_index.rs:3011 ↗
pub fn next_keys<'arena>(
    &mut self,
    wanted: usize,
    arena: &'arena mut Arena,
) -> Result<DenseBatch<'arena>>
StructDenseSampleConfigThe view a sample grows and how it draws; see DenseVerbs::sample.
dense_index.rs:1144 ↗
pub struct DenseSampleConfig<'config>

Fields

shown&'config [Key]The keys already shown: never drawn again, and the paths reach toward them.
shown_coordinates&'config [[f32; 3]]Where each of shown sits, the points later draws are placed against.
focus&'config [Key]The keys to look around; empty looks around the whole index.
seedu64The draw: equal seeds, shown keys and focus over an unchanged index draw equally.
expansion_factorusizeThe breadth of the walks behind the draws; zero derives it from the geometry.
progressOption<&'config mut ProgressCallback<'config>>Reports the draws written against wanted and stops wherever it says to.
progress_stepsusizeReports the call makes at most, the last at completion; zero derives to ten.
statsOption<&'config mut DenseTraversalStats>Where the traversal telemetry lands, overwritten by the call.

Implements

Default
StructDenseSearchStreamA resumable nearest-neighbor stream; see DenseVerbs::search_stream.1
dense_index.rs:3065 ↗
pub struct DenseSearchStream<'index>

Ordering beyond the expansion horizon is best-effort nearest, not globally exact. Each pull lands its matches in the arena it is given as one query of a search, so nothing allocates per match. An empty pull means the walk is drained.

Dropping it waits for every deferred call naming the stream, then releases the walk state it keeps.

Implements

Debug, Drop
nextPulls up to wanted more matches into arena, as the one query of Matches.
dense_index.rs:3073 ↗
pub fn next<'arena>(&mut self, wanted: usize, arena: &'arena mut Arena) -> Result<Matches<'arena>>
StructDenseSearchStreamInitConfigThe query a stream walks and the breadth of its walk; see DenseVerbs::search_stream.
dense_index.rs:1215 ↗
pub struct DenseSearchStreamInitConfig<Query>

Fields

queryQueryExactly one query row.
expansion_factorusizeThe breadth of the candidates the walk explores; zero derives it from the geometry.

Implements

From<Query>
StructDenseVectorsThe rows DenseVerbs::get or DenseVerbs::attend exported into the arena it borrows.1
dense_index.rs:1265 ↗
pub struct DenseVectors<'arena, Value>

Rust-only.

viewOne row per entry under the key in insertion order, or per query, at the pitch the library reported; refused with Status::Device over device memory.
dense_index.rs:1275 ↗
pub fn view(&self) -> Result<MatrixView<'arena, Value>>
StructSampleThe draws DenseVerbs::sample exported into the arena it borrows.5
dense_index.rs:1338 ↗
pub struct Sample<'arena>

Rust-only.

writtenDraws the call wrote; fewer than wanted only once the region is exhausted.
dense_index.rs:1349 ↗
pub fn written(&self) -> usize
keysThe keys drawn, refused with Status::Device over device memory.
dense_index.rs:1352 ↗
pub fn keys(&self) -> Result<&'arena [Key]>
entry_ordinalsWhich of its key's entries each draw is, in the order DenseVerbs::get writes them.
dense_index.rs:1359 ↗
pub fn entry_ordinals(&self) -> Result<&'arena [usize]>
parentsThe one shown or earlier draw each draw hangs from and its distance, one query per draw, a draw with none holding no match.
dense_index.rs:1367 ↗
pub fn parents(&self) -> Matches<'arena>
coordinatesWhere each draw is placed, beside the shown keys.
dense_index.rs:1376 ↗
pub fn coordinates(&self) -> Result<&'arena [[f32; 3]]>