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:
parent
f7d0eb428a
commit
081177aebf
@ -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
|
||||
|
@ -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'],
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user