feat: 新增标签分类体系与固定类型筛选优化
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import {
|
||||
FIXED_PROJECT_TYPE_TAGS,
|
||||
inferProjectTypeSlug,
|
||||
inferTagCategory,
|
||||
} from '../src/lib/tag-taxonomy'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
async function ensureFixedProjectTypeTags() {
|
||||
const result = await Promise.all(
|
||||
FIXED_PROJECT_TYPE_TAGS.map((item) =>
|
||||
prisma.tag.upsert({
|
||||
where: { slug: item.slug },
|
||||
update: {
|
||||
name: item.name,
|
||||
nameEn: item.nameEn,
|
||||
category: 'FIXED_PROJECT_TYPE',
|
||||
},
|
||||
create: {
|
||||
name: item.name,
|
||||
nameEn: item.nameEn,
|
||||
slug: item.slug,
|
||||
category: 'FIXED_PROJECT_TYPE',
|
||||
},
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
return new Map(result.map((tag) => [tag.slug, tag.id]))
|
||||
}
|
||||
|
||||
async function backfillTagCategories() {
|
||||
const tags = await prisma.tag.findMany()
|
||||
let updated = 0
|
||||
|
||||
for (const tag of tags) {
|
||||
const inferredCategory = inferTagCategory({
|
||||
slug: tag.slug,
|
||||
name: tag.name,
|
||||
nameEn: tag.nameEn,
|
||||
})
|
||||
|
||||
if (tag.category !== inferredCategory) {
|
||||
await prisma.tag.update({
|
||||
where: { id: tag.id },
|
||||
data: { category: inferredCategory },
|
||||
})
|
||||
updated += 1
|
||||
}
|
||||
}
|
||||
|
||||
return updated
|
||||
}
|
||||
|
||||
async function backfillProjectFixedTypes(fixedTypeIdMap: Map<string, string>) {
|
||||
const projects = await prisma.project.findMany({
|
||||
where: { status: 'ACTIVE' },
|
||||
include: {
|
||||
tags: {
|
||||
include: {
|
||||
tag: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const createData: Array<{ projectId: string; tagId: string }> = []
|
||||
|
||||
for (const project of projects) {
|
||||
const fixedTypeSlug = inferProjectTypeSlug({
|
||||
name: project.name,
|
||||
nameEn: project.nameEn,
|
||||
description: project.description,
|
||||
descriptionEn: project.descriptionEn,
|
||||
tags: project.tags.map((tag) => ({
|
||||
slug: tag.tag.slug,
|
||||
name: tag.tag.name,
|
||||
nameEn: tag.tag.nameEn,
|
||||
})),
|
||||
})
|
||||
|
||||
const fixedTypeTagId = fixedTypeIdMap.get(fixedTypeSlug)
|
||||
if (!fixedTypeTagId) {
|
||||
throw new Error(`Missing fixed project type tag: ${fixedTypeSlug}`)
|
||||
}
|
||||
|
||||
createData.push({
|
||||
projectId: project.id,
|
||||
tagId: fixedTypeTagId,
|
||||
})
|
||||
}
|
||||
|
||||
const removed = await prisma.projectTag.deleteMany({
|
||||
where: {
|
||||
tag: {
|
||||
category: 'FIXED_PROJECT_TYPE',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const inserted = await prisma.projectTag.createMany({
|
||||
data: createData,
|
||||
skipDuplicates: true,
|
||||
})
|
||||
|
||||
return {
|
||||
projectCount: projects.length,
|
||||
inserted: inserted.count,
|
||||
removed: removed.count,
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('[taxonomy] start')
|
||||
|
||||
const fixedTypeIdMap = await ensureFixedProjectTypeTags()
|
||||
const updatedTagCategoryCount = await backfillTagCategories()
|
||||
const projectResult = await backfillProjectFixedTypes(fixedTypeIdMap)
|
||||
|
||||
console.log('[taxonomy] done', {
|
||||
updatedTagCategoryCount,
|
||||
projectCount: projectResult.projectCount,
|
||||
insertedProjectTypeLinks: projectResult.inserted,
|
||||
removedOldProjectTypeLinks: projectResult.removed,
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error('[taxonomy] failed', error)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
||||
Reference in New Issue
Block a user