From 2fbf0b7bb68fa3318798c6f46bebcd8092cc2b07 Mon Sep 17 00:00:00 2001 From: jpv-os Date: Mon, 11 Sep 2023 12:27:04 +0200 Subject: [PATCH] fix: querying for one-to-many or one-to-one relationships in typeorm would not return any entities because of an implementation error when filtering for the correct results after batch selecting all related entities. --- package.json | 2 ++ packages/query-typeorm/package.json | 2 ++ .../src/query/relation-query.builder.ts | 17 ++++++--- yarn.lock | 36 +++++++++++++++++++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 31413c85f..d7e15bb3b 100644 --- a/package.json +++ b/package.json @@ -66,9 +66,11 @@ "@types/jest": "29.5.4", "@types/lodash.escaperegexp": "4.1.7", "@types/lodash.filter": "4.6.7", + "@types/lodash.keys": "4.2.7", "@types/lodash.merge": "4.6.7", "@types/lodash.omit": "4.5.7", "@types/lodash.pick": "4.4.7", + "@types/lodash.pickby": "4.6.7", "@types/node": "20.5.7", "@types/passport-jwt": "3.0.9", "@types/passport-local": "1.0.35", diff --git a/packages/query-typeorm/package.json b/packages/query-typeorm/package.json index 2845cf3e7..f50422cf4 100644 --- a/packages/query-typeorm/package.json +++ b/packages/query-typeorm/package.json @@ -20,8 +20,10 @@ "dependencies": { "camel-case": "^4.1.2", "lodash.filter": "^4.6.0", + "lodash.keys": "^4.2.0", "lodash.merge": "^4.6.2", "lodash.omit": "^4.5.0", + "lodash.pickby": "^4.6.0", "tslib": "^2.6.2", "uuid": "^9.0.0" }, diff --git a/packages/query-typeorm/src/query/relation-query.builder.ts b/packages/query-typeorm/src/query/relation-query.builder.ts index 4e6296fc7..8ebc2bb6f 100644 --- a/packages/query-typeorm/src/query/relation-query.builder.ts +++ b/packages/query-typeorm/src/query/relation-query.builder.ts @@ -1,6 +1,8 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { AggregateQuery, Class, Query } from '@ptc-org/nestjs-query-core' import lodashFilter from 'lodash.filter' +import lodashKeys from 'lodash.keys' +import lodashPickBy from 'lodash.pickby' import { Brackets, ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm' import { DriverUtils } from 'typeorm/driver/DriverUtils' import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata' @@ -357,16 +359,21 @@ export class RelationQueryBuilder { fromAlias: aliasName, fromPrimaryKeys, joins: [], - mapRelations: (entity: Entity, relations: Relation[]): Relation[] => { - const filter = columns.reduce( + mapRelations: (entity: Entity, relations: Relation[], rawRelations: RawRelation[]): Relation[] => { + // create a filter for the raw relation array to filter only for the objects that are related to this entity + // do this by building an alias based on the column database name for filtering + // e.g. if the entity is a customer, look for a customer id in the raw relation entity object. + const rawFilter = columns.reduce( (columnsFilter, column) => ({ ...columnsFilter, - [column.propertyName]: column.referencedColumn.getEntityValue(entity) + [this.buildAlias(column.databaseName)]: column.referencedColumn.getEntityValue(entity) }), {} as Partial ) - - return lodashFilter(relations, filter) as Relation[] + // find all indices where the raw relation entity matches the filter + const rawIndices = lodashKeys(lodashPickBy(rawRelations, rawFilter)).map((idx) => +idx) + // return all mapped entities by using the indices that were calculated using the raw entities + return rawIndices.map((idx) => relations[idx]) }, batchSelect: (qb: SelectQueryBuilder, entities: Entity[]) => { const params = {} diff --git a/yarn.lock b/yarn.lock index 9b1a613b1..caf297630 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5939,8 +5939,10 @@ __metadata: dependencies: camel-case: ^4.1.2 lodash.filter: ^4.6.0 + lodash.keys: ^4.2.0 lodash.merge: ^4.6.2 lodash.omit: ^4.5.0 + lodash.pickby: ^4.6.0 tslib: ^2.6.2 uuid: ^9.0.0 peerDependencies: @@ -6960,6 +6962,15 @@ __metadata: languageName: node linkType: hard +"@types/lodash.keys@npm:4.2.7": + version: 4.2.7 + resolution: "@types/lodash.keys@npm:4.2.7" + dependencies: + "@types/lodash": "*" + checksum: 2da5cdc5c306c759d8647687701c3a550cb268ba7b644773fede824d94d79e3d753f0f7cf63762809afeacccbd68223954be0ba6958b34750e20329f56825d50 + languageName: node + linkType: hard + "@types/lodash.merge@npm:4.6.7": version: 4.6.7 resolution: "@types/lodash.merge@npm:4.6.7" @@ -6987,6 +6998,15 @@ __metadata: languageName: node linkType: hard +"@types/lodash.pickby@npm:4.6.7": + version: 4.6.7 + resolution: "@types/lodash.pickby@npm:4.6.7" + dependencies: + "@types/lodash": "*" + checksum: 1a4d85dd4ce371352b65dead78e1c6d89c4d59c440bfd9b27023b1113c8610115f2dda17c056b94697f7bfbd947bd8abfe0afd5195b65e2675b404e0e1542fae + languageName: node + linkType: hard + "@types/lodash@npm:*": version: 4.14.195 resolution: "@types/lodash@npm:4.14.195" @@ -15665,6 +15685,13 @@ __metadata: languageName: node linkType: hard +"lodash.keys@npm:^4.2.0": + version: 4.2.0 + resolution: "lodash.keys@npm:4.2.0" + checksum: 055576c8c4a0bacc0c1da9bcbb520e6e70dcf94c609495263686c62c8242a440293e9ab8387a7398dda529cb05b76e8f783c3fd3d6ba7bc6d5d6d2e08e8512ae + languageName: node + linkType: hard + "lodash.memoize@npm:4.x, lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" @@ -15700,6 +15727,13 @@ __metadata: languageName: node linkType: hard +"lodash.pickby@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.pickby@npm:4.6.0" + checksum: a554d898c15bcd3218e4005b95b5146210bd862010c7d242d17106ee36aed9b9209a858ce974136ab1faadd86a82297761c206fda7f1886278bac827145c5536 + languageName: node + linkType: hard + "lodash.snakecase@npm:^4.1.1": version: 4.1.1 resolution: "lodash.snakecase@npm:4.1.1" @@ -16772,9 +16806,11 @@ __metadata: "@types/jest": 29.5.4 "@types/lodash.escaperegexp": 4.1.7 "@types/lodash.filter": 4.6.7 + "@types/lodash.keys": 4.2.7 "@types/lodash.merge": 4.6.7 "@types/lodash.omit": 4.5.7 "@types/lodash.pick": 4.4.7 + "@types/lodash.pickby": 4.6.7 "@types/node": 20.5.7 "@types/passport-jwt": 3.0.9 "@types/passport-local": 1.0.35