From 0d2c9cfd45ac052b81719b0a68f34cd4a8b93741 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Thu, 17 Aug 2023 15:25:14 +0800 Subject: [PATCH] feat(search): convert answer and question to search content --- internal/repo/answer/answer_repo.go | 2 +- internal/repo/question/question_repo.go | 2 +- internal/repo/search_sync/search_sync.go | 107 +++++++++++++++++++++-- plugin/search.go | 9 +- 4 files changed, 105 insertions(+), 15 deletions(-) diff --git a/internal/repo/answer/answer_repo.go b/internal/repo/answer/answer_repo.go index 2cffdb4a..377a5c28 100644 --- a/internal/repo/answer/answer_repo.go +++ b/internal/repo/answer/answer_repo.go @@ -391,6 +391,6 @@ func (ar *answerRepo) updateSearch(ctx context.Context, answerID string) (err er Score: int64(answer.VoteCount), HasAccepted: answer.Accepted == schema.AnswerAcceptedEnable, } - err = s.UpdateContent(ctx, answerID, content) + err = s.UpdateContent(ctx, content) return } diff --git a/internal/repo/question/question_repo.go b/internal/repo/question/question_repo.go index eb159628..4f51e6f2 100644 --- a/internal/repo/question/question_repo.go +++ b/internal/repo/question/question_repo.go @@ -467,6 +467,6 @@ func (qr *questionRepo) updateSearch(ctx context.Context, questionID string) (er Score: int64(question.VoteCount), HasAccepted: question.AcceptedAnswerID != "" && question.AcceptedAnswerID != "0", } - err = s.UpdateContent(ctx, questionID, content) + err = s.UpdateContent(ctx, content) return } diff --git a/internal/repo/search_sync/search_sync.go b/internal/repo/search_sync/search_sync.go index 3f3bff35..1cd0cb37 100644 --- a/internal/repo/search_sync/search_sync.go +++ b/internal/repo/search_sync/search_sync.go @@ -2,9 +2,13 @@ package search_sync import ( "context" + "github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/entity" + "github.com/answerdev/answer/internal/schema" + "github.com/answerdev/answer/pkg/uid" "github.com/answerdev/answer/plugin" + "github.com/segmentfault/pacman/log" ) func NewPluginSyncer(data *data.Data) plugin.SearchSyncer { @@ -15,16 +19,103 @@ type PluginSyncer struct { data *data.Data } -func (p *PluginSyncer) GetAnswersPage(ctx context.Context, page, pageSize int) (answerList []*entity.Answer, err error) { - answerList = make([]*entity.Answer, 0) +func (p *PluginSyncer) GetAnswersPage(ctx context.Context, page, pageSize int) ( + answerList []*plugin.SearchContent, err error) { + answers := make([]*entity.Answer, 0) startNum := (page - 1) * pageSize - err = p.data.DB.Context(ctx).Limit(pageSize, startNum).Find(&answerList) - return answerList, err + err = p.data.DB.Context(ctx).Limit(pageSize, startNum).Find(&answers) + if err != nil { + return nil, err + } + return p.convertAnswers(ctx, answers) } -func (p *PluginSyncer) GetQuestionsPage(ctx context.Context, page, pageSize int) (questionList []*entity.Question, err error) { - questionList = make([]*entity.Question, 0) +func (p *PluginSyncer) GetQuestionsPage(ctx context.Context, page, pageSize int) ( + questionList []*plugin.SearchContent, err error) { + questions := make([]*entity.Question, 0) startNum := (page - 1) * pageSize - err = p.data.DB.Context(ctx).Limit(pageSize, startNum).Find(&questionList) - return questionList, err + err = p.data.DB.Context(ctx).Limit(pageSize, startNum).Find(&questions) + if err != nil { + return nil, err + } + return p.convertQuestions(ctx, questions) +} + +func (p *PluginSyncer) convertAnswers(ctx context.Context, answers []*entity.Answer) ( + answerList []*plugin.SearchContent, err error) { + for _, answer := range answers { + question := &entity.Question{} + exist, err := p.data.DB.Context(ctx).Where("id = ?", answer.QuestionID).Get(question) + if err != nil { + log.Errorf("get question failed %s", err) + continue + } + if !exist { + continue + } + + tagListList := make([]*entity.TagRel, 0) + tags := make([]string, 0) + err = p.data.DB.Context(ctx).Where("object_id = ?", uid.DeShortID(question.ID)). + Where("status = ?", entity.TagRelStatusAvailable).Find(&tagListList) + if err != nil { + log.Errorf("get tag list failed %s", err) + } + for _, tag := range tagListList { + tags = append(tags, tag.TagID) + } + + content := &plugin.SearchContent{ + ObjectID: answer.ID, + Title: question.Title, + Type: constant.AnswerObjectType, + Content: answer.ParsedText, + Answers: 0, + Status: plugin.SearchContentStatus(answer.Status), + Tags: tags, + QuestionID: answer.QuestionID, + UserID: answer.UserID, + Views: int64(question.ViewCount), + Created: answer.CreatedAt.Unix(), + Active: answer.UpdatedAt.Unix(), + Score: int64(answer.VoteCount), + HasAccepted: answer.Accepted == schema.AnswerAcceptedEnable, + } + answerList = append(answerList, content) + } + return answerList, nil +} + +func (p *PluginSyncer) convertQuestions(ctx context.Context, questions []*entity.Question) ( + questionList []*plugin.SearchContent, err error) { + for _, question := range questions { + tagListList := make([]*entity.TagRel, 0) + tags := make([]string, 0) + err := p.data.DB.Context(ctx).Where("object_id = ?", question.ID). + Where("status = ?", entity.TagRelStatusAvailable).Find(&tagListList) + if err != nil { + log.Errorf("get tag list failed %s", err) + } + for _, tag := range tagListList { + tags = append(tags, tag.TagID) + } + content := &plugin.SearchContent{ + ObjectID: question.ID, + Title: question.Title, + Type: constant.QuestionObjectType, + Content: question.ParsedText, + Answers: int64(question.AnswerCount), + Status: plugin.SearchContentStatus(question.Status), + Tags: tags, + QuestionID: question.ID, + UserID: question.UserID, + Views: int64(question.ViewCount), + Created: question.CreatedAt.Unix(), + Active: question.UpdatedAt.Unix(), + Score: int64(question.VoteCount), + HasAccepted: question.AcceptedAnswerID != "" && question.AcceptedAnswerID != "0", + } + questionList = append(questionList, content) + } + return questionList, nil } diff --git a/plugin/search.go b/plugin/search.go index 115be2c8..37a64f4e 100644 --- a/plugin/search.go +++ b/plugin/search.go @@ -2,7 +2,6 @@ package plugin import ( "context" - "github.com/answerdev/answer/internal/entity" ) type SearchResult struct { @@ -89,8 +88,8 @@ type Search interface { SearchContents(ctx context.Context, cond *SearchBasicCond) (res []SearchResult, total int64, err error) SearchQuestions(ctx context.Context, cond *SearchBasicCond) (res []SearchResult, total int64, err error) SearchAnswers(ctx context.Context, cond *SearchBasicCond) (res []SearchResult, total int64, err error) - UpdateContent(ctx context.Context, contentID string, content *SearchContent) error - DeleteContent(ctx context.Context, contentID string) error + UpdateContent(ctx context.Context, content *SearchContent) (err error) + DeleteContent(ctx context.Context, objectID string) (err error) } type SearchDesc struct { @@ -99,8 +98,8 @@ type SearchDesc struct { } type SearchSyncer interface { - GetAnswersPage(ctx context.Context, page, pageSize int) (answerList []*entity.Answer, err error) - GetQuestionsPage(ctx context.Context, page, pageSize int) (questionList []*entity.Question, err error) + GetAnswersPage(ctx context.Context, page, pageSize int) (answerList []*SearchContent, err error) + GetQuestionsPage(ctx context.Context, page, pageSize int) (questionList []*SearchContent, err error) } var (