@coasys/ad4m / Exports / ModelQueryBuilder
Class: ModelQueryBuilder<T>
Query builder for Ad4mModel queries. Allows building queries with a fluent interface and either running them once or subscribing to updates.
Example
const builder = Recipe.query(perspective)
.where({ category: "Dessert" })
.order({ rating: "DESC" })
.limit(10);
// Run once
const recipes = await builder.run();
// Or subscribe to updates
await builder.subscribe(recipes => {
console.log("Updated recipes:", recipes);
});Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel |
Table of contents
Constructors
Properties
Methods
- count
- countSubscribe
- dispose
- first
- get
- include
- limit
- offset
- order
- overrideModelClassName
- paginate
- paginateSubscribe
- parent
- properties
- subscribe
- useSurrealDB
- where
Constructors
constructor
• new ModelQueryBuilder<T>(perspective, ctor, query?)
Type parameters
| Name | Type |
|---|---|
T | extends Ad4mModel<T> |
Parameters
| Name | Type |
|---|---|
perspective | PerspectiveProxy |
ctor | typeof Ad4mModel |
query? | Query |
Defined in
model/ModelQueryBuilder.ts:43 (opens in a new tab)
Properties
ctor
• Private ctor: typeof Ad4mModel
Defined in
model/ModelQueryBuilder.ts:39 (opens in a new tab)
currentSubscription
• Private Optional currentSubscription: any
Defined in
model/ModelQueryBuilder.ts:40 (opens in a new tab)
modelClassName
• Private modelClassName: string = null
Defined in
model/ModelQueryBuilder.ts:38 (opens in a new tab)
perspective
• Private perspective: PerspectiveProxy
Defined in
model/ModelQueryBuilder.ts:36 (opens in a new tab)
queryParams
• Private queryParams: Query = {}
Defined in
model/ModelQueryBuilder.ts:37 (opens in a new tab)
useSurrealDBFlag
• Private useSurrealDBFlag: boolean = true
Defined in
model/ModelQueryBuilder.ts:41 (opens in a new tab)
Methods
count
▸ count(): Promise<number>
Gets the total count of matching entities.
Returns
Promise<number>
Total count
Example
const totalDesserts = await Recipe.query(perspective)
.where({ category: "Dessert" })
.count();Defined in
model/ModelQueryBuilder.ts:430 (opens in a new tab)
countSubscribe
▸ countSubscribe(callback): Promise<number>
Subscribes to count updates for matching entities.
This method:
- Creates and initializes a SurrealDB live query subscription for the count (default)
- Sets up the callback to process future count updates
- Returns the initial count immediately
Remember to call dispose() when you're done with the subscription to clean up resources.
Parameters
| Name | Type | Description |
|---|---|---|
callback | (count: number) => void | Function to call with updated count |
Returns
Promise<number>
Initial count
Example
const builder = Recipe.query(perspective)
.where({ status: "active" });
const initialCount = await builder.countSubscribe(count => {
console.log("Active items:", count);
});
// When done with subscription:
builder.dispose();Remarks
By default, this uses SurrealDB live queries for real-time updates.
Prolog subscriptions remain available via .useSurrealDB(false).
Defined in
model/ModelQueryBuilder.ts:477 (opens in a new tab)
dispose
▸ dispose(): void
Disposes of the current subscription if one exists.
This method:
- Stops the keepalive signals to the subscription
- Unsubscribes from GraphQL subscription updates
- Notifies the backend to clean up subscription resources
- Clears the subscription reference
You should call this method when you're done with a subscription to prevent memory leaks and ensure proper cleanup.
Returns
void
Defined in
model/ModelQueryBuilder.ts:61 (opens in a new tab)
first
▸ first(): Promise<T>
Returns the first matching instance, or null if none match.
Internally sets limit: 1 and delegates to get().
Returns
Promise<T>
The first matching instance, or null
Example
const recipe = await Recipe.query(perspective)
.where({ name: "Pasta" })
.first();Defined in
model/ModelQueryBuilder.ts:334 (opens in a new tab)
get
▸ get(): Promise<T[]>
Executes the query once and returns the results.
Returns
Promise<T[]>
Array of matching entities
Example
const recipes = await Recipe.query(perspective)
.where({ category: "Dessert" })
.get();Defined in
model/ModelQueryBuilder.ts:305 (opens in a new tab)
include
▸ include(map): ModelQueryBuilder<T>
Specifies which relations to eager-load (hydrate into model instances).
Without include, relation fields contain raw expression URIs (strings).
With include, the URIs are resolved into fully-hydrated model instances
using the target class declared in the relation decorator.
Supports nested includes for multi-level eager loading.
Parameters
| Name | Type | Description |
|---|---|---|
map | IncludeMap | An IncludeMap describing which relations to hydrate |
Returns
The query builder for chaining
Example
// Hydrate comments one level deep
const recipes = await Recipe.query(perspective)
.include({ comments: true })
.run();
// recipe.comments is now Comment[] (model instances), not string[]
// Nested: hydrate comments AND each comment's author
const recipes = await Recipe.query(perspective)
.include({ comments: { author: true } })
.run();Defined in
model/ModelQueryBuilder.ts:253 (opens in a new tab)
limit
▸ limit(limit): ModelQueryBuilder<T>
Sets the maximum number of results to return.
Parameters
| Name | Type | Description |
|---|---|---|
limit | number | Maximum number of results |
Returns
The query builder for chaining
Example
.limit(10)Defined in
model/ModelQueryBuilder.ts:116 (opens in a new tab)
offset
▸ offset(offset): ModelQueryBuilder<T>
Sets the number of results to skip.
Parameters
| Name | Type | Description |
|---|---|---|
offset | number | Number of results to skip |
Returns
The query builder for chaining
Example
.offset(20) // Skip first 20 resultsDefined in
model/ModelQueryBuilder.ts:132 (opens in a new tab)
order
▸ order(orderBy): ModelQueryBuilder<T>
Sets the order for the query results.
Parameters
| Name | Type | Description |
|---|---|---|
orderBy | Order | The ordering criteria |
Returns
The query builder for chaining
Example
.order({ createdAt: "DESC" })Defined in
model/ModelQueryBuilder.ts:100 (opens in a new tab)
overrideModelClassName
▸ overrideModelClassName(className): ModelQueryBuilder<T>
Parameters
| Name | Type |
|---|---|
className | string |
Returns
Defined in
model/ModelQueryBuilder.ts:258 (opens in a new tab)
paginate
▸ paginate(pageSize, pageNumber): Promise<PaginationResult<T>>
Gets a page of results with pagination metadata.
Parameters
| Name | Type | Description |
|---|---|---|
pageSize | number | Number of items per page |
pageNumber | number | Which page to retrieve (1-based) |
Returns
Promise<PaginationResult<T>>
Paginated results with metadata
Example
const page = await Recipe.query(perspective)
.where({ category: "Main" })
.paginate(10, 1);
console.log(`Page ${page.pageNumber}, ${page.results.length} of ${page.totalCount}`);Defined in
model/ModelQueryBuilder.ts:529 (opens in a new tab)
paginateSubscribe
▸ paginateSubscribe(pageSize, pageNumber, callback): Promise<PaginationResult<T>>
Subscribes to paginated results updates.
This method:
- Creates and initializes a SurrealDB live query subscription for the paginated results (default)
- Sets up the callback to process future page updates
- Returns the initial page immediately
Remember to call dispose() when you're done with the subscription to clean up resources.
Parameters
| Name | Type | Description |
|---|---|---|
pageSize | number | Number of items per page |
pageNumber | number | Which page to retrieve (1-based) |
callback | (results: PaginationResult<T>) => void | Function to call with updated pagination results |
Returns
Promise<PaginationResult<T>>
Initial pagination results
Example
const builder = Recipe.query(perspective)
.where({ category: "Main" });
const initialPage = await builder.paginateSubscribe(10, 1, page => {
console.log("Updated page:", page.results);
});
// When done with subscription:
builder.dispose();Remarks
By default, this uses SurrealDB live queries for real-time updates.
Prolog subscriptions remain available via .useSurrealDB(false).
Defined in
model/ModelQueryBuilder.ts:577 (opens in a new tab)
parent
▸ parent(idOrInstance, modelOrPredicate?, options?): ModelQueryBuilder<T>
Scopes the query to instances linked from a parent.
The predicate is resolved in order of precedence:
- Instance only — the parent's constructor is used as the model
class; its relation metadata is scanned for a relation whose
target()matches the queried model class. - Instance + options with
field— direct field-name lookup on the parent model's relation metadata (disambiguates when a parent has multiple relations targeting the same child class). - String id + model class — same metadata scan (or field lookup if
options include
field). - String id + string predicate — raw escape hatch, no metadata lookup.
Passing a plain string id with no second argument throws because the predicate cannot be resolved without a model class.
Parameters
| Name | Type | Description |
|---|---|---|
idOrInstance | string | Ad4mModel | The parent's expression URI or an Ad4mModel instance |
modelOrPredicate? | string | typeof Ad4mModel | { field: string } | A model class (predicate auto-resolved) or a raw predicate string |
options? | Object | Optional settings: field for direct relation-name lookup |
options.field? | string | - |
Returns
The query builder for chaining
Example
// Instance — predicate auto-resolved from Cookbook's @HasMany(() => Recipe)
Recipe.query(perspective).parent(cookbook).get();
// Instance + field — disambiguate when parent has multiple relations to same child
Recipe.query(perspective).parent(cookbook, { field: "recipes" }).get();
// String id + model class
Recipe.query(perspective).parent(cookbookId, Cookbook).get();
// String id + model class + field
Recipe.query(perspective).parent(cookbookId, Cookbook, { field: "recipes" }).get();
// String id + raw predicate (escape hatch)
Recipe.query(perspective).parent(cookbookId, "cookbook://recipe").get();Defined in
model/ModelQueryBuilder.ts:177 (opens in a new tab)
properties
▸ properties(properties): ModelQueryBuilder<T>
Specifies which properties to include in the results.
Parameters
| Name | Type | Description |
|---|---|---|
properties | string[] | Array of property names to include |
Returns
The query builder for chaining
Example
.properties(["name", "description", "rating"])Defined in
model/ModelQueryBuilder.ts:222 (opens in a new tab)
subscribe
▸ subscribe(callback): Promise<T[]>
Subscribes to the query and receives updates when results change.
This method:
- Creates and initializes a SurrealDB live query subscription (default)
- Sets up the callback to process future updates
- Returns the initial results immediately
Remember to call dispose() when you're done with the subscription to clean up resources.
Parameters
| Name | Type | Description |
|---|---|---|
callback | (results: T[]) => void | Function to call with updated results |
Returns
Promise<T[]>
Initial results array
Example
const builder = Recipe.query(perspective)
.where({ status: "cooking" });
const initialRecipes = await builder.subscribe(recipes => {
console.log("Updated recipes:", recipes);
});
// When done with subscription:
builder.dispose();Remarks
By default, this uses SurrealDB live queries for real-time updates.
Prolog subscriptions remain available via .useSurrealDB(false).
Defined in
model/ModelQueryBuilder.ts:371 (opens in a new tab)
useSurrealDB
▸ useSurrealDB(enabled?): ModelQueryBuilder<T>
Enables or disables SurrealDB query path.
Parameters
| Name | Type | Default value | Description |
|---|---|---|---|
enabled | boolean | true | Whether to use SurrealDB (default: true, 10-100x faster) or Prolog (legacy) |
Returns
The query builder for chaining
Example
// Use SurrealDB (default)
const recipes = await Recipe.query(perspective)
.where({ category: "Dessert" })
.useSurrealDB(true)
.get();
// Use Prolog (legacy)
const recipesProlog = await Recipe.query(perspective)
.where({ category: "Dessert" })
.useSurrealDB(false)
.get();Remarks
Note: Subscriptions (subscribe(), countSubscribe(), paginateSubscribe()) default to SurrealDB live queries if useSurrealDB(true) is set (default).
Defined in
model/ModelQueryBuilder.ts:288 (opens in a new tab)
where
▸ where(conditions): ModelQueryBuilder<T>
Adds where conditions to the query.
Parameters
| Name | Type | Description |
|---|---|---|
conditions | Where | The conditions to filter by |
Returns
The query builder for chaining
Example
.where({
category: "Dessert",
rating: { gt: 4 },
tags: ["vegan", "quick"],
published: true
})