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>> {
|
public findAll(query: PaginateQuery): Promise<Paginated<CatEntity>> {
|
||||||
return paginate(query, this.catsRepository, {
|
return paginate(query, this.catsRepository, {
|
||||||
sortableColumns: ['id', 'name', 'color', 'age'],
|
sortableColumns: ['id', 'name', 'color', 'age'],
|
||||||
|
nullSort: 'last',
|
||||||
searchableColumns: ['name', 'color', 'age'],
|
searchableColumns: ['name', 'color', 'age'],
|
||||||
defaultSortBy: [['id', 'DESC']],
|
defaultSortBy: [['id', 'DESC']],
|
||||||
filterableColumns: {
|
filterableColumns: {
|
||||||
@ -154,6 +155,13 @@ const paginateConfig: PaginateConfig<CatEntity> {
|
|||||||
* Description: These are the columns that are valid to be sorted by.
|
* Description: These are the columns that are valid to be sorted by.
|
||||||
*/
|
*/
|
||||||
sortableColumns: ['id', 'name', 'color'],
|
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
|
* Required: false
|
||||||
|
@ -196,6 +196,22 @@ describe('paginate', () => {
|
|||||||
expect(result.data).toStrictEqual(cats.slice(0).reverse())
|
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 () => {
|
it('should sort result by multiple columns', async () => {
|
||||||
const config: PaginateConfig<CatEntity> = {
|
const config: PaginateConfig<CatEntity> = {
|
||||||
sortableColumns: ['name', 'color'],
|
sortableColumns: ['name', 'color'],
|
||||||
|
@ -46,6 +46,7 @@ export class Paginated<T> {
|
|||||||
export interface PaginateConfig<T> {
|
export interface PaginateConfig<T> {
|
||||||
relations?: RelationColumn<T>[]
|
relations?: RelationColumn<T>[]
|
||||||
sortableColumns: Column<T>[]
|
sortableColumns: Column<T>[]
|
||||||
|
nullSort?: 'first' | 'last'
|
||||||
searchableColumns?: Column<T>[]
|
searchableColumns?: Column<T>[]
|
||||||
select?: Column<T>[]
|
select?: Column<T>[]
|
||||||
maxLimit?: number
|
maxLimit?: number
|
||||||
@ -172,6 +173,8 @@ export async function paginate<T>(
|
|||||||
|
|
||||||
if (config.sortableColumns.length < 1) throw new ServiceUnavailableException()
|
if (config.sortableColumns.length < 1) throw new ServiceUnavailableException()
|
||||||
|
|
||||||
|
const NULL_SORT = config.nullSort === 'last' ? 'NULLS LAST' : 'NULLS FIRST'
|
||||||
|
|
||||||
if (query.sortBy) {
|
if (query.sortBy) {
|
||||||
for (const order of query.sortBy) {
|
for (const order of query.sortBy) {
|
||||||
if (isEntityKey(config.sortableColumns, order[0]) && ['ASC', 'DESC'].includes(order[1])) {
|
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) {
|
for (const order of sortBy) {
|
||||||
if (order[0].split('.').length > 1) {
|
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 {
|
} 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