Просмотр исходного кода

perf(core): Improve performance when querying product by slug

Michael Bromley 3 лет назад
Родитель
Сommit
742ad36942
1 измененных файлов с 13 добавлено и 23 удалено
  1. 13 23
      packages/core/src/service/services/product.service.ts

+ 13 - 23
packages/core/src/service/services/product.service.ts

@@ -174,42 +174,32 @@ export class ProductService {
         relations?: RelationPaths<Product>,
         relations?: RelationPaths<Product>,
     ): Promise<Translated<Product> | undefined> {
     ): Promise<Translated<Product> | undefined> {
         const qb = this.connection.getRepository(ctx, Product).createQueryBuilder('product');
         const qb = this.connection.getRepository(ctx, Product).createQueryBuilder('product');
-        const effectiveRelations = removeCustomFieldsWithEagerRelations(
-            qb,
-            relations ? [...new Set(this.relations.concat(relations))] : this.relations,
-        );
-        FindOptionsUtils.applyFindManyOptionsOrConditionsToQueryBuilder(qb, {
-            relations: effectiveRelations,
-        });
-        // tslint:disable-next-line:no-non-null-assertion
-        FindOptionsUtils.joinEagerRelations(qb, qb.alias, qb.expressionMap.mainAlias!.metadata);
         const translationQb = this.connection
         const translationQb = this.connection
             .getRepository(ctx, ProductTranslation)
             .getRepository(ctx, ProductTranslation)
             .createQueryBuilder('_product_translation')
             .createQueryBuilder('_product_translation')
             .select('_product_translation.baseId')
             .select('_product_translation.baseId')
             .andWhere('_product_translation.slug = :slug', { slug });
             .andWhere('_product_translation.slug = :slug', { slug });
 
 
-        const translationsAlias = relations?.includes('translations' as any)
-            ? 'product__translations'
-            : 'product_translations';
-        qb.leftJoin('product.channels', 'channel')
+        qb.leftJoin('product.translations', 'translation')
+            .andWhere('product.deletedAt IS NULL')
             .andWhere('product.id IN (' + translationQb.getQuery() + ')')
             .andWhere('product.id IN (' + translationQb.getQuery() + ')')
             .setParameters(translationQb.getParameters())
             .setParameters(translationQb.getParameters())
-            .andWhere('product.deletedAt IS NULL')
-            .andWhere('channel.id = :channelId', { channelId: ctx.channelId })
+            .select('product.id', 'id')
             .addSelect(
             .addSelect(
                 // tslint:disable-next-line:max-line-length
                 // tslint:disable-next-line:max-line-length
-                `CASE ${translationsAlias}.languageCode WHEN '${ctx.languageCode}' THEN 2 WHEN '${ctx.channel.defaultLanguageCode}' THEN 1 ELSE 0 END`,
+                `CASE translation.languageCode WHEN '${ctx.languageCode}' THEN 2 WHEN '${ctx.channel.defaultLanguageCode}' THEN 1 ELSE 0 END`,
                 'sort_order',
                 'sort_order',
             )
             )
             .orderBy('sort_order', 'DESC');
             .orderBy('sort_order', 'DESC');
-        return qb
-            .getOne()
-            .then(product =>
-                product
-                    ? this.translator.translate(product, ctx, ['facetValues', ['facetValues', 'facet']])
-                    : undefined,
-            );
+        // We use getRawOne here to simply get the ID as efficiently as possible,
+        // which we then pass to the regular findOne() method which will handle
+        // all the joins etc.
+        const result = await qb.getRawOne();
+        if (result) {
+            return this.findOne(ctx, result.id, relations);
+        } else {
+            return undefined;
+        }
     }
     }
 
 
     async create(ctx: RequestContext, input: CreateProductInput): Promise<Translated<Product>> {
     async create(ctx: RequestContext, input: CreateProductInput): Promise<Translated<Product>> {