优化计划查询避免 N+1 数据库访问
This commit is contained in:
@@ -203,11 +203,13 @@
|
||||
|
||||
## 可重构/可优化项(非阻塞,但收益高)
|
||||
|
||||
### R1 计划查询存在 N+1 查询模式
|
||||
### R1 计划查询存在 N+1 查询模式【已完成】
|
||||
- 修复状态:✅ 已完成(2026-03-03)
|
||||
- 修复内容:
|
||||
- `getPendingPlans`、`getHistoryPlans` 改为在 `weekendPlan.findMany` 中直接 `select room { name, code }`;
|
||||
- 移除逐条 `findUnique` 查房间的 N+1 查询路径。
|
||||
- 证据:
|
||||
- `src/lib/planQueries.ts:30-36`、`63-68`(每条计划单独查房间)
|
||||
- 建议:
|
||||
- 使用 `include` / 批量映射一次性拉取房间信息,减少 DB 往返。
|
||||
- `src/lib/planQueries.ts` 已由“逐条房间查询”改为“单次查询带房间关系”。
|
||||
|
||||
### R2 `atomicUpdateRoom` 对 likes 的“全删全建”策略成本较高
|
||||
- 证据:
|
||||
|
||||
+39
-41
@@ -1,5 +1,4 @@
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { ApiError } from "@/lib/api";
|
||||
|
||||
export async function getLatestPlan(roomId: string, userId: string) {
|
||||
const plan = await prisma.weekendPlan.findFirst({
|
||||
@@ -23,28 +22,27 @@ export async function getPendingPlans(userId: string) {
|
||||
endTime: { not: null, lt: new Date() },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: { id: true, planData: true, roomId: true, createdAt: true },
|
||||
select: {
|
||||
id: true,
|
||||
planData: true,
|
||||
createdAt: true,
|
||||
room: { select: { name: true, code: true } },
|
||||
},
|
||||
take: 5,
|
||||
});
|
||||
|
||||
const result = await Promise.all(
|
||||
plans.map(async (p) => {
|
||||
const room = await prisma.blindBoxRoom.findUnique({
|
||||
where: { id: p.roomId },
|
||||
select: { name: true, code: true },
|
||||
});
|
||||
const parsed = JSON.parse(p.planData);
|
||||
const days = parsed.days as { date: string; items: { activity: string }[] }[];
|
||||
return {
|
||||
id: p.id,
|
||||
roomName: room?.name ?? "未知房间",
|
||||
roomCode: room?.code ?? "",
|
||||
date: days.map((d) => d.date).join(" + "),
|
||||
activities: days.flatMap((d) => d.items.map((i) => i.activity)),
|
||||
createdAt: p.createdAt,
|
||||
};
|
||||
}),
|
||||
);
|
||||
const result = plans.map((p) => {
|
||||
const parsed = JSON.parse(p.planData);
|
||||
const days = parsed.days as { date: string; items: { activity: string }[] }[];
|
||||
return {
|
||||
id: p.id,
|
||||
roomName: p.room?.name ?? "未知房间",
|
||||
roomCode: p.room?.code ?? "",
|
||||
date: days.map((d) => d.date).join(" + "),
|
||||
activities: days.flatMap((d) => d.items.map((i) => i.activity)),
|
||||
createdAt: p.createdAt,
|
||||
};
|
||||
});
|
||||
|
||||
return { pending: result };
|
||||
}
|
||||
@@ -56,30 +54,30 @@ export async function getHistoryPlans(userId: string) {
|
||||
status: { in: ["completed", "expired"] },
|
||||
},
|
||||
orderBy: { createdAt: "desc" },
|
||||
select: { id: true, planData: true, status: true, roomId: true, createdAt: true },
|
||||
select: {
|
||||
id: true,
|
||||
planData: true,
|
||||
status: true,
|
||||
createdAt: true,
|
||||
room: { select: { name: true, code: true } },
|
||||
},
|
||||
take: 50,
|
||||
});
|
||||
|
||||
const result = await Promise.all(
|
||||
plans.map(async (p) => {
|
||||
const room = await prisma.blindBoxRoom.findUnique({
|
||||
where: { id: p.roomId },
|
||||
select: { name: true, code: true },
|
||||
});
|
||||
const parsed = JSON.parse(p.planData);
|
||||
const days = parsed.days as { date: string; items: { activity: string }[] }[];
|
||||
return {
|
||||
id: p.id,
|
||||
status: p.status,
|
||||
roomName: room?.name ?? "未知房间",
|
||||
roomCode: room?.code ?? "",
|
||||
date: days.map((d) => d.date).join(" + "),
|
||||
dayCount: days.length,
|
||||
activities: days.flatMap((d) => d.items.map((i) => i.activity)),
|
||||
createdAt: p.createdAt,
|
||||
};
|
||||
}),
|
||||
);
|
||||
const result = plans.map((p) => {
|
||||
const parsed = JSON.parse(p.planData);
|
||||
const days = parsed.days as { date: string; items: { activity: string }[] }[];
|
||||
return {
|
||||
id: p.id,
|
||||
status: p.status,
|
||||
roomName: p.room?.name ?? "未知房间",
|
||||
roomCode: p.room?.code ?? "",
|
||||
date: days.map((d) => d.date).join(" + "),
|
||||
dayCount: days.length,
|
||||
activities: days.flatMap((d) => d.items.map((i) => i.activity)),
|
||||
createdAt: p.createdAt,
|
||||
};
|
||||
});
|
||||
|
||||
return { history: result };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user