diff --git a/src/orm/base_model/index.ts b/src/orm/base_model/index.ts index 1ef649b2..1a3430bd 100644 --- a/src/orm/base_model/index.ts +++ b/src/orm/base_model/index.ts @@ -721,6 +721,29 @@ class BaseModelImpl implements LucidRow { return this.query(options).where(key, value).firstOrFail() } + /** + * Find multiple models instance using a key/value pair + */ + // @ts-expect-error - Return type should be inferred when used in a model + static findManyBy(clause: Record, options?: ModelAdapterOptions) + // @ts-expect-error - Return type should be inferred when used in a model + static findManyBy(key: string, value: any[], options?: ModelAdapterOptions) + static findManyBy( + key: string | Record, + value?: any[] | ModelAdapterOptions, + options?: ModelAdapterOptions + ) { + if (typeof key === 'object') { + return this.query(value as ModelAdapterOptions).where(key) + } + + if (value === undefined) { + throw new Exception('"findManyBy" expects a value. Received undefined') + } + + return this.query(options).where(key, value) + } + /** * Same as `query().first()` */ diff --git a/src/types/model.ts b/src/types/model.ts index 65efb4f6..f2236352 100644 --- a/src/types/model.ts +++ b/src/types/model.ts @@ -995,6 +995,24 @@ export interface LucidModel { options?: ModelAdapterOptions ): Promise> + /** + * Find multiple models instance using a key/value pair + * + */ + findManyBy( + clause: Record, + options?: ModelAdapterOptions + ): Promise[]> + + /** + * Find multiple models instance using a key/value pair + */ + findManyBy( + key: string, + value: any[], + options?: ModelAdapterOptions + ): Promise[]> + /** * Same as `query().first()` */ diff --git a/test/orm/base_model.spec.ts b/test/orm/base_model.spec.ts index 54ee7bab..67796f1b 100644 --- a/test/orm/base_model.spec.ts +++ b/test/orm/base_model.spec.ts @@ -3780,6 +3780,66 @@ test.group('Base Model | fetch', (group) => { assert.equal(users[1].$primaryKeyValue, 1) }) + test('find many using a clause', async ({ fs, assert }) => { + const app = new AppFactory().create(fs.baseUrl, () => {}) + await app.init() + const db = getDb() + const adapter = ormAdapter(db) + + const BaseModel = getBaseModel(adapter) + + class User extends BaseModel { + @column({ isPrimary: true }) + declare id: number + + @column() + declare username: string + + @column() + declare email: string + } + + await db + .insertQuery() + .table('users') + .multiInsert([{ username: 'virk' }, { username: 'nikk' }]) + + const users = await User.findManyBy({ points: 0 }) + assert.lengthOf(users, 2) + assert.equal(users[0].$primaryKeyValue, 1) + assert.equal(users[1].$primaryKeyValue, 2) + }) + + test('find many using a key/value pair', async ({ fs, assert }) => { + const app = new AppFactory().create(fs.baseUrl, () => {}) + await app.init() + const db = getDb() + const adapter = ormAdapter(db) + + const BaseModel = getBaseModel(adapter) + + class User extends BaseModel { + @column({ isPrimary: true }) + declare id: number + + @column() + declare username: string + + @column() + declare email: string + } + + await db + .insertQuery() + .table('users') + .multiInsert([{ username: 'virk' }, { username: 'nikk' }]) + + const users = await User.findManyBy('points', 0) + assert.lengthOf(users, 2) + assert.equal(users[0].$primaryKeyValue, 1) + assert.equal(users[1].$primaryKeyValue, 2) + }) + test('return the existing row when search criteria matches', async ({ fs, assert }) => { const app = new AppFactory().create(fs.baseUrl, () => {}) await app.init()