Skip to main content

Reference

Reference​

Both overloads are in Vali_Flow.NoSql.Redis.Extensions.ValiFlowRedisSearchExtensions.

ToRedisSearch<T>(this ValiFlow<T> flow, Func<object?, string?>? customConverter = null)​

Translates the conditions accumulated in a ValiFlow<T> builder into a RediSearch query string.

ParameterTypeRequiredDescription
flowValiFlow<T>YesThe builder containing the conditions.
customConverterFunc<object?, string?>?NoHook for mapping CLR types to their tag-value string. Return null to fall through to the default conversion.

Returns: string — pass to new Query(result) or use directly in FT().Search(...).

ToRedisSearch<T>(this Expression<Func<T, bool>> expression, Func<object?, string?>? customConverter = null)​

Same translation for a pre-built Expression<Func<T, bool>>.

Expression<Func<Order, bool>> expr = o => o.Status == "Pending";
string query = expr.ToRedisSearch();

Supported Operations​

ValiFlow methodIR nodeRediSearch output
.EqualTo(x => x.NumField, 42)EqualNode (numeric)@NumField:[42 42]
.EqualTo(x => x.StrField, "v")EqualNode (string)@StrField:{"v"}
.NotEqualTo(x => x.NumField, 42)EqualNode(IsNegated, numeric)(-@NumField:[42 42])
.NotEqualTo(x => x.StrField, "v")EqualNode(IsNegated, string)-@StrField:{"v"}
.GreaterThan(x => x.Field, v)ComparisonNode(GT)@Field:[(v +inf]
.GreaterThanOrEqualTo(x => x.Field, v)ComparisonNode(GTE)@Field:[v +inf]
.LessThan(x => x.Field, v)ComparisonNode(LT)@Field:[-inf (v]
.LessThanOrEqualTo(x => x.Field, v)ComparisonNode(LTE)@Field:[-inf v]
.Contains(x => x.Field, "txt")LikeNode(Contains)@Field:*txt*
.StartsWith(x => x.Field, "pre")LikeNode(StartsWith)@Field:pre*
.EndsWith(x => x.Field, "suf")LikeNode(EndsWith)@Field:*suf
.In(x => x.Field, [1, 2, 3])InNode (numeric)(@Field:[1 1]|@Field:[2 2]|@Field:[3 3])
.In(x => x.Field, ["a", "b"])InNode (string)@Field:{"a"|"b"}
.And(a, b)AndNode(a b)
.Or(a, b)OrNode(a | b)
.Not(inner)NotNode-(inner)

Exclusive range bounds: RediSearch uses (value (opening parenthesis before the number) to express strict inequality. GreaterThan emits [(v +inf] and LessThan emits [-inf (v].

Tag escaping: \ and " inside quoted tag values are escaped to \\ and \".

Mixed IN list: If an InNode contains a mix of numeric and non-numeric values, InvalidOperationException is thrown. All non-null values in an In list must be of the same kind (all numeric/bool, or all strings).


Type Mapping​

Values are classified as either numeric (mapped to range queries) or string (mapped to tag queries).

Numeric/bool types (use range query syntax @field:[v v]):

CLR typeRediSearch representation
bool1 (true) or 0 (false)
intstring representation
longstring representation
doublestring representation (InvariantCulture)
floatstring representation (InvariantCulture)
decimalconverted to double, then string

String/other types (use tag query syntax @field:{"value"}):

CLR typeTag value
stringthe string itself
Enum.ToString() (name, not number)
anything else.ToString()

Custom Value Converter​

Use customConverter to control how domain types appear in the query string. The converter is called before the built-in classification. Return null to let the default handle the value.

// Domain type
record Money(decimal Amount, string Currency);

// Converter: use the numeric amount so it lands in a range query
string query = new ValiFlow<Product>()
.GreaterThan(x => x.Price, new Money(100m, "USD"))
.ToRedisSearch(value =>
{
if (value is Money m)
return m.Amount.ToString(CultureInfo.InvariantCulture);
return null;
});

// query → "@Price:[(100 +inf]"

Returning a string from the converter always produces a tag query for equality, and is used as-is for range queries (so return an invariant-culture number string for numeric fields).


Advanced Example​

var query = new ValiFlow<User>()
.EqualTo(x => x.Country, "PE")
.GreaterThan(x => x.Age, 18)
.ToRedisSearch();