Skip to content

Commit

Permalink
搜索支持按字段搜索
Browse files Browse the repository at this point in the history
  • Loading branch information
juniaoshaonian committed Aug 25, 2024
1 parent 8e81b20 commit 6726879
Show file tree
Hide file tree
Showing 16 changed files with 488 additions and 84 deletions.
14 changes: 7 additions & 7 deletions internal/bff/internal/web/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const (
func (h *Handler) CollectionRecords(ctx *ginx.Context, req CollectionInfoReq, sess session.Session) (ginx.Result, error) {
uid := sess.Claims().Uid
// 获取收藏记录
records, err := h.intrSvc.CollectionInfo(ctx, uid, req.ID, req.Offset, req.Limit)
records, err := h.intrSvc.CollectionInfo(ctx.Request.Context(), uid, req.ID, req.Offset, req.Limit)
if err != nil {
return systemErrorResult, err
}
Expand Down Expand Up @@ -49,22 +49,22 @@ func (h *Handler) CollectionRecords(ctx *ginx.Context, req CollectionInfoReq, se
qid2s = append(qid2s, qids...)

eg.Go(func() error {
cs, err1 := h.caseSvc.GetPubByIDs(ctx, cids)
cs, err1 := h.caseSvc.GetPubByIDs(ctx.Request.Context(), cids)
csm = slice.ToMap(cs, func(element cases.Case) int64 {
return element.Id
})
return err1
})

eg.Go(func() error {
qs, err1 := h.queSvc.GetPubByIDs(ctx, qids)
qs, err1 := h.queSvc.GetPubByIDs(ctx.Request.Context(), qids)
qsm = slice.ToMap(qs, func(element baguwen.Question) int64 {
return element.Id
})
return err1
})
eg.Go(func() error {
qsets, qerr := h.queSetSvc.GetByIDsWithQuestion(ctx, qsids)
qsets, qerr := h.queSetSvc.GetByIDsWithQuestion(ctx.Request.Context(), qsids)
qssmap = slice.ToMap(qsets, func(element baguwen.QuestionSet) int64 {
return element.Id
})
Expand All @@ -75,7 +75,7 @@ func (h *Handler) CollectionRecords(ctx *ginx.Context, req CollectionInfoReq, se
})

eg.Go(func() error {
csets, cserr := h.caseSetSvc.GetByIdsWithCases(ctx, csids)
csets, cserr := h.caseSetSvc.GetByIdsWithCases(ctx.Request.Context(), csids)
cssmap = slice.ToMap(csets, func(element cases.CaseSet) int64 {
return element.ID
})
Expand All @@ -91,13 +91,13 @@ func (h *Handler) CollectionRecords(ctx *ginx.Context, req CollectionInfoReq, se
eg = errgroup.Group{}
eg.Go(func() error {
var err1 error
queExamResMap, err1 = h.queExamSvc.GetResults(ctx, uid, qid2s)
queExamResMap, err1 = h.queExamSvc.GetResults(ctx.Request.Context(), uid, qid2s)
return err1
})

eg.Go(func() error {
var err1 error
caseExamResMap, err1 = h.caseExamSvc.GetResults(ctx, uid, cids)
caseExamResMap, err1 = h.caseExamSvc.GetResults(ctx.Request.Context(), uid, cids)
return err1
})
// 获取进度
Expand Down
11 changes: 11 additions & 0 deletions internal/search/internal/domain/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package domain

// 定义的查询元数据
type QueryMeta struct {
// 查询的内容
Keyword string
// 是否是全量字段的
IsAll bool
// 需要查询的关键字
Col string
}
226 changes: 226 additions & 0 deletions internal/search/internal/integration/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,232 @@ func (s *HandlerTestSuite) TestSearch() {
assert.Equal(t, want, ans)
}

func (s *HandlerTestSuite) TestSearchWithCol() {
testCases := []struct {
name string
before func(t *testing.T)
after func(t *testing.T, wantRes web.SearchResult, actual web.SearchResult)
wantAns web.SearchResult
req web.SearchReq
}{
{
name: "搜索cases",
before: func(t *testing.T) {
s.initCases()
},
after: func(t *testing.T, wantRes web.SearchResult, actual web.SearchResult) {
for idx := range actual.Cases {
require.True(t, actual.Cases[idx].Utime != "")
require.True(t, actual.Cases[idx].Ctime != "")
actual.Cases[idx].Ctime = ""
actual.Cases[idx].Utime = ""
}
assert.Equal(t, wantRes, actual)
},
wantAns: web.SearchResult{
Cases: []web.Case{
{
Id: 6,
Uid: 1,
Labels: []string{"label1"},
Title: "test_title",
Content: "Elasticsearch内容",
GithubRepo: "Elasticsearch github代码库",
GiteeRepo: "Elasticsearch gitee代码库",
Keywords: "Elasticsearch关键词",
Shorthand: "Elasticsearch速记",
Highlight: "Elasticsearch亮点",
Guidance: "Elasticsearch引导",
Status: 2,
},
{
Id: 5,
Uid: 1,
Labels: []string{"test_label"},
Title: "Elasticsearch标题",
Content: "Elasticsearch内容",
GithubRepo: "Elasticsearch github代码库",
GiteeRepo: "Elasticsearch gitee代码库",
Keywords: "Elasticsearch关键词",
Shorthand: "Elasticsearch速记",
Highlight: "Elasticsearch亮点",
Guidance: "Elasticsearch引导",
Status: 2,
},
},
},
req: web.SearchReq{
Keywords: "biz:case:labels:test_label title:test_title",
Offset: 0,
Limit: 20,
},
},
{
name: "搜索questions",
before: func(t *testing.T) {
s.initQuestions()
},
after: func(t *testing.T, wantRes web.SearchResult, actual web.SearchResult) {
for idx := range actual.Questions {
require.True(t, actual.Questions[idx].Utime != "")
actual.Questions[idx].Utime = ""
if idx < 3 {
assert.Equal(t, wantRes.Questions[idx], actual.Questions[idx])
}
}
assert.ElementsMatch(t, wantRes.Questions, actual.Questions)

},
wantAns: web.SearchResult{
Questions: []web.Question{
{
ID: 2,
UID: 101,
Title: "test_title",
Labels: []string{"elasticsearch", "search"},
Content: "I want to know how to use Elasticsearch for searching.",
Status: 2,
},
{
ID: 1,
UID: 101,
Title: "dasdsa",
Labels: []string{"test_label"},
Content: "I want to know how to use Elasticsearch for searching.",
Status: 2,
},
{
ID: 12,
UID: 101,
Title: "How to use Elasticsearch?",
Labels: []string{"elasticsearch", "search"},
Content: "I want to know how to use Elasticsearch for searching.",
Status: 2,
Answer: web.Answer{
Intermediate: web.AnswerElement{
ID: 1,
Content: "Elasticsearch is a distributed search and analytics engine.",
Keywords: "test_intermediate_keywords",
Shorthand: "",
Highlight: "distributed search and analytics engine",
Guidance: "Learn more about Elasticsearch documentation.",
},
},
},
},
},
req: web.SearchReq{
Keywords: "biz:question:title:test_title labels:test_label answer.intermediate.keywords:test_intermediate_keywords",
Offset: 0,
Limit: 20,
},
},
{
name: "搜索skills",
before: func(t *testing.T) {
s.initSkills()
},
after: func(t *testing.T, wantRes web.SearchResult, actual web.SearchResult) {
for idx := range actual.Skills {
require.True(t, actual.Skills[idx].Utime != "")
actual.Skills[idx].Utime = ""
actual.Skills[idx].Ctime = ""
actual.Skills[idx].Basic = handlerSkillLevel(s.T(), actual.Skills[idx].Basic)
actual.Skills[idx].Intermediate = handlerSkillLevel(s.T(), actual.Skills[idx].Intermediate)
actual.Skills[idx].Advanced = handlerSkillLevel(s.T(), actual.Skills[idx].Advanced)
if idx < 3 {
assert.Equal(t, wantRes.Skills[idx], actual.Skills[idx])
}
}
assert.ElementsMatch(t, wantRes.Skills, actual.Skills)

},
wantAns: web.SearchResult{
Skills: []web.Skill{
{
ID: 1,
Labels: []string{"programming", "golang"},
Name: "test_name",
Desc: "Learn Golang programming language",
},
{
ID: 2,
Labels: []string{"programming", "test_label"},
Name: "",
Desc: "Learn Golang programming language",
},
{
ID: 4,
Labels: []string{"programming"},
Name: "",
Desc: "",
Basic: web.SkillLevel{
ID: 1,
Desc: "test_basic",
Questions: []int64{1},
Cases: []int64{1},
},
},
},
},
req: web.SearchReq{
Keywords: "biz:skill:labels:golang name:test_name labels:test_label basic.desc:test_basic",
Offset: 0,
Limit: 20,
},
},
{
name: "搜索questionSets",
before: func(t *testing.T) {
s.initQuestionSets()
},
after: func(t *testing.T, wantRes web.SearchResult, actual web.SearchResult) {
for idx := range actual.QuestionSet {
require.True(t, actual.QuestionSet[idx].Utime != "")
actual.QuestionSet[idx].Utime = ""
}
},
wantAns: web.SearchResult{
QuestionSet: []web.QuestionSet{
{
Id: 2,
Uid: 123,
Title: "test_title",
Description: "This is a test question set",
},
{
Id: 1,
Uid: 123,
Title: "jjjkjk",
Description: "test_desc",
},
},
},
req: web.SearchReq{
Keywords: "biz:questionSet:title:test_title",
Offset: 0,
Limit: 20,
},
},
}
for _, tc := range testCases {
tc := tc
s.T().Run(tc.name, func(t *testing.T) {
tc.before(t)
time.Sleep(3 * time.Second)
req, err := http.NewRequest(http.MethodPost,
"/search/list", iox.NewJSONReader(tc.req))
req.Header.Set("content-type", "application/json")
require.NoError(t, err)
recorder := test.NewJSONResponseRecorder[web.SearchResult]()
s.server.ServeHTTP(recorder, req)
require.Equal(t, 200, recorder.Code)
tc.after(t, tc.wantAns, recorder.MustScan().Data)
})
}

}

func (s *HandlerTestSuite) TestSync() {
testcases := []struct {
name string
Expand Down
4 changes: 2 additions & 2 deletions internal/search/internal/repository/case.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ func NewCaseRepo(caseDao dao.CaseDAO) CaseRepo {
}
}

func (c *caseRepository) SearchCase(ctx context.Context, offset, limit int, keywords string) ([]domain.Case, error) {
cases, err := c.caseDao.SearchCase(ctx, offset, limit, keywords)
func (c *caseRepository) SearchCase(ctx context.Context, offset, limit int, queryMetas []domain.QueryMeta) ([]domain.Case, error) {
cases, err := c.caseDao.SearchCase(ctx, offset, limit, queryMetas)
if err != nil {
return nil, err
}
Expand Down
52 changes: 52 additions & 0 deletions internal/search/internal/repository/dao/builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package dao

import (
"strings"

"github.com/ecodeclub/webook/internal/search/internal/domain"
"github.com/olivere/elastic/v7"
)

// 用于构建查询
type Col struct {
// 列名
Name string
// 权重
Boost int
}

func buildCols(cols map[string]Col, queryMetas []domain.QueryMeta) []elastic.Query {
colMap := make(map[string][]string, len(cols))
for _, meta := range queryMetas {
if meta.IsAll {
for _, col := range cols {
colMap = setCol(colMap, col.Name, meta.Keyword)
}
} else {
colMap = setCol(colMap, meta.Col, meta.Keyword)
}
}
queries := make([]elastic.Query, 0, len(colMap))
for colname, keyword := range colMap {
col := cols[colname]
query := elastic.NewMatchQuery(colname, strings.Join(keyword, " "))
if col.Boost != 0 {
query = query.Boost(float64(col.Boost))
}
queries = append(queries, query)
}
return queries
}

func setCol(colMap map[string][]string, col, keyword string) map[string][]string {
ks, ok := colMap[col]
if ok {
ks = append(ks, keyword)
colMap[col] = ks
} else {
colMap[col] = []string{
keyword,
}
}
return colMap
}
Loading

0 comments on commit 6726879

Please sign in to comment.