From f4190e65a4379fd53018dc9809b017dccd0152c4 Mon Sep 17 00:00:00 2001 From: marian2js Date: Mon, 24 Aug 2020 15:57:44 -0300 Subject: [PATCH] feat(mongodb): Add support for find relations with MongoDB --- packages/query-typeorm-mongo/src/index.ts | 4 +- .../services/typeorm-query-mongo.service.ts | 153 +++++++++++------- 2 files changed, 101 insertions(+), 56 deletions(-) diff --git a/packages/query-typeorm-mongo/src/index.ts b/packages/query-typeorm-mongo/src/index.ts index 34fe2dd43..4ac7c15e5 100644 --- a/packages/query-typeorm-mongo/src/index.ts +++ b/packages/query-typeorm-mongo/src/index.ts @@ -1,2 +1,2 @@ -export { TypeOrmQueryService, TypeOrmQueryServiceOpts } from './services'; -export { NestjsQueryTypeOrmModule } from './module'; +export { TypeOrmMongoQueryService, TypeOrmMongoQueryServiceOpts } from './services'; +export { NestjsQueryTypeOrmMongoModule } from './module'; diff --git a/packages/query-typeorm-mongo/src/services/typeorm-query-mongo.service.ts b/packages/query-typeorm-mongo/src/services/typeorm-query-mongo.service.ts index bef76fa91..bf7545fa5 100644 --- a/packages/query-typeorm-mongo/src/services/typeorm-query-mongo.service.ts +++ b/packages/query-typeorm-mongo/src/services/typeorm-query-mongo.service.ts @@ -5,7 +5,6 @@ import { DeepPartial, DeleteManyResponse, Filter, - FilterComparisons, Query, QueryService, UpdateManyResponse, @@ -17,6 +16,17 @@ export interface TypeOrmMongoQueryServiceOpts { useSoftDelete?: boolean; } +const mongoOperatorMapper: { [k: string]: string } = { + eq: '$eq', + neq: '$ne', + gt: '$gt', + gte: '$gte', + lt: '$lt', + lte: '$lte', + in: '$in', + notIn: '$nin', +}; + /** * Base class for all query services that use a `typeorm` Repository. * @@ -48,35 +58,34 @@ export class TypeOrmMongoQueryService implements QueryService { } protected buildExpression(filter: Filter): FindConditions { - const where: FindConditions = {}; - - Object.entries(filter).forEach(([key, value]) => { + return Object.entries(filter).reduce((prev: FindConditions, [key, value]) => { + if (!value) { + return prev; + } if (Array.isArray(value)) { - where[`$${key}`] = value.map((subFilter) => this.buildExpression(subFilter)); - } else if (value) { - Object.entries(value).forEach(([fieldKey, fieldValue]) => { - let mongoOperator: string | undefined; - if (['eq', 'gt', 'gte', 'lt', 'lte', 'in'].includes(fieldKey)) { - mongoOperator = `$${fieldKey}`; - } - if (fieldKey === 'neq') { - mongoOperator = '$ne'; - } - if (fieldKey === 'notIn') { - mongoOperator = '$nin'; - } - if (mongoOperator) { - where[key] = { - [mongoOperator]: fieldValue, + return { + ...prev, + [`$${key}`]: value.map((subFilter) => this.buildExpression(subFilter)), + }; + } + const findConditions = Object.entries(value).reduce( + (prevCondition: FindConditions, [fieldKey, fieldValue]) => { + if (mongoOperatorMapper[fieldKey]) { + return { + ...prevCondition, + [mongoOperatorMapper[fieldKey]]: fieldValue, }; - } else { - this.logger.error(`Operator ${fieldKey} not supported yet`); } - }); - } - }); - - return where; + this.logger.error(`Operator ${fieldKey} not supported yet`); + return prevCondition; + }, + {}, + ); + return { + ...prev, + [key]: findConditions, + }; + }, {}); } /** @@ -314,22 +323,24 @@ export class TypeOrmMongoQueryService implements QueryService { } } - queryRelations( - RelationClass: Class, - relationName: string, - dto: Entity, - query: Query, - ): Promise; - queryRelations( - RelationClass: Class, - relationName: string, - dtos: Entity[], - query: Query, - ): Promise>; - queryRelations(RelationClass: any, relationName: any, dtos: any, query: any) { + /** + * Adds multiple relations. + * @param relationName - The name of the relation to query for. + * @param id - The id of the dto to add the relation to. + * @param relationIds - The ids of the relations to add. + */ + addRelations(relationName: string, id: string | number, relationIds: (string | number)[]): Promise { throw new Error('Not implemented yet'); } + aggregateRelations( + RelationClass: Class, + relationName: string, + entities: Entity[], + filter: Filter, + aggregate: AggregateQuery, + ): Promise>>; + aggregateRelations( RelationClass: Class, relationName: string, @@ -337,52 +348,86 @@ export class TypeOrmMongoQueryService implements QueryService { filter: Filter, aggregate: AggregateQuery, ): Promise>; + aggregateRelations( RelationClass: Class, relationName: string, - dtos: Entity[], + dto: Entity | Entity[], filter: Filter, aggregate: AggregateQuery, - ): Promise>>; - aggregateRelations(RelationClass: any, relationName: any, dtos: any, filter: any, aggregate: any) { + ): Promise | Map>> { throw new Error('Not implemented yet'); } + countRelations( + RelationClass: Class, + relationName: string, + entities: Entity[], + filter: Filter, + ): Promise>; + countRelations( RelationClass: Class, relationName: string, dto: Entity, filter: Filter, ): Promise; + countRelations( RelationClass: Class, relationName: string, - dto: Entity[], + dto: Entity | Entity[], filter: Filter, - ): Promise>; - countRelations(RelationClass: any, relationName: any, dto: any, filter: any) { + ): Promise> { throw new Error('Not implemented yet'); } + findRelation( + RelationClass: Class, + relationName: string, + dtos: Entity[], + ): Promise>; findRelation( RelationClass: Class, relationName: string, dto: Entity, ): Promise; - findRelation( + async findRelation( RelationClass: Class, relationName: string, - dtos: Entity[], - ): Promise>; - findRelation(RelationClass: any, relationName: any, dtos: any) { - throw new Error('Not implemented yet'); + dto: Entity | Entity[], + ): Promise<(Relation | undefined) | Map> { + const dtos: Entity[] = Array.isArray(dto) ? dto : [dto]; + const relationRepo = this.repo.manager.getRepository(RelationClass); + return dtos.reduce(async (prev, curr) => { + const map = await prev; + map.set(curr, await relationRepo.findOne(curr[relationName as keyof Entity])); + return map; + }, Promise.resolve(new Map())); } - addRelations(relationName: string, id: string | number, relationIds: (string | number)[]): Promise { + queryRelations( + RelationClass: Class, + relationName: string, + entities: Entity[], + query: Query, + ): Promise>; + queryRelations( + RelationClass: Class, + relationName: string, + dto: Entity, + query: Query, + ): Promise; + queryRelations( + RelationClass: Class, + relationName: string, + dto: Entity | Entity[], + query: Query, + ): Promise> { throw new Error('Not implemented yet'); } - setRelation(relationName: string, id: string | number, relationId: string | number): Promise { + removeRelation(relationName: string, id: string | number, relationId: string | number): Promise { throw new Error('Not implemented yet'); } @@ -394,7 +439,7 @@ export class TypeOrmMongoQueryService implements QueryService { throw new Error('Not implemented yet'); } - removeRelation(relationName: string, id: string | number, relationId: string | number): Promise { + setRelation(relationName: string, id: string | number, relationId: string | number): Promise { throw new Error('Not implemented yet'); } }