【问题标题】:typeorm select OneToMany entity by last createdAttypeorm 按最后创建时间选择 OneToMany 实体
【发布时间】:2021-07-06 15:08:27
【问题描述】:

我认为有一个非常典型的问题 - 通过 typeorm 选择 OneToMany 关系的最新实体的正确方法是什么? db 是postgresql

@Entity('hubs')
export class Hub {

    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column()
    ip: string;

    @OneToMany(type => HubStatus, statusLog => statusLog.hub, { cascade: true })
    statusLog: Array<HubStatus>;

    @UpdateDateColumn()
    updatedAt: Date;

    lastStatus: any;

    @AfterLoad()
    async getStatus() {
          const query = createQueryBuilder(Hub)
            .leftJoinAndSelect("Hub.statusLog", "statusLog", 'Hub.id = :id', { id: this.id })
            //.addSelect("MAX(statusLog.createdAt)")
            //.andHaving('statusLog.createdAt = MAX(statusLog.createdAt)');
            //.andWhere('Hub.id = :id', { id: this.id })
            //.andWhere('statusLog.createdAt = MAX(statusLog.createdAt)');

          //assign part of result to this.lastStatus
    }
}

@Entity('hub-status')
export class HubStatus {

    @PrimaryGeneratedColumn()
    id: string;

    @Column({type: 'json')
    somecolumn

    @ManyToOne(type => Hub, hub => hub.statusLog)
    hub: Hub;

    @CreateDateColumn()
    createdAt: Date;
}

我想在@AfterLoad 块中获取最新的(通过 createdAt)关联的HubStatusmax 不能在where 子句中使用,我还尝试了在select 中使用max 的多种选项,但由于不同的原因它们失败了。

【问题讨论】:

    标签: javascript postgresql typescript typeorm


    【解决方案1】:

    我是这样做的,所以它至少可以用于开发目的:

    @AfterLoad()
    async getStatus() {
        const innerSelect = getRepository(HubStatus)
            .createQueryBuilder()
            .select('id')
            .where('HubStatus.hub.id = :id')
            .orderBy('id', "DESC")
            .limit(1);
    
        const query = createQueryBuilder(Hub)
            .select('somecolumn')
            .leftJoin(`Hub.statusLog`, "statusLog", `statusLog.id = (${innerSelect.getSql()})`, { id: this.id })
    
        this.lastStatus = (await query.getRawOne()).somecolumn;
    }
    

    但问题仍然悬而未决 - HubStatus 中可能会有数百万个条目,如果认为 ORDER BY + LIMIT 1 解决方案在这种情况下表现不佳。

    【讨论】:

      【解决方案2】:

      另一种方法是在连接条件中使用leftJoinAndMapOne 查询构建器方法和NOT EXISTS SQL 条件来测试以后的实体:

            const query = createQueryBuilder(Hub)
              .leftJoinAndMapOne('Hub.statusLog', HubStatus, 'statusLog',
               `Hub.id = statusLog.hubId AND NOT EXISTS (
               SELECT 1 FROM hub-status hs1 WHERE hs1.hubId = Hub.id AND hs1.id > statusLog.id)`,
              ).getMany()
      

      【讨论】:

        猜你喜欢
        • 2021-05-20
        • 1970-01-01
        • 2019-07-27
        • 1970-01-01
        • 2019-11-13
        • 1970-01-01
        • 2021-11-27
        • 2022-01-24
        • 1970-01-01
        相关资源
        最近更新 更多