SmallWorld Class
Definition
Namespace: HNSW.Net
public class SmallWorld<TItem, TDistance>
Type parameters
TItem
: The item stored in the graph (for example float[]).
TDistance
: The numeric distance type returned by the distance function. Any numeric struct that implements IComparable<TDistance> works (float, int, …).
The Hierarchical Navigable Small World graph. A single SmallWorld<TItem, TDistance> builds the index, grows it with new items, and answers k-NN queries. It is generic over both the item type and the distance type, so it works with float[] embeddings, byte[] fingerprints, or any custom record.
Remarks
The layering of the HNSW graph is handled internally — add items, ask for neighbours. The graph supports incremental inserts but not per-item deletion; see Building a graph for the soft-delete and rebuild patterns.
The type is thread-safe by default: a reader-writer lock lets many KNNSearch calls run concurrently while serialising mutations such as AddItems. Pass threadSafe: false to the constructor to drop the lock when you have your own synchronisation or only ever query a fully-built graph. See Thread safety.
Constructors
| Name | Description |
|---|---|
SmallWorld(distance, generator, parameters, threadSafe) |
Creates an empty graph with a distance function, a random generator, and parameters. |
Constructor
public SmallWorld(
Func<TItem, TItem, TDistance> distance,
IProvideRandomValues generator,
SmallWorldParameters parameters,
bool threadSafe = true)
Creates an empty graph. distance is the metric used everywhere the library compares items — smaller must mean closer. generator supplies the randomness for level assignment; pass DefaultRandomGenerator.Instance. parameters is the SmallWorldParameters configuration. Set threadSafe: false to skip the internal reader-writer lock. See Distance functions.
Methods
| Name | Description |
|---|---|
AddItems(items) |
Inserts a batch of items and returns the integer IDs assigned to them. |
AddItems(items, progressReporter) |
Inserts a batch of items while reporting progress through an IProgressReporter. |
KNNSearch(item, k, filterItem, cancellationToken) |
Returns up to k items closest to the query under the distance function. |
GetItem(id) |
Returns the item stored for a given integer ID. |
SerializeGraph(stream) |
Writes the graph structure (parameters and edges) to a stream. |
DeserializeGraph(items, distance, generator, stream, threadSafe) |
Static. Rebuilds a graph from a stream and the original items. |
AddItems
public IReadOnlyList<int> AddItems(IReadOnlyList<TItem> items)
Inserts one batch of items into the graph and returns the integer IDs HNSW assigns to each input. The IDs are returned from KNNSearch and used everywhere the library refers to an item; they are stable for the lifetime of the graph. Call AddItems again to grow the same graph — there is no separate index/query mode. See Building a graph.
AddItems (with progress)
public IReadOnlyList<int> AddItems(
IReadOnlyList<TItem> items,
IProgressReporter progressReporter)
Same as AddItems(items), but calls IProgressReporter.Progress from the inserting thread as the batch is processed. total is the count for this call, not the cumulative graph size. See Progress reporting.
KNNSearch
public IList<KNNSearchResult> KNNSearch(
TItem item,
int k,
Func<TItem, bool> filterItem = null,
CancellationToken cancellationToken = default)
Returns up to k items judged closest to item under the distance function, each as a KNNSearchResult. The list is not pre-sorted — sort by Distance for ranked output. Pass filterItem to keep only candidates that satisfy a predicate; the cancellationToken is only checked when a filter is supplied. See k-NN search and Filtering.
GetItem
public TItem GetItem(int id)
Returns the item stored for the integer ID returned by AddItems. Takes a read lock when the graph is thread-safe.
SerializeGraph
public void SerializeGraph(Stream stream)
Writes the graph structure — parameters and edges — to any Stream as a MessagePack blob with an HNSW header. The vectors themselves are not stored; re-supply them on load. See Serialization.
DeserializeGraph
public static (SmallWorld<TItem, TDistance> graph, int[] missing) DeserializeGraph(
IReadOnlyList<TItem> items,
Func<TItem, TItem, TDistance> distance,
IProvideRandomValues generator,
Stream stream,
bool threadSafe = true)
Static factory that rebuilds a graph from a stream. Pass the original items in the same order, the same distance function used at build time, and a random generator. Returns the graph plus a missing array listing any items the file references that weren't supplied — normally empty. InitialDistanceCacheSize is reset to 0 on load. See Serialization and Thread safety.
Properties
| Name | Description |
|---|---|
Parameters |
The live SmallWorldParameters. Change EfSearch between queries here. |
Items |
A copy of the stored items, taken under a read lock. |
UnsafeItems |
The underlying item list, returned directly with no lock. |
Parameters
public SmallWorldParameters Parameters { get; }
The SmallWorldParameters the graph was built with. EfSearch is the runtime dial — assign Parameters.EfSearch between queries to trade recall against latency without rebuilding.
Items
public IReadOnlyList<TItem> Items { get; }
Returns a copy of the stored items under a read lock. Safe to enumerate even while a writer adds more items, at the cost of an allocation. See Thread safety.
UnsafeItems
public IReadOnlyList<TItem> UnsafeItems { get; }
Returns the underlying item list directly, with no lock. Cheap, but you must guarantee no AddItems runs concurrently — enumerating it during a mutation throws. See Thread safety.
Nested types
| Name | Description |
|---|---|
KNNSearchResult |
A single search hit: ID, item, and distance. |
KNNSearchResult
public struct KNNSearchResult
A single result returned by KNNSearch. Exposes Id — the integer ID assigned by AddItems; Item — the original TItem reference; and Distance — the numeric distance from the query.
Applies to
HNSW.Net — see Parameters, Distance functions, and the guides.