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

如何用TypeORM单查询获取含最新帖子的用户列表(NestJS+MySQL)

获取带有最新单条帖子的用户列表(TypeORM解决方案)

问题背景

使用Nest.js + TypeORM + MySQL技术栈,实体定义如下:

@Entity()
export class User {
    @PrimaryGeneratedColumn('uuid')
    id: string

    @Column()
    name: string

    @OneToMany(() => Post, post => post.user)
    posts: Post[]
}

@Entity()
export class Post {
    @PrimaryGeneratedColumn('uuid')
    id: string

    @Column()
    title: string

    @ManyToOne(() => User, user => user.posts)
    user: User

    @CreateDateColumn()
    created_at: Date
}

尝试通过以下查询获取每个用户的最新单条帖子,但查询未按帖子created_at倒序筛选出最新帖子:

import { getRepository } from 'typeorm';
import { User } from './entities/User';
import { Post } from './entities/Post';

const usersWithPosts = await getRepository(User)
  .createQueryBuilder('user')
  .leftJoinAndMapOne(
    'user.post', // Map the 'post' property of the 'user' entity
    Post,        // Target entity
    'post',      // Alias for the 'post' entity
    'user.id = post.userId', // ON condition for the join
    qb => qb.orderBy('post.created_at', 'DESC') // Order posts here
  )
  .orderBy('user.name', 'ASC') // Order users here
  .getMany();

需要仅使用TypeORM查询(不使用原生SQL)实现需求。

解决方案

方法一:子查询排序后限制返回数量

leftJoinAndMapOne需要明确限制子查询返回单条记录,仅排序无法确保只取最新帖子。修改后代码如下:

const usersWithPosts = await getRepository(User)
  .createQueryBuilder('user')
  .leftJoinAndMapOne(
    'user.latestPost', // 映射到用户的新属性latestPost
    (subQuery) => subQuery
      .select('post.*')
      .from(Post, 'post')
      .where('post.userId = user.id')
      .orderBy('post.created_at', 'DESC')
      .limit(1), // 仅取最新的一条帖子
    'latestPost',
    'user.id = latestPost.userId'
  )
  .orderBy('user.name', 'ASC')
  .getMany();

方法二:通过子查询匹配最新创建时间

若需避免同一时间多条帖子的歧义,可先查询每个用户帖子的最新创建时间,再关联匹配对应帖子:

const usersWithPosts = await getRepository(User)
  .createQueryBuilder('user')
  .leftJoinAndMapOne(
    'user.latestPost',
    Post,
    'latestPost',
    `latestPost.userId = user.id 
     AND latestPost.created_at = (
       SELECT MAX(p.created_at) FROM post p WHERE p.userId = user.id
     )`
  )
  .orderBy('user.name', 'ASC')
  .getMany();

注意事项

  • 需在User实体中临时添加latestPost?: Post属性,用于映射查询结果;
  • 方法一更简洁高效,适合绝大多数场景;方法二在存在同一时间多条帖子时,会返回该时间点的任意一条(若需全部返回,可改用leftJoinAndMapMany)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:22:36