ServerQueryBuilder

source

Server-side query builder.

Queries are written by starting from a context and a model, and applying join, filter, and sort clauses to refine the row selection. Then, the query is materialised into a View, at which point it is evaluated.

The most basic form of query just selects rows of a model:

from(Account).select()       // get all rows
from(Account).selectFirst()  // get the first row
from(Account).selectCount()  // get the total number of rows

Left joins can be done on foreign key fields.

from(AccountUser).leftJoin("Account").select()

Joins may also be done upon joined foreign key fields.

from(AccountUser)
  .leftJoin("Account")
  .leftJoin("Account.ParentAccount")
  .select()

Filtering and sorting can be done using the where() and orderBy() clauses.

from(AccountUser)
  .leftJoin("Account")
  .where(ne("Account.Deleted", true))
  .orderBy(asc("Account.Name"))
  .select()

By default, queries exclude deleted records. To include deleted records, opt-in using the .includeDeleted() method:

from(Account)
  .includeDeleted()
  .select()

Constructors

new ServerQueryBuilder<T extends Model<string, T> = Model<string>, F extends string | number | symbol = keyof T, LeftJoined = never, InnerJoined = never>(context: Context, sourceModel: ModelType<T>): ServerQueryBuildersource

Properties

readonlycontext: Contextsource

filter: FilterPredicate[]source

inherited from Query.filter

Filter predicates to reduce the resultset. These can refer to joined fields.

joins: JoinSpec[]source

inherited from Query.joins

Join specifications for adding columns from other models.

readonlymodel: ModelType<T>source

inherited from Query.model

The primary source model for the query.

selectedFields: keyof T[]source

sort: SortPredicate[]source

inherited from Query.sort

Sort predicates to order the resultset. These can refer to joined fields.

staticcookInputs: booleansource

Whether or not to preparse filter predicates.

This is used by the websocket-server REPL, to allow predicates to be entered in a more convenient fashion (e.g. using strings instead of fully qualified enums). This adds some overhead, so it is not enabled all the time.

Within this library we have no way of knowing whether or not we are executing within a REPL context, so we have the REPL server set this flag while evaluating user input.

Methods

Static methods

staticfromContextAndModel<T extends Model<string, T>>(context: Context, model: ModelType<T>): ServerQueryBuildersource

For internal use. Use from instead.

staticfromContextAndQuery<T extends Model<string, T>>(context: Context, query: Query): ServerQueryBuildersource

For internal use. Use from instead.

staticfromExistingView<T extends Model<string, T>>(view: View): ServerQueryBuildersource

For internal use. Use from instead.

Instance methods

[custom](): Pagesource

all(): T[]source

Executes the query and returns the resultset as an array.

get(id: Id<T>): undefined | Tsource

Fetch a single record using its primary key.

innerJoin<FKs extends Exclude<ForeignKeyIn<T>, InnerJoined>[]>(foreignKeyFields: FKs): ServerQueryBuildersource

Nominates the foreign key fields upon which to perform a inner join. Multiple foreign key fields may be specified in a single innerJoin() call. If joining on joined fields, each stage of the join must be a separate call. For example:

from(Foo).innerJoin("Bar", "Baz").innerJoin("Baz.Luhrmann")

innerJoinOnPredicates<U extends Model<string, U>, AsName extends string>(rightQuery: ServerQueryBuilder, asName: AsName, joinPredicates: ExactJoinPredicate[]): ServerQueryBuildersource

Nominates a second query upon which to perform an inner join. The first argument is the query; the second argument is the name with which to prefix the joined fields; the remaining arguments are the boolean predicates upon which to conduct the join. For example:

from(Model.SecurityValues)
  .innerJoinOnPredicates(
    from(Model.Security),
    "ParentSecurity",
    eq("SecurityValues.Security", "ParentSecurity.Id"),
  )

The join performed is an inner join. Only the first of each matching tuple will be selected, so as to preserve the uniqueness of the key field on the left-hand side. To control which record is matched, use filter and/or sort clauses on the right-hand query. For example:

from(Model.SecurityValues)
  .innerJoinOnPredicates(
    from(Model.Security)
      .where(contains("Label", "ABC-"))
      .orderBy(asc("Issuer")),
    "ParentSecurity",
    eq("SecurityValues.Security", "ParentSecurity.Id"),
  )

This is the generic form of inner join. If the join is on a foreign key, the simpler form .innerJoin("ForeignField") should be used instead.

leftJoin<FKs extends Exclude<ForeignKeyIn<T>, LeftJoined>[]>(foreignKeyFields: FKs): ServerQueryBuildersource

Nominates the foreign key fields upon which to perform a left equijoin. Multiple foreign key fields may be specified in a single leftJoin() call. If joining on joined fields, each stage of the join must be a separate call. For example:

from(Foo).leftJoin("Bar", "Baz").leftJoin("Baz.Luhrmann")

leftJoinOnPredicates<U extends Model<string, U>, AsName extends string>(rightQuery: ServerQueryBuilder, asName: AsName, joinPredicates: ExactJoinPredicate[]): ServerQueryBuildersource

Nominates a second query upon which to perform a left outer join. The first argument is the query; the second argument is the name with which to prefix the joined fields; the remaining arguments are the boolean predicates upon which to conduct the join. For example:

from(SecurityValues)
  .leftJoinOnPredicates(
    from(Model.Security),
    "ParentSecurity",
    eq("SecurityValues.Security", "ParentSecurity.Id"),
  )

The join performed is a left outer join, but only the first matching record from the right-hand side will be selected, so as to preserve the uniqueness of the key field on the left-hand side. To control which record is matched, use filter and/or sort clauses on the right-hand query. For example:

from(SecurityValues)
  .leftJoinOnPredicates(
    from(Security)
      .where(contains("Label", "ABC-"))
      .orderBy(asc("Issuer")),
    "ParentSecurity",
    eq("SecurityValues.Security", "ParentSecurity.Id"),
  )

This is the generic form of left join. If the join is on a foreign key, the simpler form .leftJoin("ForeignField") should be used instead.

map<U>(transformFn: Function): U[]source

Executes the query and returns an array constructed by applying the given transformation function to each record of the resultset.

orderBy(predicates: undefined | SortPredicate<T>[]): ServerQueryBuildersource

Nominates the order by which to sort the resultset. The ordering consists of one or more sort predicates. For example:

from(Account).orderBy(desc("OpenDate"), asc("Name"))

select<Fs extends keyof T[]>(fields: Fs): ServerQueryBuildersource

Selects which fields to include in the resultset.

selectCount(): numbersource

Returns the total number of records in the resultset.

selectFirst(): undefined | Tsource

Returns the first record in the resultset.

toMetadata(): QueryReflectionMetadatasource

Returns the reflection metadata for this query.

toPersistentView(): Handlesource

Materialises this query into a persistent Handle to a live View.

toView(): Viewsource

Materialises this query into a live updating View.

useSlice(slice: Slice): Pagesource

Returns a live Page of the resultset.

useSlice(offset: number, count: number): Pagesource

where(predicates: FilterPredicate[]): ServerQueryBuildersource

Sets the criteria by which to filter the resultset. The filter consists of one or more filter predicates. For example:

from(Account).where(eq("AccountType", AccountType.Issuer))
from(Account).where(not(isNull("ClosedDate")))

Conjunctions may be created by nesting predicates such as all, any, and not. There is (currently) no limit to the level of nesting permitted, although very complex expressions should be avoided.

whereIf<V>(maybeValue: undefined | V, receiver: Function): ServerQueryBuildersource

Conditionally adds filter criteria. The second argument must be a function that accepts a value and returns a filter predicate. If the first argument is not undefined, its value is passed to the second argument. This is useful for adding conditional clauses without breaking out of the builder chain. For example:

from(AuctionAccount)
  .where(eq("Auction", auctionId))
  .whereIf(accountId, accountId => eq("Account", accountId))

This filters the AuctionAccount model by the Auction field, and then also by Account field if the value of accountId is not undefined.

Inherited methods

as<U extends Model<string, U>>(): Querysource

inherited from Query.as

getFromClause(): stringsource

inherited from Query.getFromClause

getJoinClauses(): string[]source

inherited from Query.getJoinClauses

getOrderByClauses(): string[]source

inherited from Query.getOrderByClauses

getWhereClauses(): string[]source

inherited from Query.getWhereClauses

toHash(): QueryHashsource

inherited from Query.toHash

toJSON(): objectsource

inherited from Query.toJSON

toString(): stringsource

inherited from Query.toString

staticapplyFieldGuards<T>(target: AbstractCtor<T>, item: any, tracer: Tracer): Maybe<T>source

inherited from Query.applyFieldGuards

staticisModelType(value: any): undefined | ModelType<Model<string>>source

inherited from Query.isModelType

staticvalidate<T extends ValidatableType<T>>(this: AbstractCtor<T> & CanHaveValidateHook<T>, item: any, tracer: Tracer = ...): Maybe<T>source

inherited from Query.validate

staticvalidateHook<K extends keyof Query<Model<string>>>(field: K, item: Query, tracer: Tracer): undefined | Maybe<Query<Model<string>>[K]>source

inherited from Query.validateHook

staticwithFields<T extends FieldDict>(fields: T): Validatable<MaterialisedType<T>> & Ctor<MaterialisedType<T>>source

inherited from Query.withFields