Skip to content

Commit

Permalink
Merge pull request #142 from HydrogenC/teacher-name
Browse files Browse the repository at this point in the history
Enable searching courses by teacher name
  • Loading branch information
JingYiJun authored Dec 19, 2024
2 parents a6b3be9 + 4db24ae commit 64555dd
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 3 deletions.
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")
}
if page > 0 {
if pageSize == 0 {
Expand Down
6 changes: 4 additions & 2 deletions danke/model/course_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package model
import (
"context"
"encoding/base64"
"regexp"
"time"

"github.com/eko/gocache/lib/v4/store"
"github.com/opentreehole/backend/common"
"github.com/vmihailenco/msgpack/v5"
"golang.org/x/crypto/sha3"
"regexp"
"time"
)

// CourseGroup 课程组
Expand All @@ -24,6 +25,7 @@ type CourseGroup struct {
CourseCount int `json:"course_count" gorm:"not null;default:0"` // 课程数量
ReviewCount int `json:"review_count" gorm:"not null;default:0"` // 评价数量
Courses CourseList `json:"courses"`
Teachers []*Teacher `gorm:"many2many:teacher_course_groups;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}

var CourseCodeRegexp = regexp.MustCompile(`^([A-Z]{3,})([0-9]{2,})`)
Expand Down
1 change: 1 addition & 0 deletions danke/model/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func Init() {
err = DB.AutoMigrate(
&CourseGroup{},
&Course{},
&Teacher{},
&Review{},
&ReviewHistory{},
&Achievement{},
Expand Down
7 changes: 7 additions & 0 deletions danke/model/teacher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package model

type Teacher struct {
ID int `json:"id"`
Name string `json:"name" gorm:"not null"` // 教师姓名
CourseGroups []*CourseGroup `gorm:"many2many:teacher_course_groups;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
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
// GenerateTeacherTable(DB)
}
94 changes: 94 additions & 0 deletions danke_utils/teacher_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package main

import (
"fmt"
"slices"
"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"` // 课程组 ID
}

type TeacherCourseLink struct {
TeacherID int `gorm:"primaryKey;autoIncrement:false"`
CourseGroupID int `gorm:"primaryKey;autoIncrement:false"` // 课程组编号
}

func AppendUnique[T comparable](slice []T, elems ...T) []T {
for _, elem := range elems {
if !slices.Contains(slice, elem) {
slice = append(slice, elem)
}
}

return slice
}

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

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

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

var queryResult []Course
query := DB.Table("course")
query.FindInBatches(&queryResult, BatchSize, func(tx *gorm.DB, batch int) error {
for _, course := range queryResult {
teacherList := strings.Split(course.Teachers, ",")
for _, name := range teacherList {
courseList, found := dataMap[name]
if found {
dataMap[name] = AppendUnique(courseList, course.CourseGroupID)
} else {
dataMap[name] = []int{course.CourseGroupID}
}
}
}

fmt.Printf("Handled batchg %d\n", batch)
return nil
})

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

// Avoid insertion failure due to duplication
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_course_groups").Create(links)
links = nil
}
}
}

0 comments on commit 64555dd

Please sign in to comment.