TypeORM:尝试按 loadRelationCountAndMap 之后创建的字段排序时,无法读取未定义的属性“databaseName”

问题描述 投票:0回答:1

我正在尝试计算帖子的观看次数,然后按观看次数对帖子进行排序。

这是我尝试计算的代码部分。 Alias.views 是一个对象数组。据我了解,alias.viewsCount应该是一个数字。

            qb.loadRelationCountAndMap('alias.commentsCount', 'alias.comments');
            qb.loadRelationCountAndMap('alias.votesCount', 'alias.voters');
            qb.loadRelationCountAndMap('alias.viewsCount', 'alias.views');
            qb.loadRelationCountAndMap('alias.sharesCount', 'alias.distributors');

            qb.orderBy('alias.viewsCount', 'DESC');

但我总是收到此错误(日志):

query: START TRANSACTION
query: SELECT "category"."id" AS "category_id", "category"."name" AS "category_name", "category"."slug" AS "category_slug" FROM "app_post_category" "category" INNER JOIN "app_post_category_post_type" "category_postTypes" ON "category_postTypes"."post_category_id"="category"."id" INNER JOIN "app_post_type" "postTypes" ON "postTypes"."id"="category_postTypes"."post_type_id" AND ("postTypes"."post_type" IN ($1, $2)) -- PARAMETERS: ["POST","ARTICLE"]
query: ROLLBACK
query: START TRANSACTION
[Nest] 923   - 05/30/2019, 4:47 PM   [ExceptionsHandler] Cannot read property 'databaseName' of undefined +21439ms
TypeError: Cannot read property 'databaseName' of undefined
    at /usr/src/app/src/query-builder/SelectQueryBuilder.ts:1866:145
    at Array.map (<anonymous>)
    at SelectQueryBuilder.createOrderByCombinedWithSelectExpression (/usr/src/app/src/query-builder/SelectQueryBuilder.ts:1861:14)
    at SelectQueryBuilder.<anonymous> (/usr/src/app/src/query-builder/SelectQueryBuilder.ts:1779:46)

    at step (/usr/src/app/node_modules/tslib/tslib.js:133:27)
    at Object.next (/usr/src/app/node_modules/tslib/tslib.js:114:57)
    at /usr/src/app/node_modules/tslib/tslib.js:107:75
    at new Promise (<anonymous>)
    at Object.__awaiter (/usr/src/app/node_modules/tslib/tslib.js:103:16)
    at SelectQueryBuilder.executeEntitiesAndRawResults (/usr/src/app/node_modules/typeorm/query-builder/SelectQueryBuilder.js:1313:24)

是的,当我尝试按

loadRelationCountAndMap

中的这 4 个字段中的任何一个进行排序时,就会出现错误

这是 PostEntity 和我获取帖子的整个功能:

export class PostEntity extends AbstractEntity {

    @Column({name: 'title', nullable: true})
    public title: string;

    @Column('text', {name: 'content', nullable: true})
    public content: string;

    @Column({name: 'video_url', nullable: true})
    public videoUrl: string;

    @Column('json', {name: 'media', nullable: true})
    public media: string[];

    @Column('enum', {enum: PostStatus, name: 'status', default: PostStatus.IN_REVIEW})
    public status: PostStatus;

    @Column('enum', {enum: PostType, name: 'type', default: PostType.POST})
    public type: PostType;

    @ManyToOne(() => User, object => object.posts, {nullable: false, onDelete: 'CASCADE'})
    @JoinColumn({name: 'author_id'})
    public author: User;

    @Column({name: 'author_id'})
    public authorId: number;

    @OneToMany(() => PostComment, object => object.post)
    public comments: PostComment[];

    @ManyToMany(() => User, object => object.votedPosts)
    public voters: User[];

    @ManyToMany(() => User, object => object.sharedPosts)
    public distributors: User[];

    @OneToMany(() => PostReport, postReport => postReport.post)
    public reports: PostReport[];

    @ManyToMany(() => TagEntity, object => object.posts, {cascade: ['insert', 'update']})
    @JoinTable({
        name: 'app_post_tags',
        joinColumn: {name: 'post_id', referencedColumnName: 'id'},
        inverseJoinColumn: {name: 'tag_id', referencedColumnName: 'id'}
    })
    public tags: TagEntity[];

    @ManyToOne(() => PostCategory, object => object.posts, {nullable: true, onDelete: 'SET NULL'})
    @JoinColumn({name: 'category_id'})
    public category: PostCategory;

    @ManyToOne(() => RewardTransfer, {nullable: true, onDelete: 'SET NULL'})
    @JoinColumn({name: 'reward_id'})
    public reward: RewardTransfer;

    @ManyToMany(() => User, {cascade: ['insert', 'update']})
    @JoinTable({
        name: 'app_post_mentions',
        joinColumn: {name: 'post_id', referencedColumnName: 'id'},
        inverseJoinColumn: {name: 'user_id', referencedColumnName: 'id'}
    })
    public mentions: User[];

    @OneToMany(() => Account, account => account.user)
    public accounts: Account[];

    @OneToMany(() => PostView, postView => postView.post)
    public views: PostView[];

    @OneToOne(() => PinnedPostEntity, object => object.post)
    public pinnedPost: PinnedPostEntity;

}

public async findMany(request: Request, userId?: number): Promise<FeedDto[]> {

        return getManager().transaction(async entityManager => {

            const filter: IPostFeedQuery = request.query;

            const qb = entityManager.createQueryBuilder(PostEntity, 'alias');

            qb.leftJoin('alias.author', 'author')
                .addSelect(['author.id', 'author.firstName', 'author.lastName', 'author.pictureUrl']);

            qb.where('alias.status IN (:...statuses)', {
                statuses: [PostStatus.PUBLISHED,
                    ...(filter.userId && userId && filter.userId === userId ? [PostStatus.IN_REVIEW] : [])]
            });

            qb.leftJoinAndSelect('alias.category', 'category');

            if (filter.userId) {
                qb.andWhere('author.id = :authorId', {authorId: filter.userId});
            }

            if (filter.category) {
                qb.andWhere('category.slug = :category', {category: filter.category});
            }

            if (filter.type) {
                qb.andWhere('alias.type = :type', {type: filter.type});
            } else {
                qb.andWhere('alias.type <> :ignoredType', {ignoredType: PostType.FORUM_TOPIC});
            }

            if (filter.tag) {
                qb.leftJoin('alias.tags', 'tags')
                    .andWhere('tags.slug = :tag', {tag: filter.tag});
            }

            qb.loadRelationCountAndMap('alias.commentsCount', 'alias.comments');
            qb.loadRelationCountAndMap('alias.votesCount', 'alias.voters');
            qb.loadRelationCountAndMap('alias.viewsCount', 'alias.views');
            qb.loadRelationCountAndMap('alias.sharesCount', 'alias.distributors');

            qb.orderBy('alias.viewsCount', 'DESC');

            if (userId) {
                qb.leftJoin(
                    'alias.voters',
                    'voters',
                    'voters.id = :userId', {userId}).addSelect(['voters.id']);
                qb.leftJoin(
                    'alias.reports',
                    'reports',
                    'reports.reporter = :userId', {userId}).addSelect(['reports.createdAt']);
                qb.leftJoin(
                    'alias.distributors',
                    'distributors',
                    'distributors.id = :userId', {userId}).addSelect(['distributors.id']);
            }

            const data = await this.apiService.setPagination<PostEntity>(request, qb);
            return data.map(value => new FeedDto(value));
        });
    }

抱歉代码太多,感谢您的帮助。

javascript typescript sql-order-by nestjs typeorm
1个回答
0
投票

orderBy (addOrderBy) 的查询生成器行为与其他 typeorm 方法不同,您必须使用实体属性名称而不是数据库名称。

例如:

class UserEntiy {
    id: string;

    createdAt: Date; // but in your database this field in snake_case
}

async getManyUsers(): Promise<[users: UserEnity[], total: number]> {
    const qb = qb.createQueryBuilder('u');

    qb.where(`u.created_at < NOW()`); // snake_case
    qb.orderBy(`u.createdAt`, 'DESC'); // entity camelCase

    return qb.getManyAndCount();
}

其他情况可以搜索https://github.com/typeorm/typeorm/issues/747

© www.soinside.com 2019 - 2024. All rights reserved.