先使用 hydrooj backup 备份数据库。
使用 hydrooj db 命令进入 mongosh,然后执行下面的命令定义比赛删除函数:
// 定义一个删除比赛的函数,参数为 domainId(域ID)和 tid(比赛ID)
function deleteContest(domainId, tid) {
// 如果 tid 传的是字符串,转成 ObjectId;已经是 ObjectId 就保持原样
tid = (typeof tid === "string") ? ObjectId(tid) : tid;
// 查出该比赛下所有「答疑」文档(docType=31)的 _id 列表
// 先 toArray() 物化成普通对象再 map,避免游标代理的循环引用问题
const cids = db.document.find({ domainId, docType: 31, parentType: 30, parentId: tid }).toArray().map(d => d._id);
// 查出该比赛下所有「打印任务」文档(docType=32)的 _id 列表
const pids = db.document.find({ domainId, docType: 32, parentType: 30, parentId: tid }).toArray().map(d => d._id);
// 删除比赛文档本身(docType=30, docId=tid)
db.document.deleteMany({ domainId, docType: 30, docId: tid });
// 删除该比赛的参赛状态(document.status 集合,docType=30)
db["document.status"].deleteMany({ domainId, docType: 30, docId: tid });
// 删除挂在比赛下的讨论(parentType=30, parentId=tid)
db.document.deleteMany({ domainId, parentType: 30, parentId: tid });
// 如果有答疑,删除这些答疑文档
if (cids.length) {
db.document.deleteMany({ _id: { $in: cids } });
// 一并删除这些答疑对应的状态文档
db["document.status"].deleteMany({ domainId, docType: 31, docId: { $in: cids } });
}
// 如果有打印任务,删除这些打印文档
if (pids.length) {
db.document.deleteMany({ _id: { $in: pids } });
// 一并删除这些打印任务对应的状态文档
db["document.status"].deleteMany({ domainId, docType: 32, docId: { $in: pids } });
}
// 删除该比赛的气球记录(contest.balloon 集合)
db["contest.balloon"].deleteMany({ domainId, tid });
// 删除该比赛的定时隐藏任务(schedule 集合)
db.schedule.deleteMany({ type: "schedule", subType: "contest", domainId, tid });
// 比赛内提交记录【保留】,仅解除与比赛的关联(unset contest 字段)
db.record.updateMany({ domainId, contest: tid }, { $unset: { contest: "" } });
// 返回完成提示
return "done: contest " + tid;
}之后调用函数来删除比赛:
// 调用函数,删除指定域下指定 ID 的比赛(示例参数,请替换为真实值)
deleteContest("system", "contestId");说明几个字段含义,便于核对:
- docType:30=比赛,31=答疑,32=打印任务(定义在
document.ts)。 parentType: 30, parentId: tid:表示「挂在tid这场比赛下的子文档」(讨论/答疑/打印都用这个关联)。document.status是独立集合(collStatus),所以比赛、答疑、打印的状态都单独再删一遍。