redis-vl-dotnet

FilterQuery

FilterQuery is the general-purpose search object for structured RediSearch filters without a free-text query string.

When to use it

Use FilterQuery when the match criteria come from fielded filters:

  • tag equality and set membership (Filter.Tag(field).Eq/In) and wildcard patterns (Filter.Tag(field).Like("tech*"))

  • numeric ranges

  • text expressions built with the filter DSL: Match, Phrase, Prefix, Fuzzy, and Wildcard

  • geo radius (WithinRadius) and bounding-box (WithinBox) predicates

  • timestamp ranges over epoch-seconds fields (Filter.Timestamp(field).After/Before/Between/Eq)

  • boolean combinations through Filter.And(…​), Filter.Or(…​), and !

If you need a user-supplied text search string, use TextQuery instead.

Filter operators

// Tag wildcard patterns (the * is preserved, other characters escaped)
Filter.Tag("category").Like("tech*", "*ml");      // @category:{tech*|*ml}

// Fuzzy text match (Levenshtein distance 1-3)
Filter.Text("title").Fuzzy("redis");              // @title:%redis%
Filter.Text("title").Fuzzy("redis", 2);           // @title:%%redis%%

// Wildcard text match (DIALECT 2 w'...' syntax)
Filter.Text("title").Wildcard("f?o*bar");         // @title:w'f?o*bar'

// Geo bounding box (min/max longitude, min/max latitude)
Filter.Geo("location").WithinBox(-74.05, 40.6, -73.85, 40.9);

// Timestamp ranges over an epoch-seconds numeric field
Filter.Timestamp("created").After(DateTimeOffset.UtcNow.AddDays(-7));
Filter.Timestamp("created").Between(start, end);  // start/end are DateTimeOffset or long epoch seconds

Basic shape

var scienceFictionQuery = new FilterQuery(
    Filter.And(
        Filter.Tag("genre").Eq("science-fiction"),
        Filter.Numeric("year").GreaterThan(1980)),
    returnFields: ["title", "year", "genre"],
    pagination: new QueryPagination(offset: 0, limit: 10));

var results = await index.SearchAsync<MovieListing>(scienceFictionQuery);

The canonical runnable reference is /examples/JsonStorageExample.

Paging and projections

FilterQuery stores paging in QueryPagination:

  • default paging is offset: 0, limit: 10

  • offset and limit cannot be negative

  • returnFields are normalized, so duplicate names and leading @ markers are removed

If returnFields is omitted, RediSearch returns the stored document payload for the matching storage type. Add projections when you want smaller responses or plan to map into a projection type.

Typed mapping and batches

Every search result can stay raw or map into a .NET type:

var projected = await index.SearchAsync<MovieSummary>(
    new FilterQuery(Filter.Tag("genre").Eq("crime"), ["title", "year"]));

For larger result sets, iterate with SearchBatchesAsync:

await foreach (var batch in index.SearchBatchesAsync(
    new FilterQuery(Filter.Tag("genre").Eq("crime"), ["title"], pagination: new QueryPagination(limit: 100)),
    batchSize: 100))
{
    foreach (var document in batch.Documents)
    {
        Console.WriteLine(document.Values["title"]);
    }
}

The batch helpers clone the original query and advance only the pagination window.