Skip to content

Commit

Permalink
fix(search): ci
Browse files Browse the repository at this point in the history
  • Loading branch information
wsm25 committed Aug 24, 2024
1 parent dabea6e commit c8d6d75
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 161 deletions.
2 changes: 1 addition & 1 deletion model/po/course.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type CoursePO struct {
MainTeacherName string `gorm:"index"`
Department string `gorm:"index;index:uniq_course,unique"`

SearchIndex SearchIndex `gorm:"index:idx_search, type:gin"`
SearchIndex SearchIndex // `gorm:"index:idx_search, type:gin"`
}

func (po *CoursePO) TableName() string {
Expand Down
2 changes: 1 addition & 1 deletion model/po/review.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type ReviewPO struct {
Rating int64 `gorm:"index"`
Semester string `gorm:"index;index:uniq_course_review,unique"`
IsAnonymous bool
SearchIndex SearchIndex `gorm:"index:idx_search, type:gin"`
SearchIndex SearchIndex // `gorm:"index:idx_search, type:gin"`
}

func (po *ReviewPO) TableName() string {
Expand Down
138 changes: 69 additions & 69 deletions model/po/search.go
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
package po

import (
"context"
"database/sql/driver"
"jcourse_go/util"
"strings"

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

type SearchIndex string

// ref: https://gorm.io/zh_CN/docs/data_types.html

// warning: need manual migeration!
func (i *SearchIndex) Scan(value interface{}) error { return nil }
func (i SearchIndex) Value() (driver.Value, error) { return nil, nil }
func (i SearchIndex) GormDataType() string { return "tsvector" }

func (i SearchIndex) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return clause.Expr{
SQL: "to_tsvector('simple', ?)",
Vars: []interface{}{i},
}
}

func toIndex(fields []string) SearchIndex {
var sb strings.Builder
for _, field := range fields {
for _, segment := range util.Fenci(field) {
sb.WriteString(segment)
sb.WriteByte(' ')
}
}
return SearchIndex(sb.String())
}

func (c *CoursePO) GenerateSearchIndex() {
c.SearchIndex = toIndex([]string{
c.Name,
c.Code, // 前缀模糊匹配更为适合
c.MainTeacherName,
c.Department, // 不分词更为适合
})
}

func (t *TeacherPO) GenerateSearchIndex() {
t.SearchIndex = toIndex([]string{
t.Name,
t.Department,
t.Code,
})
}

func (t *TrainingPlanPO) GenerateSearchIndex() {
t.SearchIndex = toIndex([]string{
t.Degree,
t.Major,
t.Department,
})
}

func (r *ReviewPO) GenerateSearchIndex() {
r.SearchIndex = toIndex([]string{
r.Comment,
})
}
package po

import (
"context"
"database/sql/driver"
"jcourse_go/util"
"strings"

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

type SearchIndex string

// ref: https://gorm.io/zh_CN/docs/data_types.html

// warning: need manual migeration!
func (i *SearchIndex) Scan(value interface{}) error { return nil }
func (i SearchIndex) Value() (driver.Value, error) { return nil, nil }
func (i SearchIndex) GormDataType() string { return "tsvector" }

func (i SearchIndex) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return clause.Expr{
SQL: "to_tsvector('simple', ?)",
Vars: []interface{}{string(i)},
}
}

func toIndex(fields []string) SearchIndex {
var sb strings.Builder
for _, field := range fields {
for _, segment := range util.Fenci(field) {
sb.WriteString(segment)
sb.WriteByte(' ')
}
}
return SearchIndex(sb.String())
}

func (c *CoursePO) GenerateSearchIndex() {
c.SearchIndex = toIndex([]string{
c.Name,
c.Code, // 前缀模糊匹配更为适合
c.MainTeacherName,
c.Department, // 不分词更为适合
})
}

func (t *TeacherPO) GenerateSearchIndex() {
t.SearchIndex = toIndex([]string{
t.Name,
t.Department,
t.Code,
})
}

func (t *TrainingPlanPO) GenerateSearchIndex() {
t.SearchIndex = toIndex([]string{
t.Degree,
t.Major,
t.Department,
})
}

func (r *ReviewPO) GenerateSearchIndex() {
r.SearchIndex = toIndex([]string{
r.Comment,
})
}
2 changes: 1 addition & 1 deletion model/po/teacher.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type TeacherPO struct {
ProfileURL string
Biography string // 个人简述

SearchIndex SearchIndex `gorm:"index:idx_search, type:gin"`
SearchIndex SearchIndex // `gorm:"index:idx_search, type:gin"`
}

func (po *TeacherPO) TableName() string {
Expand Down
2 changes: 1 addition & 1 deletion model/po/trainingplan.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type TrainingPlanPO struct {
MinCredits float64 `gorm:"index;index:uniq_training_plan,unique"`
MajorClass string `gorm:"index;index:uniq_training_plan,unique"` // the class of major

SearchIndex SearchIndex `gorm:"index:idx_search, type:gin"`
SearchIndex SearchIndex // `gorm:"index:idx_search, type:gin"`
}

func (po *TrainingPlanPO) TableName() string {
Expand Down
2 changes: 1 addition & 1 deletion model/po/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type UserPO struct {
UserRole string `gorm:"index"` // 用户在选课社区的身份
LastSeenAt time.Time

SearchIndex SearchIndex `gorm:"index:idx_search, type:gin"`
SearchIndex SearchIndex // `gorm:"index:idx_search, type:gin"`
}

func (po *UserPO) TableName() string {
Expand Down
98 changes: 49 additions & 49 deletions repository/search.go
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
package repository

import (
"jcourse_go/util"
"strings"

"gorm.io/gorm"
)

func (*CourseQuery) WithSearch(query string) DBOption { return withSearch(query) }
func (*ReviewQuery) WithSearch(query string) DBOption { return withSearch(query) }
func (*TeacherQuery) WithSearch(query string) DBOption { return withSearch(query) }
func (*TrainingPlanQuery) WithSearch(query string) DBOption { return withSearch(query) }

func withSearch(query string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("search_index @@ to_tsquery('simple', ?)",
userQueryToTsQuery(query),
)
}
}

// 目前只搜用户名
func (*UserQuery) WithSearch(query string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("name LIKE ?", query+"%")
}
}

// 空格分割的每个词都要匹配,词内分词做模糊匹配
func userQueryToTsQuery(query string) string {
var sb strings.Builder
words := strings.Fields(query)
for i, word := range words {
if i != 0 {
sb.WriteString(" & ")
}
sb.WriteByte('(')
segs := util.Fenci(word)
for j, seg := range segs {
if j != 0 {
sb.WriteString(" | ")
}
sb.WriteString(seg)
}
sb.WriteByte(')')
}
return sb.String()
}
package repository

import (
"jcourse_go/util"
"strings"

"gorm.io/gorm"
)

func (*CourseQuery) WithSearch(query string) DBOption { return withSearch(query) }
func (*ReviewQuery) WithSearch(query string) DBOption { return withSearch(query) }
func (*TeacherQuery) WithSearch(query string) DBOption { return withSearch(query) }
func (*TrainingPlanQuery) WithSearch(query string) DBOption { return withSearch(query) }

func withSearch(query string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("search_index @@ to_tsquery('simple', ?)",
userQueryToTsQuery(query),
)
}
}

// 目前只搜用户名
func (*UserQuery) WithSearch(query string) DBOption {
return func(db *gorm.DB) *gorm.DB {
return db.Where("name LIKE ?", query+"%")
}
}

// 空格分割的每个词都要匹配,词内分词做模糊匹配
func userQueryToTsQuery(query string) string {
var sb strings.Builder
words := strings.Fields(query)
for i, word := range words {
if i != 0 {
sb.WriteString(" & ")
}
sb.WriteByte('(')
segs := util.Fenci(word)
for j, seg := range segs {
if j != 0 {
sb.WriteString(" | ")
}
sb.WriteString(seg)
}
sb.WriteByte(')')
}
return sb.String()
}
44 changes: 22 additions & 22 deletions util/fenci.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package util

import (
"github.com/go-ego/gse"
)

var seg gse.Segmenter

func Fenci(src string) []string {
return seg.Slice(src, true)
}

// TODO: add assets path
func InitFenci() error {
if err := seg.LoadStop(); err != nil {
return err
}
if err := seg.LoadDict(); err != nil {
return err
}
return nil
}
package util

import (
"github.com/go-ego/gse"
)

var seg gse.Segmenter

func Fenci(src string) []string {
return seg.Slice(src, true)
}

// TODO: add assets path
func InitFenci() error {
if err := seg.LoadStop(); err != nil {
return err
}
if err := seg.LoadDict(); err != nil {
return err
}
return nil
}
32 changes: 16 additions & 16 deletions util/fenci_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package util_test

import (
"jcourse_go/util"
"testing"

"github.com/stretchr/testify/assert"
)

func TestFenci(t *testing.T) {
err := util.InitFenci()
assert.NoError(t, err)
const txt = "电路理论"
var target = []string{"电路", "理论"}
assert.Equal(t, util.Fenci(txt), target)
}
package util_test

import (
"jcourse_go/util"
"testing"

"github.com/stretchr/testify/assert"
)

func TestFenci(t *testing.T) {
err := util.InitFenci()
assert.NoError(t, err)
const txt = "电路理论"
var target = []string{"电路", "理论"}
assert.Equal(t, util.Fenci(txt), target)
}

0 comments on commit c8d6d75

Please sign in to comment.