fix: fixed filtering by entity field that is neither in relations and not loaded eagerly (#770)
This commit is contained in:
parent
098a21d225
commit
5f64f1ccbf
@ -1,5 +1,5 @@
|
|||||||
import { Repository, In, DataSource, TypeORMError, Like } from 'typeorm'
|
import { DataSource, In, Like, Repository, TypeORMError } from 'typeorm'
|
||||||
import { Paginated, paginate, PaginateConfig, NO_PAGINATION } from './paginate'
|
import { NO_PAGINATION, paginate, PaginateConfig, Paginated } from './paginate'
|
||||||
import { PaginateQuery } from './decorator'
|
import { PaginateQuery } from './decorator'
|
||||||
import { HttpException } from '@nestjs/common'
|
import { HttpException } from '@nestjs/common'
|
||||||
import { CatEntity, CutenessLevel } from './__tests__/cat.entity'
|
import { CatEntity, CutenessLevel } from './__tests__/cat.entity'
|
||||||
@ -8,13 +8,13 @@ import { CatHomeEntity } from './__tests__/cat-home.entity'
|
|||||||
import { CatHomePillowEntity } from './__tests__/cat-home-pillow.entity'
|
import { CatHomePillowEntity } from './__tests__/cat-home-pillow.entity'
|
||||||
import { clone } from 'lodash'
|
import { clone } from 'lodash'
|
||||||
import {
|
import {
|
||||||
parseFilterToken,
|
|
||||||
FilterComparator,
|
FilterComparator,
|
||||||
FilterOperator,
|
FilterOperator,
|
||||||
FilterSuffix,
|
FilterSuffix,
|
||||||
isOperator,
|
isOperator,
|
||||||
isSuffix,
|
isSuffix,
|
||||||
OperatorSymbolToFunction,
|
OperatorSymbolToFunction,
|
||||||
|
parseFilterToken,
|
||||||
} from './filter'
|
} from './filter'
|
||||||
import { ToyShopEntity } from './__tests__/toy-shop.entity'
|
import { ToyShopEntity } from './__tests__/toy-shop.entity'
|
||||||
import { ToyShopAddressEntity } from './__tests__/toy-shop-address.entity'
|
import { ToyShopAddressEntity } from './__tests__/toy-shop-address.entity'
|
||||||
@ -1036,6 +1036,66 @@ describe('paginate', () => {
|
|||||||
expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.cat.name=$not:Milo')
|
expect(result.links.current).toBe('?page=1&limit=20&sortBy=id:ASC&filter.cat.name=$not:Milo')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should be possible to filter by relation without loading it', async () => {
|
||||||
|
const config: PaginateConfig<CatToyEntity> = {
|
||||||
|
relations: ['cat'],
|
||||||
|
sortableColumns: ['id'],
|
||||||
|
where: { cat: { toys: { name: catToys[0].name } } },
|
||||||
|
}
|
||||||
|
const query: PaginateQuery = {
|
||||||
|
path: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await paginate<CatToyEntity>(query, catToyRepo, config)
|
||||||
|
|
||||||
|
expect(result.data.length).toStrictEqual(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be possible to filter by relation without loading it 4th level', async () => {
|
||||||
|
const config: PaginateConfig<CatToyEntity> = {
|
||||||
|
relations: ['cat'],
|
||||||
|
sortableColumns: ['id'],
|
||||||
|
where: { cat: { toys: { shop: { address: { address: Like('%123%') } } } } },
|
||||||
|
}
|
||||||
|
const query: PaginateQuery = {
|
||||||
|
path: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await paginate<CatToyEntity>(query, catToyRepo, config)
|
||||||
|
|
||||||
|
expect(result.data.length).toStrictEqual(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be possible to filter by relation without loading it 4th level with load eager', async () => {
|
||||||
|
const config: PaginateConfig<CatToyEntity> = {
|
||||||
|
loadEagerRelations: true,
|
||||||
|
sortableColumns: ['id'],
|
||||||
|
where: { cat: { toys: { shop: { address: { address: Like('%123%') } } } } },
|
||||||
|
}
|
||||||
|
const query: PaginateQuery = {
|
||||||
|
path: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await paginate<CatToyEntity>(query, catToyRepo, config)
|
||||||
|
|
||||||
|
expect(result.data.length).toStrictEqual(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be possible to filter by relation without including any relations', async () => {
|
||||||
|
const config: PaginateConfig<CatToyEntity> = {
|
||||||
|
loadEagerRelations: false,
|
||||||
|
sortableColumns: ['id'],
|
||||||
|
where: { cat: { toys: { shop: { address: { address: Like('%123%') } } } } },
|
||||||
|
}
|
||||||
|
const query: PaginateQuery = {
|
||||||
|
path: '',
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await paginate<CatToyEntity>(query, catToyRepo, config)
|
||||||
|
|
||||||
|
expect(result.data.length).toStrictEqual(3)
|
||||||
|
})
|
||||||
|
|
||||||
it('should return result based on filter on one-to-many relation', async () => {
|
it('should return result based on filter on one-to-many relation', async () => {
|
||||||
const config: PaginateConfig<CatEntity> = {
|
const config: PaginateConfig<CatEntity> = {
|
||||||
relations: ['toys'],
|
relations: ['toys'],
|
||||||
|
@ -122,9 +122,49 @@ function flattenWhereAndTransform<T>(
|
|||||||
isEmbedded,
|
isEmbedded,
|
||||||
virtualQuery
|
virtualQuery
|
||||||
)
|
)
|
||||||
return queryBuilder['createWhereConditionExpression'](
|
const whereClause = queryBuilder['createWhereConditionExpression'](
|
||||||
queryBuilder['getWherePredicateCondition'](alias, value)
|
queryBuilder['getWherePredicateCondition'](alias, value)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const allJoinedTables = queryBuilder.expressionMap.joinAttributes.reduce(
|
||||||
|
(acc, attr) => {
|
||||||
|
acc[attr.alias.name] = true
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
{} as Record<string, boolean>
|
||||||
|
)
|
||||||
|
|
||||||
|
const allTablesInPath = property.column.split('.').slice(0, -1)
|
||||||
|
const tablesToJoin = allTablesInPath.map((table, idx) => {
|
||||||
|
if (idx === 0) {
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
return [...allTablesInPath.slice(0, idx), table].join('.')
|
||||||
|
})
|
||||||
|
|
||||||
|
tablesToJoin.forEach((table) => {
|
||||||
|
const pathSplit = table.split('.')
|
||||||
|
const fullPath =
|
||||||
|
pathSplit.length === 1
|
||||||
|
? ''
|
||||||
|
: `_${pathSplit
|
||||||
|
.slice(0, -1)
|
||||||
|
.map((p) => p + '_rel')
|
||||||
|
.join('_')}`
|
||||||
|
const tableName = pathSplit[pathSplit.length - 1]
|
||||||
|
const tableAliasWithProperty = `${queryBuilder.alias}${fullPath}.${tableName}`
|
||||||
|
const joinTableAlias = `${queryBuilder.alias}${fullPath}_${tableName}_rel`
|
||||||
|
|
||||||
|
const baseTableAlias = allJoinedTables[joinTableAlias]
|
||||||
|
|
||||||
|
if (baseTableAlias) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
queryBuilder.leftJoin(tableAliasWithProperty, joinTableAlias)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return whereClause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user