UNPKG

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
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