Query Options
QueryOptions (namespace FlexQuery.NET.Models) is the parsed form of a request — the
single model every execution method consumes, regardless of where the request came from
(query string, fluent builder, or adapter). Understanding its properties means understanding
everything the pipeline can do.
How a request becomes options
Three equivalent paths, one destination:
C#
// 1. From FlexQueryParameters (query-string binding)
var options = parameters.ToQueryOptions(); // global default syntax
var options2 = parameters.ToQueryOptions(QuerySyntax.Fql); // explicit syntax
// 2. Built in code (fluent API)
var options4 = Query.Create()
.Filter(f => f.Equal("Status", "Active"))
.Page(1, 20)
.Build();Most endpoints skip explicit construction entirely — FlexQueryAsync(parameters, ...)
converts internally. Constructing QueryOptions yourself matters when composing: adapter
output, pre-built saved queries, or merging client input with server-side structure.
Properties
| Property | Type | Description |
|---|---|---|
Filter | FilterGroup? | Filter expression tree — conditions, nested groups, logic operators. See Filtering. |
Sort | List<SortNode> | Ordered sort specs (field, direction, optional aggregate). See Sorting. |
Select | List<SelectNode>? | Projection tree — fields, aliases, nested selections. See Projection. |
Includes | List<string>? | Navigation paths to include with all scalars. See Include. |
Expand | List<IncludeNode>? | Expansion trees with per-branch filter/sort/take. See Expand. |
ProjectionMode | ProjectionMode | Output shaping: Nested (default), Flat, FlatMixed. |
GroupBy | List<string>? | Group key fields. |
Aggregates | List<Aggregate> | Aggregate specs (typed AggregateFunction + field + alias). |
Having | HavingNode? | Condition tree over aggregate values — functions referenced as FUNCTION:Field:Operator:Value (e.g. sum:Total:gt:100), which must match a declared aggregate. |
Distinct | bool? | Applies Distinct(). |
Paging | PagingOptions | Page, PageSize (clamped 1–1000), Disabled flag. |
IncludeCount | bool? | Whether the total count is computed. |
The three request models
| Model | Use when |
|---|---|
FlexQueryParameters | ASP.NET Core [FromQuery] binding of raw strings. |
FlexQueryRequest | Strongly-typed request objects (OpenAPI-documented bodies), via ToQueryOptions(). |
QueryOptions | Composed server-side, adapter output, saved queries. |
Projection modes in detail
| Mode | Behavior |
|---|---|
Nested | Nested selections produce nested objects — the natural hierarchical shape. |
Flat | Nested collections flatten with SelectMany into a leaf-level rowset (SQL-join semantics). |
FlatMixed | Root scalars and nested-collection fields share one output row. |
Complete worked example
Composing client input with server-side constraints:
C#
[HttpGet("api/orders/search")]
public async Task<IActionResult> Search(
[FromQuery] FlexQueryParameters clientParams,
CancellationToken cancellationToken)
{
var options = clientParams.ToQueryOptions(); // client-driven part
// server-side composition - clients cannot override these
options.GroupBy = ["Status"];
options.Aggregates.Add(new Aggregate
{
Function = AggregateFunction.Sum,
Field = "TotalAmount",
Alias = "TotalRevenue",
});
var result = await db.Orders.FlexQueryAsync(options, cancellationToken);
return Ok(result);
}Common mistakes
Related
- Query Composition — building and merging these options in code
- Query Syntax — the languages that parse into them