【问题标题】:orderBy oneToMany relation using typeormorderBy oneToMany 关系使用 typeorm
【发布时间】:2021-04-04 22:06:45
【问题描述】:

我有 PublicationsEntity 与 LikesEntity 的 OneToMany 关系,我正在尝试按喜欢对我的出版物进行排序,并返回所有喜欢与喜欢关联的用户的喜欢,以及所有 cmet 以在前端显示它们

@Entity('publications')
export class PublicationsEntity {
        @PrimaryGeneratedColumn()
        id: number;
    
        @Column({ type: 'longtext' })
        publication: string;

        @ManyToOne(type => UsersEntity, users => users.publications, { 
        onDelete: "CASCADE" })
        user: UsersEntity;

        @OneToMany(type => CommentsEntity, comments => 
        comments.publication, { onDelete: "CASCADE" })
        comments: CommentsEntity[];
    
        @OneToMany(type => LikesEntity, likes => likes.publication, { onDelete: "CASCADE" })
        likes: LikesEntity[];
    }

有一个我喜欢的实体包含用户,我试图在排序后的出版物中返回每个喜欢的用户:

@Entity('likes')
export class LikesEntity {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    like: number;

    @ManyToOne(type => UsersEntity, user => user.likes, { eager: true })
    user: UsersEntity;

    @ManyToOne(type => PublicationsEntity, publication => publication.likes)
    publication: PublicationsEntity;
}

我的用户实体:

@Entity('users')
export class UsersEntity {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({ nullable: true })
    userName: string;

    @OneToMany(type => PublicationsEntity, publications => 
    publications.user, { onDelete: "CASCADE" })
    publications: PublicationsEntity[];

    @Column()
    email: string;

    @Column({ select: false })
    password: string;

    @OneToMany(type => CommentsEntity, comment => comment.user, { onDelete: "CASCADE" })
    comments: CommentsEntity[];

    @OneToMany(type => LikesEntity, like => like.user, { onDelete: "CASCADE" })
    likes: LikesEntity[];

    @OneToMany(type => PublicationsEntity, publications => publications.user, { onDelete: "CASCADE" })
    publications: PublicationsEntity[];

    @CreateDateColumn({ type: "timestamp", default: () => "CURRENT_TIMESTAMP(6)" })
    createdAt: Date;

    @UpdateDateColumn({ type: "timestamp", default: () => "CURRENT_TIMESTAMP(6)", onUpdate: "CURRENT_TIMESTAMP(6)" })
    updatedAt: Date;
}

还有我的 PublicationsService

async getPublications() {
    return await getConnection()
    .createQueryBuilder(PublicationsEntity, 'publications')
    .leftJoinAndSelect('publications.likes', 'likes')
    .leftJoinAndSelect('publications.user', 'user')
    .leftJoinAndSelect('publications.comments', 'comments')
    .leftJoinAndSelect('comments.children', 'children')
    //.orderBy()
    .getMany()
}

我点赞表上的一些数据:https://i.stack.imgur.com/wJ0l5.png

【问题讨论】:

    标签: nestjs typeorm


    【解决方案1】:

    首先,我认为你应该在你的实体上修复一些东西 在您的 PublicationsEntity 中

     @OneToMany(type => LikesEntity, likes => likes.publication, { onDelete: "CASCADE" })
        likes: LikesEntity[]; // this one should be an array
    

    对于 LikesEntity

    @ManyToOne(type => PublicationsEntity, publication => publication.likes)
    publication: PublicationsEntity;
    

    对于您的问题,我假设您想要返回按赞数排序的出版物,为此您应该在查询中添加:

    async getPublications() {
    return await getConnection()
    .createQueryBuilder(PublicationsEntity, 'publications')
    .leftJoin('publications.likes', 'likes')
    .addSelect("COUNT(likes.publication) AS total_likes" )
    .orderBy('total_likes', 'ASC') // or DESC
    .groupBy("likes.publication")
    .getRawMany()
      }
    

    更新

    据我从您下面的 cmets 中了解到,我认为您需要使用 map 和 sort 功能来获得所需的结果:

    async getPublications() {
    return await getConnection()
    .createQueryBuilder(PublicationsEntity, 'publications')
    .leftJoinAndSelect('publications.likes', 'likes')
    .leftJoinAndSelect('publications.user', 'user')
    .leftJoinAndSelect('publications.comments', 'comments')
    .leftJoinAndSelect('comments.children', 'children')
    //.orderBy()
    .getMany().then(data => data.map(a => ({ ...a, total_likes:a.likes.length })).sort(function (a, b) {
      return b.total_likes - a.total_likes; // this's going to sort by DESC if you want to make the opposite just do a.total_likes - b.total_likes
    })
    )
    

    }

    【讨论】:

    • 你好 Youba,谢谢你的回答,我试过了,我得到了以下错误:Error: ER_WRONG_FIELD_WITH_GROUP: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'jesaispas.publications.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
    • 尝试改变模式similar problem
    • 这能解决你的问题吗?
    • 是的,非常感谢您的帮助!我想知道你是否知道在 groupBy 和使用 getMany() 之类的过程中保留所有喜欢的方法,它按喜欢排序我的出版物,但我想在前面显示 likes.length 和 groupBy 接缝总是返回只有一个元素,即使我有例如一个具有 OneToMany 关系的行 cmets,例如 'Likes' 和 20 cmets,它也只返回一个项目,而且由于某些原因,我使用 ASC / DESC 的第一个项目总是与 0 相同的出版物,我不知道为什么
    • 我们不能在这种情况下使用 getMany,因为当您选择其他字段时,例如喜欢的计数 typeorm 无法将其映射到您定义的实体,因为在选择。因此,您必须将这些数据作为原始数据获取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多