如何通过Prisma按最新ProductEvent的status过滤Product?
解决方案:按最新ProductEvent的status筛选Product
首先明确:你原来的查询逻辑问题在于,include中的orderBy和take仅控制返回的关联数据,不会影响where子句的过滤规则——where.events.some会检查该Product的所有关联事件,而非你指定的最新那一条。
以下是几种可行的实现方式:
方法1:利用子查询匹配最新事件状态(Prisma ORM写法)
通过子查询获取每个Product的最新事件时间,再筛选状态匹配的记录:
const targetStatus = "WHATEVER_STATUS"; await this.client.product.findMany({ include: { events: { orderBy: { datetime: "desc" }, take: 1, }, }, where: { events: { some: { status: targetStatus, // 限定该事件是当前Product的最新事件 datetime: { equals: Prisma.sql`(SELECT MAX(datetime) FROM "ProductEvent" WHERE "productId" = "Product"."productId")` } } } } });
方法2:使用Exists子查询(更严谨的过滤)
如果需要避免匹配到多个同时间的最新事件(比如某Product有多个同一时间的事件),可以用exists子查询精准定位:
const targetStatus = "WHATEVER_STATUS"; await this.client.product.findMany({ include: { events: { orderBy: { datetime: "desc" }, take: 1, }, }, where: { exists: { select: { productId: true }, from: "ProductEvent", where: { productId: Prisma.sql`"Product"."productId"`, status: targetStatus, datetime: Prisma.sql`(SELECT MAX(datetime) FROM "ProductEvent" WHERE "productId" = "Product"."productId")` } } } });
方法3:原生SQL查询(性能最优)
当数据量较大时,原生SQL的关联查询性能更优,逻辑是先预查询每个Product的最新事件,再关联筛选:
const targetStatus = "WHATEVER_STATUS"; const result = await this.client.$queryRaw` SELECT p.*, e.* FROM "Product" p INNER JOIN ( -- 子查询获取每个Product的最新事件 SELECT pe."productId", pe."datetime", pe."status", pe."productEventId" FROM "ProductEvent" pe WHERE (pe."productId", pe."datetime") IN ( SELECT "productId", MAX("datetime") FROM "ProductEvent" GROUP BY "productId" ) ) e ON p."productId" = e."productId" WHERE e."status" = ${targetStatus}; `;
内容的提问来源于stack exchange,提问作者sharkdarras
相关产品推荐
相关产品推荐

