You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MikroORM中按嵌套实体Entity3的最大updatedAt排序查询Entity1

在MikroORM中按嵌套Entity3的updatedAt排序Entity1的findAndCount查询

首先,你需要通过关联查询将Entity2和Entity3纳入查询上下文,再基于Entity3的updatedAt字段对Entity1排序。由于是一对多嵌套关系,单个Entity1可能对应多个Entity3,通常取每个Entity1关联的Entity3中最新的updatedAt值作为排序依据。

实体定义参考(简化版)

@Entity()
export class Entity1 {
  @PrimaryKey()
  id!: number;

  @OneToMany(() => Entity2, entity2 => entity2.entity1)
  entity2s = new Collection<Entity2>(this);
}

@Entity()
export class Entity2 {
  @PrimaryKey()
  id!: number;

  @ManyToOne(() => Entity1)
  entity1!: Entity1;

  @OneToMany(() => Entity3, entity3 => entity3.entity2)
  entity3s = new Collection<Entity3>(this);
}

@Entity()
export class Entity3 {
  @PrimaryKey()
  id!: number;

  @ManyToOne(() => Entity2)
  entity2!: Entity2;

  @Property()
  updatedAt!: Date;
}

核心查询写法

const [entities, count] = await orm.em.findAndCount(Entity1, {}, {
  // 关联加载嵌套实体,确保能访问到Entity3的字段
  populate: ['entity2s.entity3s'],
  // 用子查询获取每个Entity1对应的最新Entity3的updatedAt,以此作为排序键
  orderBy: {
    $expr: (qb) => qb.select('MAX(e3.updatedAt)')
      .from(Entity3, 'e3')
      .innerJoin('e3.entity2', 'e2')
      .where('e2.entity1.id = entity1.id'),
  },
  // 指定排序方向:DESC为倒序(最新的在前),ASC为升序
  orderByDirection: 'DESC',
});

关键说明

  • 关联加载 vs 仅关联表:如果不需要返回Entity2和Entity3的具体数据,可替换populate为join,仅关联表而不加载数据:
    join: {
      entity2s: {
        entity3s: true,
      },
    },
    
  • 避免重复记录:子查询方式能确保每个Entity1只返回一次,直接关联排序会因一对多关系产生重复的Entity1条目。
  • 分组排序替代方案:也可通过左连接+分组实现相同效果:
    const [entities, count] = await orm.em.findAndCount(Entity1, {}, {
      join: {
        leftJoinAndSelect: {
          e2: 'entity1.entity2s',
          e3: 'e2.entity3s',
        },
      },
      groupBy: ['entity1.id'],
      orderBy: {
        'MAX(e3.updatedAt)': 'DESC',
      },
    });
    

内容的提问来源于stack exchange,提问作者vicebas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:14:58