首页 > 其他分享 >HydroOJ 从入门到入土(13)批量修改题号前缀

HydroOJ 从入门到入土(13)批量修改题号前缀

时间:2024-02-15 21:33:27浏览次数:27  
标签:13 前缀 数据库 pid HydroOJ 修改 备份 题号 hydro

题库的管理,无论是用前缀来分组,还是用域来分组,都有不好管理的地方,尤其是题号。有的时候导入了一堆题,导入完发现题号不是自己想要的,但删起来很麻烦,一个一个改更不现实,真是欲哭无泪。

本文主要记录了一次批量修改题号前缀的过程,仅供参考。

修改中涉及数据库操作,修改前一定要现在虚拟机上试过,然后做好备份!!!

数据库中需要修改的字段为本人自测,目前并未获得官方回复,如有回复再做更新。

目录

想法

主要需求是:在某一个域中,修改以指定前缀开头的一系列题目,把字母前缀改成别的。至于将指定范围内、或指定标签的所有题目改成别的前缀,这个以后再说。

我这次想将之前导入的所有的 P 前缀的一本通启蒙题目改成 B 前缀,一方面 B 既表示基础,排的也靠前,方便刚入门的学生查找;另一方面后边加其他前缀也不会影响 B 题库的位置,可以有 24 个字母放心加。

后期配合插件,在搜索栏下方做一排标签,就可以方便的在同一个域内跳转到相应题库,实现分组。这样可以避免使用域分组带来的无法直接引用题目的问题。

至于为什么不在一开始导入的时候就定好前缀?一是没有人一开始就能定下所有的事情,总会修修改改,二是可能会有误导入的情况。

一、备份

备份有两种,一种是在终端中直接使用 HydroOJ 自带的全量备份:

hydrooj backup

好处是方便安全,但坏处是,如果题库太大了,备份一次占地方不说,还会很久,恢复备份同理。

当然这次我为了安全,在本地虚拟机上测试的时候,还是用 hydrooj backup 做了全量备份,当做保底,然后准备用第二种方法:直接备份 MongoDB 数据库,还原的时候也是直接还原数据库。

这样的好处是快,备份和还原都快,改错了也不怕,可以快速修正。坏处是,还原的时候因为需要先清空数据库,所以带来一定的风险。

实际生产环境下,强烈建议两种备份都做好,放心点。

需要额外参考点这里查看官方文档。

MongoDB 备份

打开终端,以 root 用户身份运行:

# 备份到当前目录(.), 需要认证,备份完会出现一个数据库同名文件夹(hydro)
mongodump --db hydro --out . -u hydro -p 换成你的数据库密码 --authenticationDatabase hydro

这里如果需要备份到指定目录,就把 --out 后边的 . 换成指定目录就行了。

备份完记得确认当前目录下是否已经出现了名为 hydro 的备份文件夹,大概几十mb,里边是一堆 bson 格式的文件!

MongoDB 还原

打开终端,以 root 用户身份运行:

# 从hydro恢复数据库, 需要认证(注意!需要先用--drop清空数据库,一定先做好备份!)
mongorestore --drop --db hydro hydro -u hydro -p 换成你的数据库密码 --authenticationDatabase hydro

注意!恢复备份的时候,需要先用 --drop 清空数据库,不然无法恢复,一定先做好备份!

二、分析数据库

如果是在生产环境,除了先备份,还要找个人少的时间。

第一步,先进入 MongoDB 的 shell,有两种方法,一种是直接使用 mongosh 加一堆认证参数,比较麻烦,这里建议直接使用以下自带命令进入:

hydrooj db

这样进来就是 hydro 的数据库。

先用 navicat(使用说明)查看数据库的结构,发现 pid 存储于 document 表中,尝试手动修改了一个题,发现并未修改显示位置,而且无法打开题目了。需要同时修改 pidsort 字段。至于是否需要修改其他更多字段,等官方回复再说。

以及,这个 document 表里边存的不光是题,还有作业 / 比赛 / 训练 等等,以 docType 来区分类型,数字类型,题目的 docType10

还有一个会影响定位的是 domainId,这里我需要修改的是 system

最后,pid 的格式均为 字母+数字[+字母] 的形式,所以需要用正则把字母前缀抠出来,然后再用正则替换掉。

为了测试定位,我先用 find 只显示 pidtitle,查看定位是否精准:

db.document.find(
    {
        domainId: "system",
        docType: 10,
        pid: { $regex: /^P/i }
    },
    {
        _id: 0, // Exclude the default _id field from the output
        pid: 1, // Include the pid field
        title: 1 // Include the title field
    }
)

成功的话,应该会返回一堆结果,如下:

[
  { title: '【例2.1】Hello World', pid: 'P1' },
  { title: '【例4.1】 交换两个数的位置', pid: 'P10' },
  ...
]
Type "it" for more

三、修改数据库

使用 updateMany 对数据进行修改。

运行下列代码之前,应先检查:

  1. MongoDB 的备份是否完成?
  2. HydroOJ 的备份是否完成?
  3. 是否经过了本地虚拟机测试?
  4. (生产环境)是否是无人使用的状态?
  5. (生产环境)是否确认好了要修改的关键信息?

全部一一确认好之后,再使用下列代码:

db.document.updateMany(
   {
      domainId: "system",
      docType: 10,
      pid: { $regex: /^P/i }
   },
   [
      {
         $set: {
            pid: {
               $concat: [
                  "B",
                  { $substrBytes: ["$pid", 1, { $subtract: [{ $strLenBytes: "$pid" }, 1] }] }
               ]
            }
         }
      },
      {
         $set: {
            sort: {
               $concat: [
                  "B",
                  { $substrBytes: ["$sort", 1, { $subtract: [{ $strLenBytes: "$sort" }, 1] }] }
               ]
            }
         }
      }
   ]
)

这里的实现比较暴力,就是直接连接 B 和原字符串剩余的 len-1 个字符。如果修改的是两个字母的,那需要把这一行最后一个 1 改成 2,以此类推。

有更好的实现欢迎提供建议。

如果运行成功,将会出现运行成功的通知:

{
  acknowledged: true,
  insertedId: null,
  matchedCount: 480,  // 找到题数,可能会不一样
  modifiedCount: 480,  // 已修改题数,可能会不一样
  upsertedCount: 0
}

四、会有副作用吗

OJ 内部引用实际上用的都是题目的 id,在数据库中的 field 是 docId,所以理论上应该不受影响。

简单测试了一下作业、比赛和训练,目前没发现有什么影响。

如果你修改完发现有什么地方受影响,可以随时联系我。

标签:13,前缀,数据库,pid,HydroOJ,修改,备份,题号,hydro
From: https://www.cnblogs.com/bowen404/p/18016627

相关文章

  • hdu 5113 Black And White(DFS染色)
    Problem-5113(hdu.edu.cn)hdu没法提交,我以为我账号又崩了...#include<iostream>#include<cstring>usingnamespacestd;intT,n,m,k,kase;intcolor[30],ans[10][10];boolDFS(intx,inty,intcur){if(x>n)returntrue;for(inti=1;i<=k;i++){......
  • 「题解」P6130 随机红包
    在\([0,1]\)上随机撒\((n-1)\)个点划分成\(n\)段,求第\(k\)大的段长的期望。从Appleblue17老师的题解中学的,大概详细写很多一笔带过但是我不认为很简单的步骤。Part1令随机变量\(X\)为第\(k\)大的段长。\(E(X)=\int_0^1P(X=x)x\textdx=\int_0^1P(X\geqx)\text......
  • 「题解」ARC139F Many Xor Optimization Problems
    考虑线性空间的标准基底(即每个主元都只有对应向量有值),答案为所有基底异或和。对于一个秩\(k\)计算它对答案的贡献。固定主元为\(a_1<a_2<\cdots<a_k\),各种情况应该是等概率,也就是对第\(i\)个基底来说,\(a_i\)位一定为\(1\),再往下的位除了在\(a\)出现过的以外的位0/1是......
  • 20240213打卡
    在Android中,可以使用SQLite数据库来创建和管理本地数据库。下面使用Android自带的数据库API创建表,并进行增删改查操作:1.**创建数据库帮助类**:首先,创建一个继承自`SQLiteOpenHelper`的类,用于管理数据库的创建和版本控制。```java//DbHelper.javaimportandroid.content.Con......
  • P4113 [HEOI2012] 采花 题解
    题目链接:采花这题数据加强到卡了\(2e6\)的可持久化线段树在线做法,先给只tle了最后一个点的代码:卡常参照代码#include<bits/stdc++.h>//#pragmaGCCoptimize(2)//#pragmaGCCoptimize("Ofast,no-stack-protector,unroll-loops,fast-math")//#pragmaGCCtarget("......
  • 137. 只出现一次的数字 II(中)
    目录题目法一、排序法二、位运算题目给你一个整数数组nums,除某个元素仅出现一次外,其余每个元素都恰出现三次。请你找出并返回那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。示例1:输入:nums=[2,2,3,2]输出:3示例......
  • 2024.2.13 LGJ Round
    A一个圆上有\(2n\)个点,你需要选出\(n\)个点对连一条线段,其中一些点对已经被选。问所有点对方案中,联通块个数的和,联通的含义是线段相交,那么两条线段的端点都互相可达。\(n\le300\)。线段相交,把圆放到序列上就是区间相交然而不包含。我们拆贡献,计算每个区间\([l,r]\)的......
  • #13 2024.2.14
    有人情人节恋爱。有人情人节看海。有人情人节打模拟赛。583.loj3709「ZJOI2022」面条这个题过于神秘了。首先假设\(n\)是奇数,不然预处理log轮就好了。然后会变成xxyyzz...uuvvw的形状,并且不会变。特别神秘的是,注意到把y-x,z-y,...,v-u,w-v写成序列,那么新的差分......
  • Debug: tf_distribute_strategy_worker.yaml: Exit Code: 132, and log of pod is emp
    [ERROR:ExitCode:132,andlogofpodisempty.](base)maye@maye-Inspiron-5547:~/github_repository/tensorflow_ecosystem/distribution_strategy$kubectldescribepoddist-strat-example-worker-1-qv8wpName:dist-strat-example-worker-1-qv8wpNa......
  • 闲话2.13
    哎嘿,我复活了!昨天到的西安,旅游体验很棒啊......