Taichi Masuyama 4 лет назад
Родитель
Сommit
91de97345b
2 измененных файлов с 26 добавлено и 66 удалено
  1. 0 34
      packages/app/src/server/models/page.ts
  2. 26 32
      packages/app/src/server/service/page.ts

+ 0 - 34
packages/app/src/server/models/page.ts

@@ -423,40 +423,6 @@ async function pushRevision(pageData, newRevision, user) {
   return pageData.save();
 }
 
-/**
- * return aggregate condition to get following pages
- * - page that has the same path as the provided path
- * - pages that are descendants of the above page
- * pages without parent will be ignored
- */
-schema.statics.getAggrConditionForPageWithProvidedPathAndDescendants = function(path:string) {
-  let match;
-  if (isTopPage(path)) {
-    match = {
-      // https://regex101.com/r/Kip2rV/1
-      $match: { $or: [{ path: { $regex: '^/.*' }, parent: { $ne: null } }, { path: '/' }] },
-    };
-  }
-  else {
-    match = {
-      // https://regex101.com/r/mJvGrG/1
-      $match: { path: { $regex: `^${path}(/.*|$)` }, parent: { $ne: null } },
-    };
-  }
-  return [
-    match,
-    {
-      $project: {
-        path: 1,
-        parent: 1,
-        field_length: { $strLenCP: '$path' },
-      },
-    },
-    { $sort: { field_length: -1 } },
-    { $project: { field_length: 0 } },
-  ];
-};
-
 /**
  * add/subtract descendantCount of pages with provided paths by increment.
  * increment can be negative number

+ 26 - 32
packages/app/src/server/service/page.ts

@@ -1439,6 +1439,7 @@ class PageService {
     return nDeletedNonEmptyPages;
   }
 
+  // no need to separate Main Sub since it is devided into single page operations
   async deleteMultiplePages(pagesToDelete, user, options): Promise<void> {
     const { isRecursively, isCompletely } = options;
 
@@ -1925,33 +1926,24 @@ class PageService {
     }
 
     /*
-     * Sub Operation
+     * Sub Operation (s)
      */
-    await this.normalizeParentRecursivelyByPageIdsSubOperation(normalizablePages, user);
+    const pagesToNormalize = omitDuplicateAreaPageFromPages(pages);
+    (async() => {
+      for await (const page of pagesToNormalize) {
+        await this.normalizeParentRecursivelyByPageIdSubOperation(page, user);
+      }
+    })();
   }
 
-  async normalizeParentRecursivelyByPageIdsSubOperation(pages, user): Promise<void> {
+  private async normalizeParentRecursivelyByPageIdSubOperation(page, user) {
     const Page = mongoose.model('Page') as unknown as PageModel;
 
-    const pagesToNormalize = omitDuplicateAreaPageFromPages(pages);
-    const pageIdsToNormalize = pagesToNormalize.map(p => p._id);
-    const pathsToNormalize = Array.from(new Set(pagesToNormalize.map(p => p.path)));
+    // TODO: insertOne PageOperationBlock
 
-    // TODO: insertMany PageOperationBlock
-
-    // for updating descendantCount
-    const pageIdToExDescendantCountMap = new Map<ObjectIdLike, number>();
-
-    // MAIN PROCESS migrate recursively
-    const regexps = pathsToNormalize.map(p => new RegExp(`^${escapeStringRegexp(p)}`, 'i'));
+    const regexps = [new RegExp(`^${escapeStringRegexp(page.path)}`, 'i')];
     try {
       await this.normalizeParentRecursively(null, regexps);
-
-      // find pages to save descendantCount of normalized pages (only pages in pageIds parameter of this method)
-      const pagesBeforeUpdatingDescendantCount = await Page.findByIdsAndViewer(pageIdsToNormalize, user);
-      pagesBeforeUpdatingDescendantCount.forEach((p) => {
-        pageIdToExDescendantCountMap.set(p._id.toString(), p.descendantCount);
-      });
     }
     catch (err) {
       logger.error('V5 initial miration failed.', err);
@@ -1960,22 +1952,18 @@ class PageService {
       throw err;
     }
 
-    // POST MAIN PROCESS update descendantCount
     try {
       // update descendantCount of self and descendant pages first
-      for await (const path of pathsToNormalize) {
-        await this.updateDescendantCountOfSelfAndDescendants(path);
-      }
+      await this.updateDescendantCountOfSelfAndDescendants(page.path);
 
       // find pages again to get updated descendantCount
       // then calculate inc
-      const pagesAfterUpdatingDescendantCount = await Page.findByIdsAndViewer(pageIdsToNormalize, user);
-      for await (const page of pagesAfterUpdatingDescendantCount) {
-        const exDescendantCount = pageIdToExDescendantCountMap.get(page._id.toString()) || 0;
-        const newDescendantCount = page.descendantCount;
-        const inc = newDescendantCount - exDescendantCount;
-        await this.updateDescendantCountOfAncestors(page._id, inc, false);
-      }
+      const pageAfterUpdatingDescendantCount = await Page.findByIdAndViewer(page._id, user);
+
+      const exDescendantCount = page.descendantCount;
+      const newDescendantCount = pageAfterUpdatingDescendantCount.descendantCount;
+      const inc = newDescendantCount - exDescendantCount;
+      await this.updateDescendantCountOfAncestors(page._id, inc, false);
     }
     catch (err) {
       logger.error('Failed to update descendantCount after normalizing parent:', err);
@@ -2287,9 +2275,15 @@ class PageService {
   async updateDescendantCountOfSelfAndDescendants(path: string): Promise<void> {
     const BATCH_SIZE = 200;
     const Page = this.crowi.model('Page');
+    const { PageQueryBuilder } = Page;
+
+    const builder = new PageQueryBuilder(Page.find(), true);
+    builder.addConditionAsMigrated();
+    builder.addConditionToListWithDescendants(path);
+    builder.addConditionToSortPagesByDescPath();
+
+    const aggregatedPages = await builder.query.lean().cursor({ batchSize: BATCH_SIZE });
 
-    const aggregateCondition = Page.getAggrConditionForPageWithProvidedPathAndDescendants(path);
-    const aggregatedPages = await Page.aggregate(aggregateCondition).cursor({ batchSize: BATCH_SIZE });
 
     const recountWriteStream = new Writable({
       objectMode: true,