Vector Search with the .NET Client

Tip
The source code for this tutorial is available on GitHub.

This tutorial demonstrates how to perform kNN vector search and hybrid queries with the .NET Hot Rod client.

Prerequisites

  • A running Infinispan server.

  • .NET 10 or later.

Running the Example

dotnet run --project vector-search

Code Walkthrough

Schema and Code Generation

The example uses a Protos/beer.proto file with Grpc.Tools to generate a C# Beer class at build time. The same schema — with Infinispan indexing annotations — is registered on the server.

/* @Indexed */
message Beer {
  /* @Keyword(projectable = true, sortable = true) */
  string name = 1;
  /* @Vector(dimension = 3, similarity = COSINE) */
  repeated float descriptionEmbedding = 7;
}

Creating a Typed Cache

The builder infers marshallers from the Beer type and the Protobuf encoding. No manual marshaller setup needed.

var cache = client.NewCache<Beer>("beers")
    .WithEncoding(MediaType.Protobuf)
    .Build();

kNN Vector Search (Typed)

Use the <→ operator to find the k nearest neighbors to a query vector. Query<Beer>() returns typed results.

var results = await cache.Query<Beer>(
    "from quickstart.Beer b where b.descriptionEmbedding <-> [:v]~:k",
    new Dictionary<string, object> { ["v"] = new[] { 0.9f, 0.1f, 0.1f }, ["k"] = 3 });
foreach (var b in results)
    Console.WriteLine($"  {b.Name} {b.Style}");

Score Projection

Use score(b) to include the similarity score in projections.

var results = await cache.Query(
    "select b.name, b.style, score(b) from quickstart.Beer b where b.descriptionEmbedding <-> [:v]~:k",
    new Dictionary<string, object> { ["v"] = new[] { 0.05f, 0.9f, 0.1f }, ["k"] = 3 });

Hybrid Queries

Combine vector search with metadata filters using the filtering clause.

var results = await cache.Query(
    "select score(b), b.name, b.style, b.abv from quickstart.Beer b " +
    "where b.descriptionEmbedding <-> [:v]~:k " +
    "filtering (b.style = 'Lager' and b.abv < 5.0)",
    new Dictionary<string, object> { ["v"] = new[] { 0.05f, 0.95f, 0.05f }, ["k"] = 3 });

Combine vector search with full-text filters.

var results = await cache.Query(
    "select score(b), b.name from quickstart.Beer b " +
    "where b.descriptionEmbedding <-> [:v]~:k " +
    "filtering b.description : 'citrus'",
    new Dictionary<string, object> { ["v"] = new[] { 0.1f, 0.1f, 0.95f }, ["k"] = 5 });

Expected Output

The example runs 8 query demonstrations including full-text search, keyword and range filters, projections with sorting, kNN vector search, score projection, and three hybrid query variants.