adonis-odm
Version:
A comprehensive MongoDB ODM for AdonisJS with Lucid-style API, type-safe relationships, embedded documents, and transaction support
246 lines • 8.39 kB
TypeScript
import { Collection, Document } from 'mongodb';
import { QueryOperator, QueryValue, SortDirection, PaginatedResult, ModelConstructor } from '../types/index.js';
import { BaseModel } from '../base_model/base_model.js';
import type { LoadRelationConstraint, EmbedRelationConstraint } from '../types/relationship_inference.js';
import type { MongoTransactionClient } from '../transaction_client.js';
/**
* SEAMLESS TYPE-SAFE MODEL QUERY BUILDER - Like AdonisJS Lucid!
*
* This enhanced query builder provides automatic type inference for relationships
* and seamless type safety without requiring any type assertions or extra steps.
*
* Key Features:
* - Automatic relationship name inference from model definitions
* - Type-safe load callbacks with proper IntelliSense
* - Compile-time error checking for invalid relationship names
* - Method chaining like AdonisJS Lucid
* - Bulk loading to prevent N+1 query problems
*/
export declare class ModelQueryBuilder<T extends Document = Document, TModel extends BaseModel = BaseModel> {
private collection;
private modelConstructor;
private whereBuilder;
private queryExecutor;
private queryUtils;
private loadRelations;
private embedRelations;
constructor(collection: Collection<T>, modelConstructor: ModelConstructor, transactionClient?: MongoTransactionClient);
/**
* Associate this query builder with a transaction
*/
useTransaction(trx: MongoTransactionClient): this;
/**
* Add a where condition
*/
where(field: string, value: QueryValue): this;
where(field: string, operator: QueryOperator, value: QueryValue): this;
/**
* Alias for where method
*/
andWhere(field: string, value: QueryValue): this;
andWhere(field: string, operator: QueryOperator, value: QueryValue): this;
/**
* Add a where not condition
*/
whereNot(field: string, value: QueryValue): this;
whereNot(field: string, operator: QueryOperator, value: QueryValue): this;
/**
* Alias for whereNot method
*/
andWhereNot(field: string, operatorOrValue: QueryOperator | QueryValue, value?: QueryValue): this;
/**
* Add an OR where condition
*/
orWhere(field: string, operatorOrValue: QueryOperator | QueryValue, value?: QueryValue): this;
/**
* Add an OR where not condition
*/
orWhereNot(field: string, operatorOrValue: QueryOperator | QueryValue, value?: QueryValue): this;
/**
* Add a where like condition (case-sensitive)
*/
whereLike(field: string, value: string): this;
/**
* Add a where ilike condition (case-insensitive)
*/
whereILike(field: string, value: string): this;
/**
* Add a where null condition
*/
whereNull(field: string): this;
/**
* Add an OR where null condition
*/
orWhereNull(field: string): this;
/**
* Add a where not null condition
*/
whereNotNull(field: string): this;
/**
* Add an OR where not null condition
*/
orWhereNotNull(field: string): this;
/**
* Add a where exists condition
*/
whereExists(field: string): this;
/**
* Add an OR where exists condition
*/
orWhereExists(field: string): this;
/**
* Add a where not exists condition
*/
whereNotExists(field: string): this;
/**
* Add an OR where not exists condition
*/
orWhereNotExists(field: string): this;
/**
* Add a where in condition
*/
whereIn(field: string, values: QueryValue[]): this;
/**
* Add an OR where in condition
*/
orWhereIn(field: string, values: QueryValue[]): this;
/**
* Add a where not in condition
*/
whereNotIn(field: string, values: QueryValue[]): this;
/**
* Add an OR where not in condition
*/
orWhereNotIn(field: string, values: QueryValue[]): this;
/**
* Add a where between condition
*/
whereBetween(field: string, range: [QueryValue, QueryValue]): this;
/**
* Add an OR where between condition
*/
orWhereBetween(field: string, range: [QueryValue, QueryValue]): this;
/**
* Add a where not between condition
*/
whereNotBetween(field: string, range: [QueryValue, QueryValue]): this;
/**
* Add an OR where not between condition
*/
orWhereNotBetween(field: string, range: [QueryValue, QueryValue]): this;
/**
* Add distinct clause
*/
distinct(field: string): this;
/**
* Add group by clause
*/
groupBy(...fields: string[]): this;
/**
* Add having clause (for aggregation)
*/
having(field: string, operatorOrValue: QueryOperator | QueryValue, value?: QueryValue): this;
/**
* Add order by clause
*/
orderBy(field: string, direction?: SortDirection): this;
/**
* Set limit
*/
limit(count: number): this;
/**
* Set skip/offset
*/
skip(count: number): this;
/**
* Alias for skip method
*/
offset(count: number): this;
/**
* Set pagination using page and perPage
*/
forPage(page: number, perPage: number): this;
/**
* Select specific fields
*/
select(fields: string[] | Record<string, 0 | 1>): this;
/**
* TYPE-SAFE LOAD METHOD - Eager Load Referenced Relationships!
*
* This method provides automatic type inference for REFERENCED relationship loading.
* The callback parameter is automatically typed based on the relationship being loaded.
* Only supports REFERENCED relationships (HasOne, HasMany, BelongsTo).
* Embedded relationships are excluded because they need to be "embedded" instead.
*
* Example usage:
* ```typescript
* const users = await User.query().load('profile', (profileQuery) => {
* profileQuery.where('isActive', true).orderBy('createdAt', 'desc')
* })
* ```
*
* @param relation - The REFERENCED relationship property name (with IntelliSense support)
* @param callback - Optional callback to modify the relationship query
*/
load<K extends LoadRelationConstraint<TModel>>(relation: K, callback?: (query: ModelQueryBuilder<any, BaseModel>) => void): this;
/**
* TYPE-SAFE EMBED METHOD - Query Embedded Documents Directly!
*
* This method provides automatic type inference for EMBEDDED document querying.
* The callback parameter is automatically typed based on the embedded relationship being queried.
* Only supports EMBEDDED relationships (EmbeddedSingle, EmbeddedMany).
* Referenced relationships are excluded because they need to be "loaded" instead.
*
* Example usage:
* ```typescript
* const users = await UserWithEnhancedEmbeddedProfile.query().embed('profiles', (profileQuery) => {
* profileQuery.where('age', '>', 25).orderBy('age', 'desc').limit(5)
* })
* ```
*
* @param relation - The EMBEDDED relationship property name (with IntelliSense support)
* @param callback - Optional callback to filter/paginate the embedded documents
*/
embed<K extends EmbedRelationConstraint<TModel>>(relation: K, callback?: (query: import('../embedded/embedded_query_builder.js').EmbeddedQueryBuilder<any>) => void): this;
/**
* Execute query and return first result
*/
first(): Promise<TModel | null>;
/**
* Execute query and return first result or throw exception
*/
firstOrFail(): Promise<TModel>;
/**
* Execute query and return all results
*/
all(): Promise<TModel[]>;
/**
* Execute query and return all results (alias for all)
*/
fetch(): Promise<TModel[]>;
/**
* Execute query and return paginated results
*/
paginate(page: number, perPage: number): Promise<PaginatedResult<TModel>>;
/**
* Count documents matching the query
*/
count(): Promise<number>;
/**
* Get array of IDs for matching documents
*/
ids(): Promise<any[]>;
/**
* Update documents matching the query
*/
update(updateData: Record<string, any>): Promise<number>;
/**
* Delete documents matching the query
*/
delete(): Promise<number>;
/**
* Clone the query builder
*/
clone(): ModelQueryBuilder<T, TModel>;
}
//# sourceMappingURL=model_query_builder.d.ts.map