@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
- countSparql
- countSubscribe
- countSubscribeNow
- countSubscribeSparql
- deepQuery
- dispose
- executeSparqlQuery
- first
- get
- getSparql
- include
- includeUnverified
- limit
- linkStatus
- links
- offset
- order
- overrideModelClassName
- paginate
- paginateSparql
- paginateSubscribe
- paginateSubscribeNow
- paginateSubscribeSparql
- parent
- properties
- serialize
- subscribe
- subscribeNow
- subscribeSparql
- 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
core/src/model/ModelQueryBuilder.ts:45 (opens in a new tab)
Properties
ctor
• Private ctor: typeof Ad4mModel
Defined in
core/src/model/ModelQueryBuilder.ts:40 (opens in a new tab)
currentSubscription
• Private Optional currentSubscription: Object
Type declaration
| Name | Type |
|---|---|
dispose | () => Promise<void> |
Defined in
core/src/model/ModelQueryBuilder.ts:41 (opens in a new tab)
modelClassName
• Private modelClassName: string = null
Defined in
core/src/model/ModelQueryBuilder.ts:39 (opens in a new tab)
perspective
• Private perspective: PerspectiveProxy
Defined in
core/src/model/ModelQueryBuilder.ts:37 (opens in a new tab)
queryParams
• Private queryParams: Query = {}
Defined in
core/src/model/ModelQueryBuilder.ts:38 (opens in a new tab)
subscriptionChain
• Private subscriptionChain: Promise<void>
Tail of the subscribe/dispose chain; see serialize().
Defined in
core/src/model/ModelQueryBuilder.ts:43 (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
core/src/model/ModelQueryBuilder.ts:580 (opens in a new tab)
countSparql
▸ countSparql(): Promise<number>
Gets the total count of matching entities using SPARQL. Delegates to count().
Returns
Promise<number>
Defined in
core/src/model/ModelQueryBuilder.ts:589 (opens in a new tab)
countSubscribe
▸ countSubscribe(callback): Promise<number>
Subscribes to count updates for matching entities.
This method:
- Creates and initializes a SPARQL 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();Defined in
core/src/model/ModelQueryBuilder.ts:621 (opens in a new tab)
countSubscribeNow
▸ Private countSubscribeNow(callback): Promise<number>
Parameters
| Name | Type |
|---|---|
callback | (count: number) => void |
Returns
Promise<number>
Defined in
core/src/model/ModelQueryBuilder.ts:625 (opens in a new tab)
countSubscribeSparql
▸ countSubscribeSparql(callback): Promise<number>
Subscribes to count updates using SPARQL.
Parameters
| Name | Type |
|---|---|
callback | (count: number) => void |
Returns
Promise<number>
Deprecated
Use countSubscribe() instead — now routes through Rust model subscription.
Defined in
core/src/model/ModelQueryBuilder.ts:708 (opens in a new tab)
deepQuery
▸ deepQuery(enabled?): ModelQueryBuilder<T>
Controls whether SPARQL property getters are evaluated during hydration.
By default, collection queries evaluate property getters (deepQuery=true).
Call .deepQuery(false) to skip getter evaluation for performance.
Parameters
| Name | Type | Default value | Description |
|---|---|---|---|
enabled | boolean | true | Whether to evaluate property getters (default: true) |
Returns
The query builder for chaining
Example
const messages = await Message.query(perspective)
.parent(channel)
.deepQuery(false) // skip property getters for performance
.limit(30)
.get();Defined in
core/src/model/ModelQueryBuilder.ts:285 (opens in a new tab)
dispose
▸ dispose(): Promise<void>
Disposes of the current subscription if one exists.
This method:
- Stops the keepalive signals to the subscription
- Unsubscribes from subscription updates
- Notifies the backend to clean up subscription resources
- Clears the subscription reference
Steps 1, 2 and 4 happen synchronously, so builder.dispose() without
await is still a complete local cleanup. The returned promise resolves
once the executor has released this subscriber's hold on the subscription
(it never rejects). The executor shares one subscription between all
subscribers of the same query and only drops it when the last one
disposes, so disposing here does not interrupt another builder's updates.
You should call this method when you're done with a subscription to prevent memory leaks and ensure proper cleanup.
Returns
Promise<void>
Defined in
core/src/model/ModelQueryBuilder.ts:70 (opens in a new tab)
executeSparqlQuery
▸ Private executeSparqlQuery(): Promise<T[]>
Shared query execution logic — routes through the executor-side modelQuery endpoint.
Returns
Promise<T[]>
Defined in
core/src/model/ModelQueryBuilder.ts:390 (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
core/src/model/ModelQueryBuilder.ts:409 (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
core/src/model/ModelQueryBuilder.ts:376 (opens in a new tab)
getSparql
▸ getSparql(): Promise<T[]>
Executes the query once using SPARQL and returns the results.
Returns
Promise<T[]>
Defined in
core/src/model/ModelQueryBuilder.ts:383 (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 | TypedIncludeMap<T> | 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
core/src/model/ModelQueryBuilder.ts:354 (opens in a new tab)
includeUnverified
▸ includeUnverified(enabled?): ModelQueryBuilder<T>
Also hydrate from links whose signature did not verify.
Off by default: the executor withholds unverified links. Turn it on only to display an unverified claim, never for data you act on. See includeUnverified.
Parameters
| Name | Type | Default value | Description |
|---|---|---|---|
enabled | boolean | true | Whether to include unverified links (default: true) |
Returns
The query builder for chaining
Defined in
core/src/model/ModelQueryBuilder.ts:323 (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
core/src/model/ModelQueryBuilder.ts:138 (opens in a new tab)
linkStatus
▸ linkStatus(status): ModelQueryBuilder<T>
Reads instances as they exist in links of one status only.
'shared' leaves out every Local link, both from the values returned and
from what decides which instances are returned. Use it when the data is
shown to another user. 'local' is the converse: it returns only
instances flagged in a Local link, so a Local note on a card flagged only
in a Shared link is read without linkStatus, not under 'local'.
See linkStatus.
Parameters
| Name | Type | Description |
|---|---|---|
status | LinkStatus | 'shared' or 'local' |
Returns
The query builder for chaining
Example
const cards = await Card.query(perspective).linkStatus('shared').get();Defined in
core/src/model/ModelQueryBuilder.ts:308 (opens in a new tab)
links
▸ links(keys): ModelQueryBuilder<T>
Asks for the individual links behind each instance — author, timestamp
and proof per link — under instance.__links. See Query.links.
Parameters
| Name | Type | Description |
|---|---|---|
keys | string[] | Property / relation names, or absolute predicate IRIs |
Returns
The query builder for chaining
Example
const [post] = await Post.query(perspective).links(["comments"]).get();
post.__links!.comments.map((l) => l.timestamp); // when each comment was attachedDefined in
core/src/model/ModelQueryBuilder.ts:262 (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
core/src/model/ModelQueryBuilder.ts:154 (opens in a new tab)
order
▸ order(orderBy): ModelQueryBuilder<T>
Sets the order for the query results.
Parameters
| Name | Type | Description |
|---|---|---|
orderBy | TypedOrder<T> | The ordering criteria |
Returns
The query builder for chaining
Example
.order({ createdAt: "DESC" })Defined in
core/src/model/ModelQueryBuilder.ts:122 (opens in a new tab)
overrideModelClassName
▸ overrideModelClassName(className): ModelQueryBuilder<T>
Parameters
| Name | Type |
|---|---|
className | string |
Returns
Defined in
core/src/model/ModelQueryBuilder.ts:359 (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
core/src/model/ModelQueryBuilder.ts:727 (opens in a new tab)
paginateSparql
▸ paginateSparql(pageSize, pageNumber): Promise<PaginationResult<T>>
Gets a page of results using SPARQL. Delegates to paginate().
Parameters
| Name | Type |
|---|---|
pageSize | number |
pageNumber | number |
Returns
Promise<PaginationResult<T>>
Defined in
core/src/model/ModelQueryBuilder.ts:737 (opens in a new tab)
paginateSubscribe
▸ paginateSubscribe(pageSize, pageNumber, callback): Promise<PaginationResult<T>>
Subscribes to paginated results updates.
This method:
- Creates and initializes a SPARQL 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();Defined in
core/src/model/ModelQueryBuilder.ts:771 (opens in a new tab)
paginateSubscribeNow
▸ Private paginateSubscribeNow(pageSize, pageNumber, callback): Promise<PaginationResult<T>>
Parameters
| Name | Type |
|---|---|
pageSize | number |
pageNumber | number |
callback | (results: PaginationResult<T>) => void |
Returns
Promise<PaginationResult<T>>
Defined in
core/src/model/ModelQueryBuilder.ts:779 (opens in a new tab)
paginateSubscribeSparql
▸ paginateSubscribeSparql(pageSize, pageNumber, callback): Promise<PaginationResult<T>>
Subscribes to paginated results updates using SPARQL. Delegates to paginateSubscribe().
Parameters
| Name | Type |
|---|---|
pageSize | number |
pageNumber | number |
callback | (results: PaginationResult<T>) => void |
Returns
Promise<PaginationResult<T>>
Defined in
core/src/model/ModelQueryBuilder.ts:916 (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
core/src/model/ModelQueryBuilder.ts:199 (opens in a new tab)
properties
▸ properties(properties): ModelQueryBuilder<T>
Specifies which properties to include in the results.
Parameters
| Name | Type | Description |
|---|---|---|
properties | string[] | PropertyKeysOf<T>[] | Array of property names to include |
Returns
The query builder for chaining
Example
.properties(["name", "description", "rating"])Defined in
core/src/model/ModelQueryBuilder.ts:244 (opens in a new tab)
serialize
▸ Private serialize<R>(run): Promise<R>
Runs one subscribe variant after every earlier one on this builder has finished. Each variant disposes the previous subscription (awaiting the executor) and then registers its own; two overlapping calls would both find no current subscription, both register, and the builder could only ever dispose the last one. Serializing keeps exactly one subscription per builder.
Type parameters
| Name |
|---|
R |
Parameters
| Name | Type |
|---|---|
run | () => Promise<R> |
Returns
Promise<R>
Defined in
core/src/model/ModelQueryBuilder.ts:84 (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 SPARQL 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();Defined in
core/src/model/ModelQueryBuilder.ts:445 (opens in a new tab)
subscribeNow
▸ Private subscribeNow(callback): Promise<T[]>
Parameters
| Name | Type |
|---|---|
callback | (results: T[]) => void |
Returns
Promise<T[]>
Defined in
core/src/model/ModelQueryBuilder.ts:449 (opens in a new tab)
subscribeSparql
▸ subscribeSparql(callback): Promise<T[]>
Subscribes to the query and receives updates using SPARQL.
Parameters
| Name | Type |
|---|---|
callback | (results: T[]) => void |
Returns
Promise<T[]>
Deprecated
Use subscribe() instead — now routes through Rust model subscription.
Defined in
core/src/model/ModelQueryBuilder.ts:564 (opens in a new tab)
where
▸ where(conditions): ModelQueryBuilder<T>
Adds where conditions to the query.
Parameters
| Name | Type | Description |
|---|---|---|
conditions | TypedQueryWhere<T> | The conditions to filter by |
Returns
The query builder for chaining
Example
.where({
category: "Dessert",
rating: { gt: 4 },
tags: ["vegan", "quick"],
published: true
})Defined in
core/src/model/ModelQueryBuilder.ts:106 (opens in a new tab)