import 'server-only'; import { db } from "@/shared/db"; import { questions, questionsToKnowledgePoints } from "@/shared/db/schema"; import { and, count, desc, eq, inArray, sql, type SQL } from "drizzle-orm"; import { cache } from "react"; import type { Question, QuestionType } from "./types"; export type GetQuestionsParams = { q?: string; page?: number; pageSize?: number; ids?: string[]; knowledgePointId?: string; type?: QuestionType; difficulty?: number; }; export const getQuestions = cache(async ({ q, page = 1, pageSize = 50, ids, knowledgePointId, type, difficulty, }: GetQuestionsParams = {}) => { const offset = (page - 1) * pageSize; const conditions: SQL[] = []; if (ids && ids.length > 0) { conditions.push(inArray(questions.id, ids)); } if (q && q.trim().length > 0) { const needle = `%${q.trim().toLowerCase()}%`; conditions.push( sql`LOWER(CAST(${questions.content} AS CHAR)) LIKE ${needle}` ); } if (type) { conditions.push(eq(questions.type, type)); } if (difficulty) { conditions.push(eq(questions.difficulty, difficulty)); } if (knowledgePointId) { const subQuery = db .select({ questionId: questionsToKnowledgePoints.questionId }) .from(questionsToKnowledgePoints) .where(eq(questionsToKnowledgePoints.knowledgePointId, knowledgePointId)); conditions.push(inArray(questions.id, subQuery)); } if (!ids || ids.length === 0) { conditions.push(sql`${questions.parentId} IS NULL`) } const whereClause = conditions.length > 0 ? and(...conditions) : undefined; const [totalResult] = await db .select({ count: count() }) .from(questions) .where(whereClause); const total = Number(totalResult?.count ?? 0); const rows = await db.query.questions.findMany({ where: whereClause, limit: pageSize, offset: offset, orderBy: [desc(questions.createdAt)], with: { questionsToKnowledgePoints: { with: { knowledgePoint: true, }, }, author: { columns: { id: true, name: true, image: true, }, }, children: true, }, }); return { data: rows.map((row) => { const knowledgePoints = row.questionsToKnowledgePoints?.map((rel) => rel.knowledgePoint) ?? []; const author = row.author ? { id: row.author.id, name: row.author.name, image: row.author.image, } : null; const mapped: Question = { id: row.id, content: row.content, type: row.type, difficulty: row.difficulty ?? 1, createdAt: row.createdAt, updatedAt: row.updatedAt, author, knowledgePoints: knowledgePoints.map((kp) => ({ id: kp.id, name: kp.name })), childrenCount: row.children?.length ?? 0, }; return mapped; }), meta: { page, pageSize, total, totalPages: Math.ceil(total / pageSize), }, }; });