Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable searching courses by teacher name #142

Merged
merged 10 commits into from
Dec 19, 2024
8 changes: 7 additions & 1 deletion danke/api/course_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"errors"

"github.com/gofiber/fiber/v2"
. "github.com/opentreehole/backend/common"
. "github.com/opentreehole/backend/danke/model"
Expand Down Expand Up @@ -148,7 +149,12 @@ func SearchCourseGroupV3(c *fiber.Ctx) (err error) {
if CourseCodeRegexp.MatchString(query) {
querySet = querySet.Where("code LIKE ?", query+"%")
} else {
querySet = querySet.Where("name LIKE ?", "%"+query+"%")
queryWord :="%"+query+"%"
querySet = querySet.
Joins("JOIN teacher_course_groups tcg ON course_group.id = tcg.course_group_id").
Joins("JOIN teacher t ON tc.teacher_id = t.id").
Where("t.name like ? OR course_group.name LIKE ?", queryWord, queryWord).
Group("id")
HydrogenC marked this conversation as resolved.
Show resolved Hide resolved
}
if page > 0 {
if pageSize == 0 {
Expand Down
60 changes: 60 additions & 0 deletions danke_utils/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package main

import (
"log"
"os"
"time"

"github.com/opentreehole/backend/common"
"github.com/spf13/viper"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
)

var GormConfig = &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 表名使用单数, `User` -> `user`
},
DisableForeignKeyConstraintWhenMigrating: true, // 禁用自动创建外键约束,必须手动创建或者在业务逻辑层维护
Logger: logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Error, // 日志级别
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误
Colorful: false, // 禁用彩色打印
},
),
}

var DB *gorm.DB

func Init() {
viper.AutomaticEnv()
dbType := viper.GetString(common.EnvDBType)
dbUrl := viper.GetString(common.EnvDBUrl)

var err error

switch dbType {
case "mysql":
DB, err = gorm.Open(mysql.Open(dbUrl), GormConfig)
case "postgres":
DB, err = gorm.Open(postgres.Open(dbUrl), GormConfig)
default:
panic("db type not supported")
}

if err != nil {
panic(err)
}
}

func main() {
Init()
// Call any script as needed
// GenerateTeacherTabele(DB)
}
93 changes: 93 additions & 0 deletions danke_utils/teacher_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package main

import (
"fmt"
"strings"

"gorm.io/gorm"
"gorm.io/gorm/clause"
)

const (
BatchSize = 1000
)

type Course struct {
ID int `json:"id"`
Name string `json:"name" gorm:"not null"` // 课程名称
Code string `json:"code" gorm:"not null"` // 课程编号
CodeID string `json:"code_id" gorm:"not null"` // 选课序号。用于区分同一课程编号的不同平行班
Teachers string `json:"teachers" gorm:"not null"`
CourseGroupID int `json:"course_group_id" gorm:"not null;index"` // 课程组类型
}

type Teacher struct {
ID int
Name string `gorm:"not null"` // 课程组类型
}

type TeacherCourseLink struct {
TeacherID int `gorm:"primaryKey;autoIncrement:false"`
CourseGroupID int `gorm:"primaryKey;autoIncrement:false"` // 课程组类型
}
HydrogenC marked this conversation as resolved.
Show resolved Hide resolved

func GenerateTeacherTabele(DB *gorm.DB) {
Init()

// reader := bufio.NewReader(os.Stdin)

dataMap := map[string][]int{}

var offset int = 0
var queryResult []Course
for {
query := DB.Table("course").Limit(BatchSize).Offset(offset)
query.Find(&queryResult)
offset += len(queryResult)

if len(queryResult) == 0 {
// Finished iterating
break
}

HydrogenC marked this conversation as resolved.
Show resolved Hide resolved
for _, course := range queryResult {
teacherList := strings.Split(course.Teachers, ",")
for _, name := range teacherList {
courseList, found := dataMap[name]
if found {
dataMap[name] = append(courseList, course.CourseGroupID)
HydrogenC marked this conversation as resolved.
Show resolved Hide resolved
} else {
dataMap[name] = []int{course.CourseGroupID}
}
}
}

// Avoid insertion failure due to duplication

fmt.Printf("Handled %d records\n", offset)
// _, _ = reader.ReadString('\n')
}

var teachers []*Teacher
for k := range dataMap {
teachers = append(teachers, &Teacher{Name: k})
}

DB.Clauses(clause.OnConflict{DoNothing: true}).Table("teacher").Create(teachers)

var links []*TeacherCourseLink
for index, teacher := range teachers {
for _, cid := range dataMap[teacher.Name] {
links = append(links, &TeacherCourseLink{TeacherID: teacher.ID, CourseGroupID: cid})
}

// Submit every 100 teachers to avoid SQL being too long
if index%100 == 0 {
fmt.Printf("Inserted %d teachers\n", index)

// Avoid insertion failure due to duplication
DB.Clauses(clause.OnConflict{DoNothing: true}).Table("teacher_courses").Create(links)
links = nil
}
}
}