From 5a03fef6ec8fc3256fa5787c95c6e2b723aa4471 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Fri, 21 Jul 2023 17:27:01 +0800 Subject: [PATCH] feat(plugin): update search condition --- internal/schema/search_schema.go | 32 ++++++++++++- .../service/search_parser/search_parser.go | 24 +++++----- internal/service/search_service.go | 6 +-- plugin/search.go | 45 +++++++++++++++++-- 4 files changed, 88 insertions(+), 19 deletions(-) diff --git a/internal/schema/search_schema.go b/internal/schema/search_schema.go index 0f2e0f56..95b578c2 100644 --- a/internal/schema/search_schema.go +++ b/internal/schema/search_schema.go @@ -1,6 +1,9 @@ package schema -import "github.com/answerdev/answer/internal/base/constant" +import ( + "github.com/answerdev/answer/internal/base/constant" + "github.com/answerdev/answer/plugin" +) type SearchDTO struct { UserID string // UserID current login user ID @@ -48,6 +51,33 @@ func (s *SearchCondition) SearchAnswer() bool { return s.TargetType == constant.AnswerObjectType } +// Convert2PluginSearchCond convert to plugin search condition +func (s *SearchCondition) Convert2PluginSearchCond(page, pageSize int, order string) *plugin.SearchBasicCond { + basic := &plugin.SearchBasicCond{ + Page: page, + PageSize: pageSize, + Words: s.Words, + TagIDs: s.Tags, + UserID: s.UserID, + Order: order, + QuestionID: s.QuestionID, + VoteAmount: s.VoteAmount, + ViewAmount: s.Views, + AnswerAmount: s.AnswerAmount, + } + if s.Accepted { + basic.AnswerAccepted = plugin.AcceptedCondTrue + } else { + basic.AnswerAccepted = plugin.AcceptedCondAll + } + if s.NotAccepted { + basic.QuestionAccepted = plugin.AcceptedCondFalse + } else { + basic.QuestionAccepted = plugin.AcceptedCondAll + } + return basic +} + type SearchObject struct { ID string `json:"id"` QuestionID string `json:"question_id"` diff --git a/internal/service/search_parser/search_parser.go b/internal/service/search_parser/search_parser.go index bbbbf2dd..56dd28c8 100644 --- a/internal/service/search_parser/search_parser.go +++ b/internal/service/search_parser/search_parser.go @@ -121,17 +121,17 @@ func (sp *SearchParser) parseTags(ctx context.Context, query *string) (tags []st // parseUserID return user id or current login user id func (sp *SearchParser) parseUserID(ctx context.Context, query *string, currentUserID string) (userID string) { var ( - exprUserID = `(?m)^user:([a-z0-9._-]+)` - exprMe = "user:me" - q = *query + exprUsername = `user:(\S+)` + exprMe = "user:me" + q = *query ) - re := regexp.MustCompile(exprUserID) + re := regexp.MustCompile(exprUsername) res := re.FindStringSubmatch(q) if strings.Contains(q, exprMe) { userID = currentUserID q = strings.ReplaceAll(q, exprMe, "") - } else if len(res) == 2 { + } else if len(res) > 1 { name := res[1] user, has, err := sp.userCommon.GetUserBasicInfoByUserName(ctx, name) if err == nil && has { @@ -146,14 +146,14 @@ func (sp *SearchParser) parseUserID(ctx context.Context, query *string, currentU // parseVotes return the votes of search query func (sp *SearchParser) parseVotes(query *string) (votes int) { var ( - expr = `(?m)^score:([0-9]+)` + expr = `score:(\d+)` q = *query ) votes = -1 re := regexp.MustCompile(expr) res := re.FindStringSubmatch(q) - if len(res) == 2 { + if len(res) > 1 { votes = converter.StringToInt(res[1]) q = re.ReplaceAllString(q, "") } @@ -218,13 +218,13 @@ func (sp *SearchParser) parseIsQuestion(query *string) (isQuestion bool) { func (sp *SearchParser) parseViews(query *string) (views int) { var ( q = *query - expr = `(?m)^views:([0-9]+)` + expr = `views:(\d+)` ) views = -1 re := regexp.MustCompile(expr) res := re.FindStringSubmatch(q) - if len(res) == 2 { + if len(res) > 1 { views = converter.StringToInt(res[1]) q = re.ReplaceAllString(q, "") } @@ -236,13 +236,13 @@ func (sp *SearchParser) parseViews(query *string) (views int) { func (sp *SearchParser) parseAnswers(query *string) (answers int) { var ( q = *query - expr = `(?m)^answers:([0-9]+)` + expr = `answers:(\d+)` ) answers = -1 re := regexp.MustCompile(expr) res := re.FindStringSubmatch(q) - if len(res) == 2 { + if len(res) > 1 { answers = converter.StringToInt(res[1]) q = re.ReplaceAllString(q, "") } @@ -271,7 +271,7 @@ func (sp *SearchParser) parseAccepted(query *string) (accepted bool) { func (sp *SearchParser) parseQuestionID(query *string) (questionID string) { var ( q = *query - expr = `(?m)^inquestion:([0-9]+)` + expr = `inquestion:(\d+)` ) re := regexp.MustCompile(expr) diff --git a/internal/service/search_service.go b/internal/service/search_service.go index 9e9bff1b..995fe039 100644 --- a/internal/service/search_service.go +++ b/internal/service/search_service.go @@ -56,11 +56,11 @@ func (ss *SearchService) Search(ctx context.Context, dto *schema.SearchDTO) (res func (ss *SearchService) searchByPlugin(ctx context.Context, finder plugin.Search, cond *schema.SearchCondition, dto *schema.SearchDTO) (resp []schema.SearchResp, total int64, err error) { var res []plugin.SearchResult if cond.SearchAll() { - res, total, err = finder.SearchContents(ctx, cond.Words, cond.Tags, cond.UserID, cond.VoteAmount, dto.Page, dto.Size, dto.Order) + res, total, err = finder.SearchContents(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) } else if cond.SearchQuestion() { - res, total, err = finder.SearchQuestions(ctx, cond.Words, cond.Tags, cond.NotAccepted, cond.Views, cond.AnswerAmount, dto.Page, dto.Size, dto.Order) + res, total, err = finder.SearchQuestions(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) } else if cond.SearchAnswer() { - res, total, err = finder.SearchAnswers(ctx, cond.Words, cond.Tags, cond.Accepted, cond.QuestionID, dto.Page, dto.Size, dto.Order) + res, total, err = finder.SearchAnswers(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order)) } resp, err = ss.searchRepo.ParseSearchPluginResult(ctx, res) diff --git a/plugin/search.go b/plugin/search.go index b81543e7..42b303b5 100644 --- a/plugin/search.go +++ b/plugin/search.go @@ -28,11 +28,50 @@ type SearchContent struct { HasAccepted bool `json:"hasAccepted"` } +type SearchBasicCond struct { + // From zero-based page number + Page int + // Page size + PageSize int + + // The keywords for search. + Words []string + // TagIDs is a list of tag IDs. + TagIDs []string + // The object's owner user ID. + UserID string + // The order of the search result. + Order string + + // Weathers the question is accepted or not. Only support search question. + QuestionAccepted AcceptedCond + // Weathers the answer is accepted or not. Only support search answer. + AnswerAccepted AcceptedCond + + // Only support search answer. + QuestionID string + + // greater than or equal to the number of votes. + VoteAmount int + // greater than or equal to the number of views. + ViewAmount int + // greater than or equal to the number of answers. Only support search question. + AnswerAmount int +} + +type AcceptedCond int + +const ( + AcceptedCondAll AcceptedCond = iota + AcceptedCondTrue + AcceptedCondFalse +) + type Search interface { Base - SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes int, page, size int, order string) (res []SearchResult, total int64, err error) - SearchQuestions(ctx context.Context, words []string, tagIDs []string, notAccepted bool, views, answers int, page, size int, order string) (res []SearchResult, total int64, err error) - SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (res []SearchResult, total int64, err error) + 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 }