Browse Source

Merge pull request #3007 from nocodb/fix/nested-filter-and-sort

fix: add filter and sort support on nested list data
pull/4083/head
աɨռɢӄաօռɢ 2 years ago committed by GitHub
parent
commit
d0f003d3f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts
  2. 2
      packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts
  3. 4
      packages/nocodb/tests/unit/rest/tests/tableRow.test.ts
  4. 4
      packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

38
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts

@ -369,7 +369,7 @@ class BaseModelSqlv2 {
async multipleHmList({ colId, ids }, args: { limit?; offset? } = {}) { async multipleHmList({ colId, ids }, args: { limit?; offset? } = {}) {
try { try {
const { where, ...rest } = this._getListArgs(args as any); const { where, sort, ...rest } = this._getListArgs(args as any);
// todo: get only required fields // todo: get only required fields
// const { cn } = this.hasManyRelations.find(({ tn }) => tn === child) || {}; // const { cn } = this.hasManyRelations.find(({ tn }) => tn === child) || {};
@ -393,6 +393,7 @@ class BaseModelSqlv2 {
const qb = this.dbDriver(childTable.table_name); const qb = this.dbDriver(childTable.table_name);
await childModel.selectObject({ qb }); await childModel.selectObject({ qb });
await this.applySortAndFilter({ table: childTable, where, qb, sort });
const childQb = this.dbDriver.queryBuilder().from( const childQb = this.dbDriver.queryBuilder().from(
this.dbDriver this.dbDriver
@ -440,6 +441,26 @@ class BaseModelSqlv2 {
} }
} }
private async applySortAndFilter({
table,
where,
qb,
sort,
}: {
table: Model;
where: string;
qb;
sort: string;
}) {
const childAliasColMap = await table.getAliasColObjMap();
const filter = extractFilterFromXwhere(where, childAliasColMap);
await conditionV2(filter, qb, this.dbDriver);
if (!sort) return;
const sortObj = extractSortsObject(sort, childAliasColMap);
if (sortObj) await sortV2(sortObj, qb, this.dbDriver);
}
async multipleHmListCount({ colId, ids }) { async multipleHmListCount({ colId, ids }) {
try { try {
// const { cn } = this.hasManyRelations.find(({ tn }) => tn === child) || {}; // const { cn } = this.hasManyRelations.find(({ tn }) => tn === child) || {};
@ -483,7 +504,7 @@ class BaseModelSqlv2 {
async hmList({ colId, id }, args: { limit?; offset? } = {}) { async hmList({ colId, id }, args: { limit?; offset? } = {}) {
try { try {
const { where, ...rest } = this._getListArgs(args as any); const { where, sort, ...rest } = this._getListArgs(args as any);
// todo: get only required fields // todo: get only required fields
const relColumn = (await this.model.getColumns()).find( const relColumn = (await this.model.getColumns()).find(
@ -505,6 +526,7 @@ class BaseModelSqlv2 {
await parentTable.getColumns(); await parentTable.getColumns();
const qb = this.dbDriver(childTable.table_name); const qb = this.dbDriver(childTable.table_name);
await this.applySortAndFilter({ table: childTable, where, qb, sort });
qb.whereIn( qb.whereIn(
chilCol.column_name, chilCol.column_name,
@ -576,7 +598,7 @@ class BaseModelSqlv2 {
{ colId, parentIds }, { colId, parentIds },
args: { limit?; offset? } = {} args: { limit?; offset? } = {}
) { ) {
const { where, ...rest } = this._getListArgs(args as any); const { where, sort, ...rest } = this._getListArgs(args as any);
const relColumn = (await this.model.getColumns()).find( const relColumn = (await this.model.getColumns()).find(
(c) => c.id === colId (c) => c.id === colId
); );
@ -603,6 +625,9 @@ class BaseModelSqlv2 {
const qb = this.dbDriver(rtn).join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`); const qb = this.dbDriver(rtn).join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`);
await childModel.selectObject({ qb }); await childModel.selectObject({ qb });
await this.applySortAndFilter({ table: childTable, where, qb, sort });
const finalQb = this.dbDriver.unionAll( const finalQb = this.dbDriver.unionAll(
parentIds.map((id) => { parentIds.map((id) => {
const query = qb const query = qb
@ -646,7 +671,7 @@ class BaseModelSqlv2 {
} }
public async mmList({ colId, parentId }, args: { limit?; offset? } = {}) { public async mmList({ colId, parentId }, args: { limit?; offset? } = {}) {
const { where, ...rest } = this._getListArgs(args as any); const { where, sort, ...rest } = this._getListArgs(args as any);
const relColumn = (await this.model.getColumns()).find( const relColumn = (await this.model.getColumns()).find(
(c) => c.id === colId (c) => c.id === colId
); );
@ -681,6 +706,9 @@ class BaseModelSqlv2 {
); );
await childModel.selectObject({ qb }); await childModel.selectObject({ qb });
await this.applySortAndFilter({ table: childTable, where, qb, sort });
// todo: sanitize // todo: sanitize
qb.limit(+rest?.limit || 25); qb.limit(+rest?.limit || 25);
qb.offset(+rest?.offset || 0); qb.offset(+rest?.offset || 0);
@ -1304,7 +1332,7 @@ class BaseModelSqlv2 {
); );
obj.offset = Math.max(+(args.offset || args.o) || 0, 0); obj.offset = Math.max(+(args.offset || args.o) || 0, 0);
obj.fields = args.fields || args.f || '*'; obj.fields = args.fields || args.f || '*';
obj.sort = args.sort || args.s || this.model.primaryKey?.[0]?.tn; obj.sort = args.sort || args.s;
return obj; return obj;
} }

2
packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts

@ -203,7 +203,7 @@ async function dataRead(req: Request, res: Response) {
await getAst({ model, query: req.query, view }), await getAst({ model, query: req.query, view }),
row, row,
{}, {},
{} req.query
) )
); );
} }

4
packages/nocodb/tests/unit/rest/tests/tableRow.test.ts

@ -730,7 +730,7 @@ function tableTest() {
); );
const nestedFields = { const nestedFields = {
'Rental List': ['RentalDate', 'ReturnDate'], 'Rental List': { fields : ['RentalDate', 'ReturnDate'] },
}; };
const nestedFilter = [ const nestedFilter = [
@ -805,7 +805,7 @@ function tableTest() {
ascResponse.body.list[0]['Rental List'] ascResponse.body.list[0]['Rental List']
); );
if ( if (
nestedRentalResponse.includes('RentalId') && nestedRentalResponse.includes('ReturnDate') &&
nestedRentalResponse.includes('RentalDate') && nestedRentalResponse.includes('RentalDate') &&
nestedRentalResponse.length === 2 nestedRentalResponse.length === 2
) { ) {

4
packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

@ -562,7 +562,7 @@ function viewRowTests() {
); );
const nestedFields = { const nestedFields = {
'Rental List': ['RentalDate', 'ReturnDate'], 'Rental List': { fields : ['RentalDate', 'ReturnDate'] },
}; };
const nestedFilter = [ const nestedFilter = [
@ -638,7 +638,7 @@ function viewRowTests() {
if ( if (
!( !(
nestedRentalResponse.includes('RentalId') && nestedRentalResponse.includes('ReturnDate') &&
nestedRentalResponse.includes('RentalDate') && nestedRentalResponse.includes('RentalDate') &&
nestedRentalResponse.length === 2 nestedRentalResponse.length === 2
) )

Loading…
Cancel
Save