feat: add ability to specify whether null values should be put at the beginning or the end of the result set when sorting (#296)

This commit is contained in:
Elbarae Rguig 2022-08-20 23:25:48 +01:00 committed by GitHub
parent f7d0eb428a
commit 081177aebf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 2 deletions

View File

@ -124,6 +124,7 @@ export class CatsService {
public findAll(query: PaginateQuery): Promise<Paginated<CatEntity>> {
return paginate(query, this.catsRepository, {
sortableColumns: ['id', 'name', 'color', 'age'],
nullSort: 'last',
searchableColumns: ['name', 'color', 'age'],
defaultSortBy: [['id', 'DESC']],
filterableColumns: {
@ -154,6 +155,13 @@ const paginateConfig: PaginateConfig<CatEntity> {
* Description: These are the columns that are valid to be sorted by.
*/
sortableColumns: ['id', 'name', 'color'],
/**
* Required: false
* Type: 'first' | 'last'
* Default: 'last'
* Description: Define whether to put null values at the beginning or end of the result set.
*/
nullSort: 'last,
/**
* Required: false

View File

@ -196,6 +196,22 @@ describe('paginate', () => {
expect(result.data).toStrictEqual(cats.slice(0).reverse())
})
it('should put null values last when sorting', async () => {
const config: PaginateConfig<CatEntity> = {
sortableColumns: ['age', 'createdAt'],
nullSort: 'last',
defaultSortBy: [['age', 'DESC']],
}
const query: PaginateQuery = {
path: '',
}
const result = await paginate<CatEntity>(query, catRepo, config)
expect(result.meta.sortBy).toStrictEqual([['age', 'DESC']])
expect(result.data).toStrictEqual(cats)
})
it('should sort result by multiple columns', async () => {
const config: PaginateConfig<CatEntity> = {
sortableColumns: ['name', 'color'],

View File

@ -46,6 +46,7 @@ export class Paginated<T> {
export interface PaginateConfig<T> {
relations?: RelationColumn<T>[]
sortableColumns: Column<T>[]
nullSort?: 'first' | 'last'
searchableColumns?: Column<T>[]
select?: Column<T>[]
maxLimit?: number
@ -172,6 +173,8 @@ export async function paginate<T>(
if (config.sortableColumns.length < 1) throw new ServiceUnavailableException()
const NULL_SORT = config.nullSort === 'last' ? 'NULLS LAST' : 'NULLS FIRST'
if (query.sortBy) {
for (const order of query.sortBy) {
if (isEntityKey(config.sortableColumns, order[0]) && ['ASC', 'DESC'].includes(order[1])) {
@ -219,9 +222,9 @@ export async function paginate<T>(
for (const order of sortBy) {
if (order[0].split('.').length > 1) {
queryBuilder.addOrderBy(`${queryBuilder.alias}_${order[0]}`, order[1])
queryBuilder.addOrderBy(`${queryBuilder.alias}_${order[0]}`, order[1], NULL_SORT)
} else {
queryBuilder.addOrderBy(`${queryBuilder.alias}.${order[0]}`, order[1])
queryBuilder.addOrderBy(`${queryBuilder.alias}.${order[0]}`, order[1], NULL_SORT)
}
}