Browse Source

perf(core): Use TypeORM relation query builder when filtering collection

Relates to #1893
Thierry Tournie 3 years ago
parent
commit
8aa7201c5c
1 changed files with 41 additions and 11 deletions
  1. 41 11
      packages/core/src/service/services/collection.service.ts

+ 41 - 11
packages/core/src/service/services/collection.service.ts

@@ -559,6 +559,15 @@ export class CollectionService implements OnModuleInit {
         return filters;
     }
 
+    private chunkArray = <T>(array: T[], chunkSize: number): T[][] => {
+        const results = []
+        for (let i = 0; i < array.length; i += chunkSize) {
+          results.push(array.slice(i, i + chunkSize))
+        }
+      
+        return results
+      }
+
     /**
      * Applies the CollectionFilters
      *
@@ -583,22 +592,43 @@ export class CollectionService implements OnModuleInit {
             ...(collection.filters || []),
         ]);
         const postIds = collection.productVariants.map(v => v.id);
+        const preIdsSet = new Set(preIds);
+        const postIdsSet = new Set(postIds);
+
+        const toDeleteIds = preIds.filter((id) => !postIdsSet.has(id))
+        const toAddIds = postIds.filter((id) => !preIdsSet.has(id))
+
         try {
+            // First we remove variants that are no longer in the collection
+            const chunkedDeleteIds = this.chunkArray(toDeleteIds, 500)
+            let chunkDeleteVariant = 0
+
+            for (const chunkedDeleteId of chunkedDeleteIds) {
+                chunkDeleteVariant++
+                await this.connection.rawConnection
+                  .createQueryBuilder()
+                  .relation(Collection, 'productVariants')
+                  .of(collection)
+                  .remove(chunkedDeleteId)
+              }
+
+            // Then we add variants have been added
+            const chunkedAddIds = this.chunkArray(toAddIds, 500)
+            let chunkVariant = 0
+
+            for (const chunkedAddId of chunkedAddIds) {
+            chunkVariant++
             await this.connection.rawConnection
-                .getRepository(Collection)
-                // Only update the exact changed properties, to avoid VERY hard-to-debug
-                // non-deterministic race conditions e.g. when the "position" is changed
-                // by moving a Collection and then this save operation clobbers it back
-                // to the old value.
-                .save(pick(collection, ['id', 'productVariants']), {
-                    chunk: Math.ceil(collection.productVariants.length / 500),
-                    reload: false,
-                });
+                .createQueryBuilder()
+                .relation(Collection, 'productVariants')
+                .of(collection)
+                .add(chunkedAddId)
+            }
+
         } catch (e) {
             Logger.error(e);
         }
-        const preIdsSet = new Set(preIds);
-        const postIdsSet = new Set(postIds);
+        
 
         if (applyToChangedVariantsOnly) {
             return [...preIds.filter(id => !postIdsSet.has(id)), ...postIds.filter(id => !preIdsSet.has(id))];