Allow sorting by calculation fields.
This commit is contained in:
parent
a1e55a5324
commit
964f8222ba
|
@ -273,6 +273,7 @@ class InternalBuilder {
|
|||
const col = parts.pop()!
|
||||
const schema = this.table.schema[col]
|
||||
let identifier = this.quotedIdentifier(field)
|
||||
|
||||
if (
|
||||
schema.type === FieldType.STRING ||
|
||||
schema.type === FieldType.LONGFORM ||
|
||||
|
@ -957,6 +958,13 @@ class InternalBuilder {
|
|||
return query
|
||||
}
|
||||
|
||||
isAggregateField(field: string): boolean {
|
||||
const found = this.query.resource?.aggregations?.find(
|
||||
aggregation => aggregation.name === field
|
||||
)
|
||||
return !!found
|
||||
}
|
||||
|
||||
addSorting(query: Knex.QueryBuilder): Knex.QueryBuilder {
|
||||
let { sort, resource } = this.query
|
||||
const primaryKey = this.table.primary
|
||||
|
@ -979,13 +987,17 @@ class InternalBuilder {
|
|||
nulls = value.direction === SortOrder.ASCENDING ? "first" : "last"
|
||||
}
|
||||
|
||||
let composite = `${aliased}.${key}`
|
||||
if (this.client === SqlClient.ORACLE) {
|
||||
query = query.orderByRaw(
|
||||
`${this.convertClobs(composite)} ${direction} nulls ${nulls}`
|
||||
)
|
||||
if (this.isAggregateField(key)) {
|
||||
query = query.orderBy(key, direction, nulls)
|
||||
} else {
|
||||
query = query.orderBy(composite, direction, nulls)
|
||||
let composite = `${aliased}.${key}`
|
||||
if (this.client === SqlClient.ORACLE) {
|
||||
query = query.orderByRaw(
|
||||
`${this.convertClobs(composite)} ${direction} nulls ${nulls}`
|
||||
)
|
||||
} else {
|
||||
query = query.orderBy(composite, direction, nulls)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3381,6 +3381,124 @@ describe.each([
|
|||
expect(rows).toHaveLength(1)
|
||||
expect(rows[0].sum).toEqual(3)
|
||||
})
|
||||
|
||||
it("should be able to sort by group by field", async () => {
|
||||
const table = await config.api.table.save(
|
||||
saveTableRequest({
|
||||
schema: {
|
||||
quantity: {
|
||||
type: FieldType.NUMBER,
|
||||
name: "quantity",
|
||||
},
|
||||
price: {
|
||||
type: FieldType.NUMBER,
|
||||
name: "price",
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
const view = await config.api.viewV2.create({
|
||||
tableId: table._id!,
|
||||
name: generator.guid(),
|
||||
type: ViewV2Type.CALCULATION,
|
||||
schema: {
|
||||
quantity: { visible: true },
|
||||
sum: {
|
||||
visible: true,
|
||||
calculationType: CalculationType.SUM,
|
||||
field: "price",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await config.api.row.bulkImport(table._id!, {
|
||||
rows: [
|
||||
{
|
||||
quantity: 1,
|
||||
price: 1,
|
||||
},
|
||||
{
|
||||
quantity: 1,
|
||||
price: 2,
|
||||
},
|
||||
{
|
||||
quantity: 2,
|
||||
price: 10,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const { rows } = await config.api.viewV2.search(view.id, {
|
||||
query: {},
|
||||
sort: "quantity",
|
||||
sortOrder: SortOrder.DESCENDING,
|
||||
})
|
||||
|
||||
expect(rows).toEqual([
|
||||
expect.objectContaining({ quantity: 2, sum: 10 }),
|
||||
expect.objectContaining({ quantity: 1, sum: 3 }),
|
||||
])
|
||||
})
|
||||
|
||||
it("should be able to sort by a calculation", async () => {
|
||||
const table = await config.api.table.save(
|
||||
saveTableRequest({
|
||||
schema: {
|
||||
quantity: {
|
||||
type: FieldType.NUMBER,
|
||||
name: "quantity",
|
||||
},
|
||||
price: {
|
||||
type: FieldType.NUMBER,
|
||||
name: "price",
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await config.api.row.bulkImport(table._id!, {
|
||||
rows: [
|
||||
{
|
||||
quantity: 1,
|
||||
price: 1,
|
||||
},
|
||||
{
|
||||
quantity: 1,
|
||||
price: 2,
|
||||
},
|
||||
{
|
||||
quantity: 2,
|
||||
price: 10,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const view = await config.api.viewV2.create({
|
||||
tableId: table._id!,
|
||||
name: generator.guid(),
|
||||
type: ViewV2Type.CALCULATION,
|
||||
schema: {
|
||||
quantity: { visible: true },
|
||||
sum: {
|
||||
visible: true,
|
||||
calculationType: CalculationType.SUM,
|
||||
field: "price",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { rows } = await config.api.viewV2.search(view.id, {
|
||||
query: {},
|
||||
sort: "sum",
|
||||
sortOrder: SortOrder.DESCENDING,
|
||||
})
|
||||
|
||||
expect(rows).toEqual([
|
||||
expect.objectContaining({ quantity: 2, sum: 10 }),
|
||||
expect.objectContaining({ quantity: 1, sum: 3 }),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
!isLucene &&
|
||||
|
|
|
@ -418,13 +418,26 @@ export async function search(
|
|||
|
||||
if (params.sort) {
|
||||
const sortField = table.schema[params.sort]
|
||||
const sortType =
|
||||
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
|
||||
request.sort = {
|
||||
[mapToUserColumn(sortField.name)]: {
|
||||
direction: params.sortOrder || SortOrder.ASCENDING,
|
||||
type: sortType as SortType,
|
||||
},
|
||||
const isAggregateField = aggregations.some(agg => agg.name === params.sort)
|
||||
|
||||
if (isAggregateField) {
|
||||
request.sort = {
|
||||
[params.sort]: {
|
||||
direction: params.sortOrder || SortOrder.ASCENDING,
|
||||
type: SortType.NUMBER,
|
||||
},
|
||||
}
|
||||
} else if (sortField) {
|
||||
const sortType =
|
||||
sortField.type === FieldType.NUMBER ? SortType.NUMBER : SortType.STRING
|
||||
request.sort = {
|
||||
[mapToUserColumn(sortField.name)]: {
|
||||
direction: params.sortOrder || SortOrder.ASCENDING,
|
||||
type: sortType as SortType,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Unable to sort by ${params.sort}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue