feat: implement auto EagerLoads in library (#506)

This commit is contained in:
Manuel Nascimento 2023-03-01 05:02:13 -03:00 committed by GitHub
parent 1ea52d24da
commit 6193ea28df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 1 deletions

View File

@ -261,6 +261,46 @@ const paginateConfig: PaginateConfig<CatEntity> {
} }
``` ```
## Eager loading
Eager loading should work with typeorm's eager property out the box. Like so
```typescript
import { Entity, OneToMany } from 'typeorm';
@Entity()
export class CatEntity {
@PrimaryGeneratedColumn()
id: number
@Column('text')
name: string
@Column('text')
color: string
@Column('int')
age: number
@OneToMany(() => CatToyEntity, (catToy) => catToy.cat, {
eager: true,
})
toys: CatToyEntity[]
}
// service
class CatService {
constructor(private readonly catsRepository: Repository<CatEntity>) {}
public findAll(query: PaginateQuery): Promise<Paginated<CatEntity>> {
return paginate(query, this.catsRepository, {
sortableColumns: ['id', 'name', 'color', 'age'],
loadEagerRelations: true // set this property as true to enable the eager loading
})
}
}
```
## Usage with Query Builder ## Usage with Query Builder
You can paginate custom queries by passing on the query builder: You can paginate custom queries by passing on the query builder:

View File

@ -32,7 +32,9 @@ export class CatEntity {
@Column(() => SizeEmbed) @Column(() => SizeEmbed)
size: SizeEmbed size: SizeEmbed
@OneToMany(() => CatToyEntity, (catToy) => catToy.cat) @OneToMany(() => CatToyEntity, (catToy) => catToy.cat, {
eager: true,
})
toys: CatToyEntity[] toys: CatToyEntity[]
@OneToOne(() => CatHomeEntity, (catHome) => catHome.cat, { nullable: true }) @OneToOne(() => CatHomeEntity, (catHome) => catHome.cat, { nullable: true })

View File

@ -1981,4 +1981,24 @@ describe('paginate', () => {
expect(result.data.length).toBe(4) expect(result.data.length).toBe(4)
}) })
it('should return eager relations when set the property `loadEagerRelations` as true', async () => {
const config: PaginateConfig<CatEntity> = {
sortableColumns: ['id'],
defaultSortBy: [['id', 'ASC']],
loadEagerRelations: true,
searchableColumns: ['name'],
}
const query: PaginateQuery = {
path: '',
search: 'Garfield',
}
const result = await paginate<CatEntity>(query, catRepo, config)
expect(result.data[0].toys).toBeDefined()
expect(result.data[0].toys).toHaveLength(1)
})
}) })

View File

@ -5,6 +5,7 @@ import {
FindOptionsWhere, FindOptionsWhere,
FindOptionsRelations, FindOptionsRelations,
ObjectLiteral, ObjectLiteral,
FindOptionsUtils,
} from 'typeorm' } from 'typeorm'
import { PaginateQuery } from './decorator' import { PaginateQuery } from './decorator'
import { ServiceUnavailableException, Logger } from '@nestjs/common' import { ServiceUnavailableException, Logger } from '@nestjs/common'
@ -62,6 +63,7 @@ export interface PaginateConfig<T> {
filterableColumns?: { filterableColumns?: {
[key in Column<T>]?: (FilterOperator | FilterSuffix)[] [key in Column<T>]?: (FilterOperator | FilterSuffix)[]
} }
loadEagerRelations?: boolean
withDeleted?: boolean withDeleted?: boolean
relativePath?: boolean relativePath?: boolean
origin?: string origin?: string
@ -146,6 +148,12 @@ export async function paginate<T extends ObjectLiteral>(
const queryBuilder = repo instanceof Repository ? repo.createQueryBuilder('__root') : repo const queryBuilder = repo instanceof Repository ? repo.createQueryBuilder('__root') : repo
if (repo instanceof Repository && !config.relations && config.loadEagerRelations === true) {
if (!config.relations) {
FindOptionsUtils.joinEagerRelations(queryBuilder, queryBuilder.alias, repo.metadata)
}
}
if (isPaginated) { if (isPaginated) {
// Switch from take and skip to limit and offset // Switch from take and skip to limit and offset
// due to this problem https://github.com/typeorm/typeorm/issues/5670 // due to this problem https://github.com/typeorm/typeorm/issues/5670