Real-World API Scenario
This example demonstrates a complex request combining multiple FlexQuery.NET features to power a sophisticated dashboard view.
The Scenario
We want to fetch customers whose name contains "Connelly". For each customer, we want to include their email and name, but we only want to see their cancelled orders. Furthermore, within those cancelled orders, we only want to see the items matching "Tasty Metal Pants".
The Request
http
GET /api/customers
?query=(name contains "Connelly")
&pageSize=2
&select=id,email,name,orders.id,orders.orderDate,orders.status,orders.orderItems
&include=orders(status = "cancelled").orderItems(productName = "Tasty Metal Pants")Breakdown:
query=(name contains "Connelly"): The Root Filter. This ensures we only get customers matching this name.pageSize=2: Limits the results to 2 customers.select=id,email,name,orders.id...: The Projection. This ensures we only fetch specific columns for both the Customer and the Order objects, reducing database bandwidth.include=orders(status = "cancelled").orderItems(...): The Filtered Include.- It filters the
orderscollection to only include those with "cancelled" status. - It further filters the
orderItemswithin those orders to only include "Tasty Metal Pants".
- It filters the
The Response
json
{
"totalCount": 1,
"page": 1,
"pageSize": 2,
"totalPages": 1,
"data": [
{
"id": 42,
"name": "John Connelly",
"email": "j.connelly@example.com",
"orders": [
{
"id": 1001,
"orderDate": "2026-04-15T10:30:00Z",
"status": "cancelled",
"orderItems": [
{
"id": 5001,
"productId": 101,
"productName": "Tasty Metal Pants",
"unitPrice": 49.99
}
]
}
]
}
]
}Why this is powerful
- Efficiency: The filtering on orders and order items happens at the database level. Only one customer is returned, and their collections are already pruned.
- Security: The
selectensures that internal fields likeCustomer.SecretKeyorOrder.InternalNotesare never even fetched from the database, much less sent to the client. - Simplicity: This entire logic is handled by a single
.ApplyValidatedQueryOptions(options)call in the controller. No complex custom repositories or manual LINQ join logic required.
