| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /**
- * 修复 Book 5 的章节数据混乱问题
- *
- * 问题:大量 level=1 但 number > 20 的异常记录(这些本应是 level=3 的小节)
- * 还有些节的 parentId 指向了这些异常的 level=1 记录
- */
- const { PrismaClient } = require('./node_modules/@prisma/client');
- const prisma = new PrismaClient();
- async function main() {
- const bookId = 5;
- console.log('=== 开始修复 Book 5 章节数据 ===\n');
- // 1. 找出正常的章(level=1, number <= 20, parentId=0)
- const normalChapters = await prisma.bookChapter.findMany({
- where: { bookId, level: 1, parentId: 0, number: { lte: 20 } },
- orderBy: { number: 'asc' },
- });
- console.log('正常章:', normalChapters.map(c => `ID=${c.id}, number=${c.number}`).join(', '));
- // 2. 找出所有 level=1 但 number > 20 或 parentId != 0 的异常记录
- const abnormalLevel1 = await prisma.bookChapter.findMany({
- where: {
- bookId,
- level: 1,
- OR: [
- { number: { gt: 20 } },
- { parentId: { not: 0 } }
- ]
- },
- orderBy: { number: 'asc' },
- });
- console.log(`\n发现 ${abnormalLevel1.length} 条 level=1 的异常记录:`);
- abnormalLevel1.forEach(r => console.log(` ID=${r.id}, number=${r.number}, parentId=${r.parentId}, title=${r.title.substring(0, 40)}`));
- // 3. 找出所有 level=2 且 parentId 指向异常 level=1 记录的节
- const abnormalParentIds = abnormalLevel1.map(r => r.id);
- const sectionsWithAbnormalParent = await prisma.bookChapter.findMany({
- where: {
- bookId,
- level: 2,
- parentId: { in: abnormalParentIds }
- }
- });
- console.log(`\n发现 ${sectionsWithAbnormalParent.length} 条节指向异常父节点:`);
- sectionsWithAbnormalParent.forEach(r => console.log(` ID=${r.id}, number=${r.number}, parentId=${r.parentId}`));
- // 4. 删除策略:
- // a. 先删除所有 level=3 且 parentId 指向异常节或异常章的记录
- // b. 删除所有 level=2 且 parentId 指向异常 level=1 的记录
- // c. 删除所有异常的 level=1 记录
- // 收集所有需要删除的 parentId
- const abnormalSectionIds = sectionsWithAbnormalParent.map(r => r.id);
- const abnormalChapterIds = abnormalLevel1.map(r => r.id);
- const allInvalidParentIds = [...abnormalSectionIds, ...abnormalChapterIds];
- // 4a. 删除 level=3 且 parentId 指向无效父节点的记录
- if (allInvalidParentIds.length > 0) {
- const deleteLevel3 = await prisma.bookChapter.deleteMany({
- where: {
- bookId,
- level: 3,
- parentId: { in: allInvalidParentIds }
- }
- });
- console.log(`\n删除 ${deleteLevel3.count} 条 level=3 记录(parentId 指向无效父节点)`);
- }
- // 4b. 删除 level=2 且 parentId 指向异常 level=1 的记录
- if (abnormalParentIds.length > 0) {
- const deleteLevel2 = await prisma.bookChapter.deleteMany({
- where: {
- bookId,
- level: 2,
- parentId: { in: abnormalParentIds }
- }
- });
- console.log(`删除 ${deleteLevel2.count} 条 level=2 记录(parentId 指向异常 level=1)`);
- }
- // 4c. 删除异常的 level=1 记录
- if (abnormalLevel1.length > 0) {
- const deleteLevel1 = await prisma.bookChapter.deleteMany({
- where: {
- id: { in: abnormalLevel1.map(r => r.id) }
- }
- });
- console.log(`删除 ${deleteLevel1.count} 条异常 level=1 记录`);
- }
- // 5. 验证修复结果
- console.log('\n=== 修复后验证 ===');
- const remainingLevel1 = await prisma.bookChapter.count({
- where: { bookId, level: 1, parentId: 0 }
- });
- console.log(`剩余 level=1 记录: ${remainingLevel1} 条`);
- const remainingLevel2 = await prisma.bookChapter.count({
- where: { bookId, level: 2 }
- });
- console.log(`剩余 level=2 记录: ${remainingLevel2} 条`);
- const remainingLevel3 = await prisma.bookChapter.count({
- where: { bookId, level: 3 }
- });
- console.log(`剩余 level=3 记录: ${remainingLevel3} 条`);
- // 6. 显示修复后的正常结构
- console.log('\n修复后的章结构:');
- const chaptersAfter = await prisma.bookChapter.findMany({
- where: { bookId, level: 1, parentId: 0 },
- orderBy: { number: 'asc' },
- select: { id: true, number: true, title: true }
- });
- chaptersAfter.forEach(c => console.log(` [章${c.number}] ID=${c.id}: ${c.title}`));
- console.log('\n修复后的节数量分布:');
- for (const chapter of chaptersAfter) {
- const sectionsCount = await prisma.bookChapter.count({
- where: { bookId, level: 2, parentId: chapter.id }
- });
- console.log(` 章${chapter.number} (ID=${chapter.id}): ${sectionsCount} 个节`);
- }
- }
- main()
- .catch(console.error)
- .finally(() => prisma.$disconnect());
|