From c604f37222e6f79f915bd0f2947c20ecae857118 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Tue, 6 Jun 2023 22:48:43 +0800 Subject: [PATCH] feat(collection-manger): lazy load collection field (#1993) * feat(collection-manger): lazy load collection field * chore: console.log --- .../src/models/collection.ts | 23 +++++++++++-- .../src/repositories/collection-repository.ts | 32 +++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/packages/plugins/collection-manager/src/models/collection.ts b/packages/plugins/collection-manager/src/models/collection.ts index 8075d0d028..b07e018753 100644 --- a/packages/plugins/collection-manager/src/models/collection.ts +++ b/packages/plugins/collection-manager/src/models/collection.ts @@ -5,7 +5,7 @@ import { FieldModel } from './field'; interface LoadOptions extends Transactionable { // TODO - skipField?: boolean; + skipField?: boolean | Array; skipExist?: boolean; } @@ -41,6 +41,10 @@ export class CollectionModel extends MagicAttributeModel { await this.loadFields({ transaction }); } + if (lodash.isArray(skipField)) { + await this.loadFields({ transaction, skipField }); + } + await this.db.emitAsync('collection:loaded', { collection, transaction, @@ -49,11 +53,26 @@ export class CollectionModel extends MagicAttributeModel { return collection; } - async loadFields(options: Transactionable = {}) { + async loadFields( + options: Transactionable & { + skipField?: Array; + includeFields?: Array; + } = {}, + ) { let fields = this.get('fields') || []; + if (!fields.length) { fields = await this.getFields(options); } + + if (options.skipField) { + fields = fields.filter((field) => !options.skipField.includes(field.name)); + } + + if (options.includeFields) { + fields = fields.filter((field) => options.includeFields.includes(field.name)); + } + // @ts-ignore const instances: FieldModel[] = fields; diff --git a/packages/plugins/collection-manager/src/repositories/collection-repository.ts b/packages/plugins/collection-manager/src/repositories/collection-repository.ts index 4938303ba9..5c542d01a0 100644 --- a/packages/plugins/collection-manager/src/repositories/collection-repository.ts +++ b/packages/plugins/collection-manager/src/repositories/collection-repository.ts @@ -1,6 +1,7 @@ import { Repository } from '@nocobase/database'; import { CollectionsGraph } from '@nocobase/utils'; import { CollectionModel } from '../models/collection'; +import lodash from 'lodash'; interface LoadOptions { filter?: any; @@ -16,7 +17,9 @@ export class CollectionRepository extends Repository { const graph = new graphlib.Graph(); - const nameMap = {}; + const nameMap: { + [key: string]: CollectionModel; + } = {}; const viewCollections = []; @@ -60,15 +63,40 @@ export class CollectionRepository extends Repository { const sortedNames = graphlib.alg.topsort(graph); + const lazyCollectionFields: { + [key: string]: Array; + } = {}; for (const instanceName of sortedNames) { if (!nameMap[instanceName]) continue; - await nameMap[instanceName].load({ skipExist, skipField: viewCollections.includes(instanceName) }); + + const skipField = (() => { + if (viewCollections.includes(instanceName)) { + return true; + } + + const fields = nameMap[instanceName].get('fields'); + + return fields + .filter((field) => field['type'] === 'belongsTo' && viewCollections.includes(field.options?.['target'])) + .map((field) => field.get('name')); + })(); + + if (lodash.isArray(skipField) && skipField.length) { + lazyCollectionFields[instanceName] = skipField; + } + + await nameMap[instanceName].load({ skipField }); } // load view fields for (const viewCollectionName of viewCollections) { await nameMap[viewCollectionName].loadFields({}); } + + // load lazy collection field + for (const [collectionName, skipField] of Object.entries(lazyCollectionFields)) { + await nameMap[collectionName].loadFields({ includeFields: skipField }); + } } async db2cm(collectionName: string) {