add base repository
This commit is contained in:
parent
2c76c94578
commit
3f0a9ca6fb
@ -1,21 +1,23 @@
|
|||||||
import { isNil, pick, unset } from 'lodash';
|
import { isNil, unset } from 'lodash';
|
||||||
import { FindOptionsUtils, FindTreeOptions, TreeRepository, TreeRepositoryUtils } from 'typeorm';
|
import { FindOptionsUtils, FindTreeOptions, TreeRepositoryUtils } from 'typeorm';
|
||||||
|
|
||||||
import { CategoryEntity } from '@/modules/content/entities/category.entity';
|
import { CategoryEntity } from '@/modules/content/entities/category.entity';
|
||||||
|
import { BaseTreeRepository } from '@/modules/database/base/tree.repository';
|
||||||
|
import { OrderType, TreeChildrenResolve } from '@/modules/database/constants';
|
||||||
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
||||||
|
|
||||||
@CustomRepository(CategoryEntity)
|
@CustomRepository(CategoryEntity)
|
||||||
export class CategoryRepository extends TreeRepository<CategoryEntity> {
|
export class CategoryRepository extends BaseTreeRepository<CategoryEntity> {
|
||||||
|
protected _qbName = 'category';
|
||||||
|
|
||||||
|
protected orderBy = { name: 'customOrder', order: OrderType.ASC };
|
||||||
|
|
||||||
|
protected _childrenResolve = TreeChildrenResolve.UP;
|
||||||
|
|
||||||
buildBaseQB() {
|
buildBaseQB() {
|
||||||
return this.createQueryBuilder('category').leftJoinAndSelect('category.parent', 'parent');
|
return this.createQueryBuilder('category').leftJoinAndSelect('category.parent', 'parent');
|
||||||
}
|
}
|
||||||
|
|
||||||
async findTrees(options?: FindTreeOptions) {
|
|
||||||
const roots = await this.findRoots(options);
|
|
||||||
await Promise.all(roots.map((root) => this.findDescendantsTree(root, options)));
|
|
||||||
return roots;
|
|
||||||
}
|
|
||||||
|
|
||||||
findRoots(options?: FindTreeOptions): Promise<CategoryEntity[]> {
|
findRoots(options?: FindTreeOptions): Promise<CategoryEntity[]> {
|
||||||
const escape = (val: string) => this.manager.connection.driver.escape(val);
|
const escape = (val: string) => this.manager.connection.driver.escape(val);
|
||||||
const joinColumn = this.metadata.treeParentRelation!.joinColumns[0];
|
const joinColumn = this.metadata.treeParentRelation!.joinColumns[0];
|
||||||
@ -39,28 +41,6 @@ export class CategoryRepository extends TreeRepository<CategoryEntity> {
|
|||||||
return qb.getMany();
|
return qb.getMany();
|
||||||
}
|
}
|
||||||
|
|
||||||
async findDescendantsTree(entity: CategoryEntity, options?: FindTreeOptions) {
|
|
||||||
const qb = this.createDescendantsQueryBuilder('category', 'treeClosure', entity)
|
|
||||||
.leftJoinAndSelect('category.parent', 'parent')
|
|
||||||
.orderBy('category.customOrder', 'ASC');
|
|
||||||
FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, pick(options, ['relations', 'depth']));
|
|
||||||
const entities = await qb.getRawAndEntities();
|
|
||||||
const relationMaps = TreeRepositoryUtils.createRelationMaps(
|
|
||||||
this.manager,
|
|
||||||
this.metadata,
|
|
||||||
'category',
|
|
||||||
entities.raw,
|
|
||||||
);
|
|
||||||
TreeRepositoryUtils.buildChildrenEntityTree(
|
|
||||||
this.metadata,
|
|
||||||
entity,
|
|
||||||
entities.entities,
|
|
||||||
relationMaps,
|
|
||||||
{ depth: -1, ...pick(options, ['relations']) },
|
|
||||||
);
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
async findAncestorsTree(
|
async findAncestorsTree(
|
||||||
entity: CategoryEntity,
|
entity: CategoryEntity,
|
||||||
options?: FindTreeOptions,
|
options?: FindTreeOptions,
|
||||||
@ -95,23 +75,6 @@ export class CategoryRepository extends TreeRepository<CategoryEntity> {
|
|||||||
return qb.getCount();
|
return qb.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
async toFlatTrees(
|
|
||||||
trees: CategoryEntity[],
|
|
||||||
depth = 0,
|
|
||||||
parent: CategoryEntity | null = null,
|
|
||||||
): Promise<CategoryEntity[]> {
|
|
||||||
const data: Omit<CategoryEntity, 'children'>[] = [];
|
|
||||||
for (const item of trees) {
|
|
||||||
item.depth = depth;
|
|
||||||
item.parent = parent;
|
|
||||||
const { children } = item;
|
|
||||||
unset(item, 'children');
|
|
||||||
data.push(item);
|
|
||||||
data.push(...(await this.toFlatTrees(children, depth + 1, item)));
|
|
||||||
}
|
|
||||||
return data as CategoryEntity[];
|
|
||||||
}
|
|
||||||
|
|
||||||
async flatAncestorsTree(item: CategoryEntity) {
|
async flatAncestorsTree(item: CategoryEntity) {
|
||||||
let data: Omit<CategoryEntity, 'children'>[] = [];
|
let data: Omit<CategoryEntity, 'children'>[] = [];
|
||||||
const category = await this.findAncestorsTree(item);
|
const category = await this.findAncestorsTree(item);
|
||||||
|
@ -1,20 +1,17 @@
|
|||||||
import { pick, unset } from 'lodash';
|
import { FindOptionsUtils, FindTreeOptions, SelectQueryBuilder } from 'typeorm';
|
||||||
import {
|
|
||||||
FindOptionsUtils,
|
|
||||||
FindTreeOptions,
|
|
||||||
SelectQueryBuilder,
|
|
||||||
TreeRepository,
|
|
||||||
TreeRepositoryUtils,
|
|
||||||
} from 'typeorm';
|
|
||||||
|
|
||||||
import { CommentEntity } from '@/modules/content/entities/comment.entity';
|
import { CommentEntity } from '@/modules/content/entities/comment.entity';
|
||||||
|
import { BaseTreeRepository } from '@/modules/database/base/tree.repository';
|
||||||
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
import { CustomRepository } from '@/modules/database/decorators/repository.decorator';
|
||||||
|
import { QueryHook } from '@/modules/database/types';
|
||||||
|
|
||||||
type FindCommentTreeOptions = FindTreeOptions & {
|
type FindCommentTreeOptions = FindTreeOptions & {
|
||||||
addQuery?: (query: SelectQueryBuilder<CommentEntity>) => SelectQueryBuilder<CommentEntity>;
|
addQuery?: QueryHook<CommentEntity>;
|
||||||
};
|
};
|
||||||
@CustomRepository(CommentEntity)
|
@CustomRepository(CommentEntity)
|
||||||
export class CommentRepository extends TreeRepository<CommentEntity> {
|
export class CommentRepository extends BaseTreeRepository<CommentEntity> {
|
||||||
|
protected _qbName = 'comment';
|
||||||
|
|
||||||
buildBaseQB(qb: SelectQueryBuilder<CommentEntity>): SelectQueryBuilder<CommentEntity> {
|
buildBaseQB(qb: SelectQueryBuilder<CommentEntity>): SelectQueryBuilder<CommentEntity> {
|
||||||
return qb
|
return qb
|
||||||
.leftJoinAndSelect(`comment.parent`, 'parent')
|
.leftJoinAndSelect(`comment.parent`, 'parent')
|
||||||
@ -22,14 +19,7 @@ export class CommentRepository extends TreeRepository<CommentEntity> {
|
|||||||
.orderBy('comment.createdAt', 'DESC');
|
.orderBy('comment.createdAt', 'DESC');
|
||||||
}
|
}
|
||||||
|
|
||||||
async findTrees(options: FindCommentTreeOptions): Promise<CommentEntity[]> {
|
async findRoots(options?: FindCommentTreeOptions): Promise<CommentEntity[]> {
|
||||||
options.relations = ['parent', 'children'];
|
|
||||||
const roots = await this.findRoots(options);
|
|
||||||
await Promise.all(roots.map((root) => this.findDescendantsTree(root, options)));
|
|
||||||
return roots;
|
|
||||||
}
|
|
||||||
|
|
||||||
findRoots(options?: FindCommentTreeOptions): Promise<CommentEntity[]> {
|
|
||||||
const { addQuery, ...rest } = options;
|
const { addQuery, ...rest } = options;
|
||||||
const escape = (val: string) => this.manager.connection.driver.escape(val);
|
const escape = (val: string) => this.manager.connection.driver.escape(val);
|
||||||
const joinColumn = this.metadata.treeParentRelation!.joinColumns[0];
|
const joinColumn = this.metadata.treeParentRelation!.joinColumns[0];
|
||||||
@ -38,58 +28,19 @@ export class CommentRepository extends TreeRepository<CommentEntity> {
|
|||||||
let qb = this.buildBaseQB(this.createQueryBuilder('comment'));
|
let qb = this.buildBaseQB(this.createQueryBuilder('comment'));
|
||||||
FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, rest);
|
FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, rest);
|
||||||
qb.where(`${escape('comment')}.${escape(parentPropertyName)} IS NULL`);
|
qb.where(`${escape('comment')}.${escape(parentPropertyName)} IS NULL`);
|
||||||
qb = addQuery ? addQuery(qb) : qb;
|
qb = addQuery ? await addQuery(qb) : qb;
|
||||||
return qb.getMany();
|
return qb.getMany();
|
||||||
}
|
}
|
||||||
|
|
||||||
createDtsQueryBuilder(
|
async createDtsQueryBuilder(
|
||||||
closureTable: string,
|
closureTable: string,
|
||||||
entity: CommentEntity,
|
entity: CommentEntity,
|
||||||
options: FindCommentTreeOptions = {},
|
options: FindCommentTreeOptions = {},
|
||||||
): SelectQueryBuilder<CommentEntity> {
|
): Promise<SelectQueryBuilder<CommentEntity>> {
|
||||||
const { addQuery } = options;
|
const { addQuery } = options;
|
||||||
const qb = this.buildBaseQB(
|
const qb = this.buildBaseQB(
|
||||||
super.createDescendantsQueryBuilder('comment', closureTable, entity),
|
super.createDescendantsQueryBuilder('comment', closureTable, entity),
|
||||||
);
|
);
|
||||||
return addQuery ? addQuery(qb) : qb;
|
return addQuery ? addQuery(qb) : qb;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findDescendantsTree(
|
|
||||||
entity: CommentEntity,
|
|
||||||
options: FindCommentTreeOptions = {},
|
|
||||||
): Promise<CommentEntity> {
|
|
||||||
const qb: SelectQueryBuilder<CommentEntity> = this.createDtsQueryBuilder(
|
|
||||||
'treeClosure',
|
|
||||||
entity,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
FindOptionsUtils.applyOptionsToTreeQueryBuilder(qb, pick(options, ['relations', 'depth']));
|
|
||||||
const entities = await qb.getRawAndEntities();
|
|
||||||
const relationMaps = TreeRepositoryUtils.createRelationMaps(
|
|
||||||
this.manager,
|
|
||||||
this.metadata,
|
|
||||||
'comment',
|
|
||||||
entities.raw,
|
|
||||||
);
|
|
||||||
TreeRepositoryUtils.buildChildrenEntityTree(
|
|
||||||
this.metadata,
|
|
||||||
entity,
|
|
||||||
entities.entities,
|
|
||||||
relationMaps,
|
|
||||||
{ depth: -1, ...pick(options, ['relations']) },
|
|
||||||
);
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
async toFlatTrees(trees: CommentEntity[], depth = 0): Promise<CommentEntity[]> {
|
|
||||||
const data: Omit<CommentEntity, 'children'>[] = [];
|
|
||||||
for (const item of trees) {
|
|
||||||
item.depth = depth;
|
|
||||||
const { children } = item;
|
|
||||||
unset(item, 'children');
|
|
||||||
data.push(item);
|
|
||||||
data.push(...(await this.toFlatTrees(children, depth + 1)));
|
|
||||||
}
|
|
||||||
return data as CommentEntity[];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class CommentService {
|
|||||||
|
|
||||||
async findTrees(options: QueryCommentTreeDto = {}) {
|
async findTrees(options: QueryCommentTreeDto = {}) {
|
||||||
return this.repository.findTrees({
|
return this.repository.findTrees({
|
||||||
addQuery: (qb) => {
|
addQuery: async (qb) => {
|
||||||
return isNil(options.post) ? qb : qb.where('post.id = :id', { id: options.post });
|
return isNil(options.post) ? qb : qb.where('post.id = :id', { id: options.post });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -30,7 +30,7 @@ export class CommentService {
|
|||||||
|
|
||||||
async paginate(options: QueryCommentDto) {
|
async paginate(options: QueryCommentDto) {
|
||||||
const { post, ...query } = options;
|
const { post, ...query } = options;
|
||||||
const addQuery = (qb: SelectQueryBuilder<CommentEntity>) => {
|
const addQuery = async (qb: SelectQueryBuilder<CommentEntity>) => {
|
||||||
const condition: RecordString = {};
|
const condition: RecordString = {};
|
||||||
if (!isNil(post)) {
|
if (!isNil(post)) {
|
||||||
condition.post = post;
|
condition.post = post;
|
||||||
|
Loading…
Reference in New Issue
Block a user