// Get all productsconstallProducts=awaitctx.products.toArrayAsync();// Get all products with filteringconstexpensiveProducts=awaitctx.products.where((p)=>p.price>100).toArrayAsync();
Getting Single Items
>
1
2
3
4
5
6
7
8
9
10
// Get first product (throws if none exist)constfirstProduct=awaitctx.products.firstAsync();// Get first product or undefined if none existconstfirstOrUndefined=awaitctx.products.firstOrUndefinedAsync();// Get first expensive productconstfirstExpensive=awaitctx.products.where((p)=>p.price>100).firstOrUndefinedAsync();
Checking Existence
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Check if any products existconsthasProducts=awaitctx.products.someAsync();// Check if any expensive products existconsthasExpensiveProducts=awaitctx.products.where((p)=>p.price>100).someAsync();// Check if all products are in stockconstallInStock=awaitctx.products.everyAsync((p)=>p.inStock);// Check if all electronics are in stockconstallElectronicsInStock=awaitctx.products.where((p)=>p.category==="electronics").everyAsync((p)=>p.inStock);
Counting Items
>
1
2
3
4
5
6
7
8
9
10
11
12
// Count all productsconsttotalCount=awaitctx.products.countAsync();// Count products in specific categoryconstelectronicsCount=awaitctx.products.where((p)=>p.category==="electronics").countAsync();// Count expensive productsconstexpensiveCount=awaitctx.products.where((p)=>p.price>100).countAsync();
Aggregation Operations
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Sum all product pricesconsttotalValue=awaitctx.products.sumAsync((p)=>p.price);// Sum prices of electronicsconstelectronicsValue=awaitctx.products.where((p)=>p.category==="electronics").sumAsync((p)=>p.price);// Get minimum priceconstminPrice=awaitctx.products.minAsync((p)=>p.price);// Get maximum priceconstmaxPrice=awaitctx.products.maxAsync((p)=>p.price);// Get minimum price of electronicsconstminElectronicsPrice=awaitctx.products.where((p)=>p.category==="electronics").minAsync((p)=>p.price);
Distinct Values
>
1
2
3
4
5
6
7
8
9
10
// Get unique categoriesconstuniqueCategories=awaitctx.products.map((p)=>p.category).distinctAsync();// Get unique pricesconstuniquePrices=awaitctx.products.map((p)=>p.price).distinctAsync();// Get unique product namesconstuniqueNames=awaitctx.products.map((p)=>p.name).distinctAsync();
Grouping Data
Group items by a key value, returning a record where keys are the grouped values and values are arrays of items with that key:
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Group products by categoryconstproductsByCategory=awaitctx.products.toGroupAsync((p)=>p.category);// Result: { "electronics": Product[], "clothing": Product[], "books": Product[] }// Group products by statusconstproductsByStatus=awaitctx.products.toGroupAsync((p)=>p.status);// Result: { "active": Product[], "inactive": Product[] }// Group with filteringconstexpensiveByCategory=awaitctx.products.where((p)=>p.price>100).toGroupAsync((p)=>p.category);// Group by numeric fieldconstproductsByPriceRange=awaitctx.products.toGroupAsync((p)=>p.price<50?"budget":p.price<200?"mid":"premium");// Result: { "budget": Product[], "mid": Product[], "premium": Product[] }
The selector function must return a value that can be used as an object key (string, number, or Date). Each group contains an array of all items that share the same key value.
Removal Operations
>
1
2
3
4
5
6
7
8
9
10
11
// Remove all productsawaitctx.products.removeAsync();// Remove expensive productsawaitctx.products.where((p)=>p.price>100).removeAsync();// Remove products in specific categoryawaitctx.products.where((p)=>p.category==="electronics").removeAsync();// Remove out of stock productsawaitctx.products.where((p)=>p.inStock===false).removeAsync();
Important Notes
Lazy Evaluation
Queries are lazy - nothing executes until you call a terminal method
You can chain multiple operations before calling a terminal method
The query is built up and executed only when the terminal method is called
Async vs Callback Styles
Both async Promises and callback styles are supported:
For live results that update automatically, you can chain .subscribe() before a terminal method:
>
1
2
3
4
5
// Live query - will update when data changesctx.products.where((p)=>p.price>100).subscribe().toArrayAsync();
Common Patterns
Data Validation
>
1
2
3
4
5
6
// Check if user exists before creatingconstuserExists=awaitctx.users.where((u)=>u.email===email).someAsync();if(userExists){thrownewError("User already exists");}
Pagination with Count
>
1
2
3
4
5
6
7
8
9
// Get page data and total countconstpageSize=10;constpage=1;constoffset=(page-1)*pageSize;const[products,totalCount]=awaitPromise.all([ctx.products.skip(offset).take(pageSize).toArrayAsync(),ctx.products.countAsync(),]);
Conditional Operations
>
1
2
3
4
5
6
// Only proceed if data existsconsthasData=awaitctx.products.someAsync();if(hasData){constfirstProduct=awaitctx.products.firstAsync();// Process first product}
Organizing Data by Category
>
1
2
3
4
5
6
7
8
9
10
11
12
// Group products by category for displayconstproductsByCategory=awaitctx.products.toGroupAsync((p)=>p.category);// Iterate over groupsfor(const[category,products]ofObject.entries(productsByCategory)){console.log(`${category}: ${products.length} products`);}// Group with filteringconstactiveProductsByStatus=awaitctx.products.where((p)=>p.active).toGroupAsync((p)=>p.status);