feat(collection-manger): lazy load collection field (#1993)

* feat(collection-manger): lazy load collection field

* chore: console.log
This commit is contained in:
ChengLei Shao 2023-06-06 22:48:43 +08:00 committed by GitHub
parent 42ad77da68
commit c604f37222
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 4 deletions

View File

@ -5,7 +5,7 @@ import { FieldModel } from './field';
interface LoadOptions extends Transactionable { interface LoadOptions extends Transactionable {
// TODO // TODO
skipField?: boolean; skipField?: boolean | Array<string>;
skipExist?: boolean; skipExist?: boolean;
} }
@ -41,6 +41,10 @@ export class CollectionModel extends MagicAttributeModel {
await this.loadFields({ transaction }); await this.loadFields({ transaction });
} }
if (lodash.isArray(skipField)) {
await this.loadFields({ transaction, skipField });
}
await this.db.emitAsync('collection:loaded', { await this.db.emitAsync('collection:loaded', {
collection, collection,
transaction, transaction,
@ -49,11 +53,26 @@ export class CollectionModel extends MagicAttributeModel {
return collection; return collection;
} }
async loadFields(options: Transactionable = {}) { async loadFields(
options: Transactionable & {
skipField?: Array<string>;
includeFields?: Array<string>;
} = {},
) {
let fields = this.get('fields') || []; let fields = this.get('fields') || [];
if (!fields.length) { if (!fields.length) {
fields = await this.getFields(options); 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 // @ts-ignore
const instances: FieldModel[] = fields; const instances: FieldModel[] = fields;

View File

@ -1,6 +1,7 @@
import { Repository } from '@nocobase/database'; import { Repository } from '@nocobase/database';
import { CollectionsGraph } from '@nocobase/utils'; import { CollectionsGraph } from '@nocobase/utils';
import { CollectionModel } from '../models/collection'; import { CollectionModel } from '../models/collection';
import lodash from 'lodash';
interface LoadOptions { interface LoadOptions {
filter?: any; filter?: any;
@ -16,7 +17,9 @@ export class CollectionRepository extends Repository {
const graph = new graphlib.Graph(); const graph = new graphlib.Graph();
const nameMap = {}; const nameMap: {
[key: string]: CollectionModel;
} = {};
const viewCollections = []; const viewCollections = [];
@ -60,15 +63,40 @@ export class CollectionRepository extends Repository {
const sortedNames = graphlib.alg.topsort(graph); const sortedNames = graphlib.alg.topsort(graph);
const lazyCollectionFields: {
[key: string]: Array<string>;
} = {};
for (const instanceName of sortedNames) { for (const instanceName of sortedNames) {
if (!nameMap[instanceName]) continue; 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 // load view fields
for (const viewCollectionName of viewCollections) { for (const viewCollectionName of viewCollections) {
await nameMap[viewCollectionName].loadFields({}); 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) { async db2cm(collectionName: string) {