mirror of https://gitee.com/answerdev/answer.git
Merge branch 'fix/search' into 'test'
Fix/search See merge request opensource/answer!233
This commit is contained in:
commit
96f2ad92d1
|
@ -58,6 +58,7 @@ import (
|
|||
"github.com/answerdev/answer/internal/service/report_backyard"
|
||||
"github.com/answerdev/answer/internal/service/report_handle_backyard"
|
||||
"github.com/answerdev/answer/internal/service/revision_common"
|
||||
"github.com/answerdev/answer/internal/service/search_parser"
|
||||
"github.com/answerdev/answer/internal/service/service_config"
|
||||
"github.com/answerdev/answer/internal/service/siteinfo"
|
||||
"github.com/answerdev/answer/internal/service/siteinfo_common"
|
||||
|
@ -154,8 +155,9 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
|||
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo)
|
||||
dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData)
|
||||
answerController := controller.NewAnswerController(answerService, rankService, dashboardService)
|
||||
searchParser := search_parser.NewSearchParser(tagRepo, userCommon)
|
||||
searchRepo := search_common.NewSearchRepo(dataData, uniqueIDRepo, userCommon)
|
||||
searchService := service.NewSearchService(searchRepo, tagRepo, userCommon, followRepo)
|
||||
searchService := service.NewSearchService(searchParser, searchRepo)
|
||||
searchController := controller.NewSearchController(searchService)
|
||||
serviceRevisionService := service.NewRevisionService(revisionRepo, userCommon, questionCommon, answerService)
|
||||
revisionController := controller.NewRevisionController(serviceRevisionService)
|
||||
|
|
|
@ -67,7 +67,7 @@ func NewSearchRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo, userCommon
|
|||
}
|
||||
|
||||
// SearchContents search question and answer data
|
||||
func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID, userID string, votes int, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
|
||||
func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes int, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
|
||||
if words = filterWords(words); len(words) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -116,10 +116,12 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID,
|
|||
}
|
||||
|
||||
// check tag
|
||||
if tagID != "" {
|
||||
if len(tagIDs) > 0 {
|
||||
b.Join("INNER", "tag_rel", "question.id = tag_rel.object_id").
|
||||
Where(builder.Eq{"tag_rel.tag_id": tagID})
|
||||
argsQ = append(argsQ, tagID)
|
||||
Where(builder.In("tag_rel.tag_id", tagIDs))
|
||||
for _, tagID := range tagIDs {
|
||||
argsQ = append(argsQ, tagID)
|
||||
}
|
||||
}
|
||||
|
||||
// check user
|
||||
|
@ -193,7 +195,7 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID,
|
|||
}
|
||||
|
||||
// SearchQuestions search question data
|
||||
func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limitNoAccepted bool, answers, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
|
||||
func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, notAccepted bool, views, answers int, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
|
||||
if words = filterWords(words); len(words) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -223,11 +225,26 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limit
|
|||
}
|
||||
|
||||
// check need filter has not accepted
|
||||
if limitNoAccepted {
|
||||
if notAccepted {
|
||||
b.And(builder.Eq{"accepted_answer_id": 0})
|
||||
args = append(args, 0)
|
||||
}
|
||||
|
||||
// check views
|
||||
if views > -1 {
|
||||
b.And(builder.Gte{"view_count": views})
|
||||
args = append(args, views)
|
||||
}
|
||||
|
||||
// check answers
|
||||
if answers == 0 {
|
||||
b.And(builder.Eq{"answer_count": answers})
|
||||
args = append(args, answers)
|
||||
} else if answers > 0 {
|
||||
b.And(builder.Gte{"answer_count": answers})
|
||||
args = append(args, answers)
|
||||
}
|
||||
|
||||
if answers == 0 {
|
||||
b.And(builder.Eq{"answer_count": 0})
|
||||
args = append(args, 0)
|
||||
|
@ -274,7 +291,7 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limit
|
|||
}
|
||||
|
||||
// SearchAnswers search answer data
|
||||
func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, limitAccepted bool, questionID string, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
|
||||
func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
|
||||
if words = filterWords(words); len(words) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -303,11 +320,23 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, limitAc
|
|||
}
|
||||
}
|
||||
|
||||
if limitAccepted {
|
||||
// check tags
|
||||
// check tag
|
||||
if len(tagIDs) > 0 {
|
||||
b.Join("INNER", "tag_rel", "question.id = tag_rel.object_id").
|
||||
Where(builder.In("tag_rel.tag_id", tagIDs))
|
||||
for _, tagID := range tagIDs {
|
||||
args = append(args, tagID)
|
||||
}
|
||||
}
|
||||
|
||||
// check limit accepted
|
||||
if accepted {
|
||||
b.Where(builder.Eq{"adopted": schema.AnswerAdoptedEnable})
|
||||
args = append(args, schema.AnswerAdoptedEnable)
|
||||
}
|
||||
|
||||
// check question id
|
||||
if questionID != "" {
|
||||
b.Where(builder.Eq{"question_id": questionID})
|
||||
args = append(args, questionID)
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/answerdev/answer/internal/service/revision_common"
|
||||
"github.com/answerdev/answer/internal/service/siteinfo"
|
||||
"github.com/answerdev/answer/internal/service/siteinfo_common"
|
||||
"github.com/answerdev/answer/internal/service/search_parser"
|
||||
"github.com/answerdev/answer/internal/service/tag"
|
||||
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
|
||||
"github.com/answerdev/answer/internal/service/uploader"
|
||||
|
@ -57,6 +58,7 @@ var ProviderSetService = wire.NewSet(
|
|||
revision_common.NewRevisionService,
|
||||
NewRevisionService,
|
||||
rank.NewRankService,
|
||||
search_parser.NewSearchParser,
|
||||
NewSearchService,
|
||||
meta.NewMetaService,
|
||||
object_info.NewObjService,
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
)
|
||||
|
||||
type AcceptedAnswerSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewAcceptedAnswerSearch(repo search_common.SearchRepo) *AcceptedAnswerSearch {
|
||||
return &AcceptedAnswerSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AcceptedAnswerSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
q,
|
||||
w,
|
||||
p string
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
w = dto.Query
|
||||
p = `isaccepted:yes`
|
||||
|
||||
if strings.Index(q, p) == 0 {
|
||||
ok = true
|
||||
w = strings.TrimPrefix(q, p)
|
||||
}
|
||||
|
||||
s.w = strings.TrimSpace(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *AcceptedAnswerSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
|
||||
words := strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
return s.repo.SearchAnswers(ctx, words, true, "", s.page, s.size, s.order)
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AnswerSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewAnswerSearch(repo search_common.SearchRepo) *AnswerSearch {
|
||||
return &AnswerSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AnswerSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
q,
|
||||
w,
|
||||
p string
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
w = dto.Query
|
||||
p = `is:answer`
|
||||
|
||||
if strings.Index(q, p) == 0 {
|
||||
ok = true
|
||||
w = strings.TrimPrefix(q, p)
|
||||
}
|
||||
|
||||
s.w = strings.TrimSpace(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *AnswerSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
|
||||
words := strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
return s.repo.SearchAnswers(ctx, words, false, "", s.page, s.size, s.order)
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
"github.com/answerdev/answer/pkg/converter"
|
||||
)
|
||||
|
||||
type AnswersSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
exp int
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewAnswersSearch(repo search_common.SearchRepo) *AnswersSearch {
|
||||
return &AnswersSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *AnswersSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
q,
|
||||
w,
|
||||
p,
|
||||
exp string
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
w = dto.Query
|
||||
p = `(?m)^answers:([0-9]+)`
|
||||
|
||||
re := regexp.MustCompile(p)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
exp = res[1]
|
||||
trimLen := len(res[0])
|
||||
w = q[trimLen:]
|
||||
ok = true
|
||||
}
|
||||
|
||||
s.exp = converter.StringToInt(exp)
|
||||
s.w = strings.TrimSpace(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
|
||||
func (s *AnswersSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
|
||||
words := strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
return s.repo.SearchQuestions(ctx, words, false, s.exp, s.page, s.size, s.order)
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||
)
|
||||
|
||||
type AuthorSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
userCommon *usercommon.UserCommon
|
||||
exp string
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewAuthorSearch(repo search_common.SearchRepo, userCommon *usercommon.UserCommon) *AuthorSearch {
|
||||
return &AuthorSearch{
|
||||
repo: repo,
|
||||
userCommon: userCommon,
|
||||
}
|
||||
}
|
||||
|
||||
// Parse
|
||||
// example: "user:12345" -> {exp="" w="12345"}
|
||||
func (s *AuthorSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
exp,
|
||||
q,
|
||||
w,
|
||||
p,
|
||||
me,
|
||||
name string
|
||||
)
|
||||
exp = ""
|
||||
q = dto.Query
|
||||
w = q
|
||||
p = `(?m)^user:([a-z0-9._-]+)`
|
||||
me = "user:me"
|
||||
|
||||
re := regexp.MustCompile(p)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
name = res[1]
|
||||
user, has, err := s.userCommon.GetUserBasicInfoByUserName(nil, name)
|
||||
if err == nil && has {
|
||||
exp = user.ID
|
||||
trimLen := len(res[0])
|
||||
w = q[trimLen:]
|
||||
ok = true
|
||||
}
|
||||
} else if strings.Index(q, me) == 0 {
|
||||
exp = dto.UserID
|
||||
w = strings.TrimPrefix(q, me)
|
||||
ok = true
|
||||
}
|
||||
|
||||
w = strings.TrimSpace(w)
|
||||
s.exp = exp
|
||||
s.w = w
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
|
||||
func (s *AuthorSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
var (
|
||||
words []string
|
||||
)
|
||||
|
||||
if len(s.exp) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
words = strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
resp, total, err = s.repo.SearchContents(ctx, words, "", s.exp, -1, s.page, s.size, s.order)
|
||||
|
||||
return
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type InQuestionSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
exp string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewInQuestionSearch(repo search_common.SearchRepo) *InQuestionSearch {
|
||||
return &InQuestionSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *InQuestionSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
w,
|
||||
q,
|
||||
p,
|
||||
exp string
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
w = dto.Query
|
||||
p = `(?m)^inquestion:([0-9]+)`
|
||||
|
||||
re := regexp.MustCompile(p)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
exp = res[1]
|
||||
trimLen := len(res[0])
|
||||
w = q[trimLen:]
|
||||
ok = true
|
||||
}
|
||||
|
||||
s.exp = exp
|
||||
s.w = strings.TrimSpace(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *InQuestionSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
var (
|
||||
words []string
|
||||
)
|
||||
|
||||
words = strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
return s.repo.SearchAnswers(ctx, words, false, s.exp, s.page, s.size, s.order)
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
)
|
||||
|
||||
type NotAcceptedQuestion struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewNotAcceptedQuestion(repo search_common.SearchRepo) *NotAcceptedQuestion {
|
||||
return &NotAcceptedQuestion{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *NotAcceptedQuestion) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
q,
|
||||
w,
|
||||
p string
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
w = dto.Query
|
||||
p = `hasaccepted:no`
|
||||
|
||||
if strings.Index(q, p) == 0 {
|
||||
ok = true
|
||||
w = strings.TrimPrefix(q, p)
|
||||
}
|
||||
|
||||
s.w = strings.TrimSpace(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *NotAcceptedQuestion) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
var (
|
||||
words []string
|
||||
)
|
||||
|
||||
words = strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
return s.repo.SearchQuestions(ctx, words, true, -1, s.page, s.size, s.order)
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
)
|
||||
|
||||
type ObjectSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewObjectSearch(repo search_common.SearchRepo) *ObjectSearch {
|
||||
return &ObjectSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ObjectSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
w string
|
||||
)
|
||||
w = strings.TrimSpace(dto.Query)
|
||||
if len(w) > 0 {
|
||||
ok = true
|
||||
}
|
||||
|
||||
s.w = w
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *ObjectSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
|
||||
words := strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
return s.repo.SearchContents(ctx, words, "", "", -1, s.page, s.size, s.order)
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type QuestionSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewQuestionSearch(repo search_common.SearchRepo) *QuestionSearch {
|
||||
return &QuestionSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *QuestionSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
q,
|
||||
w,
|
||||
p string
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
w = dto.Query
|
||||
p = `is:question`
|
||||
|
||||
if strings.Index(q, p) == 0 {
|
||||
ok = true
|
||||
w = strings.TrimPrefix(q, p)
|
||||
}
|
||||
|
||||
s.w = strings.TrimSpace(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
|
||||
func (s *QuestionSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
|
||||
words := strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
return s.repo.SearchQuestions(ctx, words, false, -1, s.page, s.size, s.order)
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
"github.com/answerdev/answer/pkg/converter"
|
||||
)
|
||||
|
||||
type ScoreSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
exp int
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewScoreSearch(repo search_common.SearchRepo) *ScoreSearch {
|
||||
return &ScoreSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ScoreSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
exp := ""
|
||||
q := dto.Query
|
||||
w := q
|
||||
p := `(?m)^score:([0-9]+)`
|
||||
|
||||
re := regexp.MustCompile(p)
|
||||
res := re.FindStringSubmatch(w)
|
||||
if len(res) == 2 {
|
||||
exp = res[1]
|
||||
trimLen := len(res[0])
|
||||
w = q[trimLen:]
|
||||
ok = true
|
||||
}
|
||||
|
||||
w = strings.TrimSpace(w)
|
||||
s.exp = converter.StringToInt(exp)
|
||||
s.w = w
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *ScoreSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
var (
|
||||
words []string
|
||||
)
|
||||
|
||||
words = strings.Split(s.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
resp, total, err = s.repo.SearchContents(ctx, words, "", "", s.exp, s.page, s.size, s.order)
|
||||
return
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/answerdev/answer/internal/entity"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/activity_common"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
|
||||
)
|
||||
|
||||
type TagSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
tagRepo tagcommon.TagRepo
|
||||
followCommon activity_common.FollowRepo
|
||||
page int
|
||||
size int
|
||||
exp string
|
||||
w string
|
||||
userID string
|
||||
Extra schema.GetTagPageResp
|
||||
order string
|
||||
}
|
||||
|
||||
func NewTagSearch(repo search_common.SearchRepo, tagRepo tagcommon.TagRepo, followCommon activity_common.FollowRepo) *TagSearch {
|
||||
return &TagSearch{
|
||||
repo: repo,
|
||||
tagRepo: tagRepo,
|
||||
followCommon: followCommon,
|
||||
}
|
||||
}
|
||||
|
||||
// Parse
|
||||
// example: "[tag]hello" -> {exp="tag" w="hello"}
|
||||
func (ts *TagSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
exp := ""
|
||||
w := dto.Query
|
||||
q := w
|
||||
p := `(?m)^\[([a-zA-Z0-9-\+\.#]+)\]`
|
||||
|
||||
re := regexp.MustCompile(p)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
exp = res[1]
|
||||
trimLen := len(res[0])
|
||||
w = q[trimLen:]
|
||||
ok = true
|
||||
}
|
||||
w = strings.TrimSpace(w)
|
||||
ts.exp = exp
|
||||
ts.w = w
|
||||
ts.page = dto.Page
|
||||
ts.size = dto.Size
|
||||
ts.userID = dto.UserID
|
||||
ts.order = dto.Order
|
||||
return ok
|
||||
}
|
||||
|
||||
func (ts *TagSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
var (
|
||||
words []string
|
||||
tag *entity.Tag
|
||||
exists, followed bool
|
||||
)
|
||||
tag, exists, err = ts.tagRepo.GetTagBySlugName(ctx, ts.exp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ts.userID != "" {
|
||||
followed, err = ts.followCommon.IsFollowed(ts.userID, tag.ID)
|
||||
}
|
||||
|
||||
ts.Extra = schema.GetTagPageResp{
|
||||
TagID: tag.ID,
|
||||
SlugName: tag.SlugName,
|
||||
DisplayName: tag.DisplayName,
|
||||
OriginalText: tag.OriginalText,
|
||||
ParsedText: tag.ParsedText,
|
||||
QuestionCount: tag.QuestionCount,
|
||||
IsFollower: followed,
|
||||
}
|
||||
ts.Extra.GetExcerpt()
|
||||
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
words = strings.Split(ts.w, " ")
|
||||
if len(words) > 3 {
|
||||
words = words[:4]
|
||||
}
|
||||
|
||||
resp, total, err = ts.repo.SearchContents(ctx, words, tag.ID, "", -1, ts.page, ts.size, ts.order)
|
||||
|
||||
return
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ViewsSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
exp string
|
||||
q string
|
||||
order string
|
||||
}
|
||||
|
||||
func NewViewsSearch(repo search_common.SearchRepo) *ViewsSearch {
|
||||
return &ViewsSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ViewsSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
exp := ""
|
||||
w := dto.Query
|
||||
q := w
|
||||
p := `(?m)^views:([0-9]+)`
|
||||
|
||||
re := regexp.MustCompile(p)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
exp = res[1]
|
||||
trimLen := len(res[0])
|
||||
q = w[trimLen:]
|
||||
ok = true
|
||||
}
|
||||
|
||||
q = strings.TrimSpace(q)
|
||||
s.exp = exp
|
||||
s.q = q
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
func (s *ViewsSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
return
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
)
|
||||
|
||||
type WithinSearch struct {
|
||||
repo search_common.SearchRepo
|
||||
w string
|
||||
page int
|
||||
size int
|
||||
order string
|
||||
}
|
||||
|
||||
func NewWithinSearch(repo search_common.SearchRepo) *WithinSearch {
|
||||
return &WithinSearch{
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WithinSearch) Parse(dto *schema.SearchDTO) (ok bool) {
|
||||
var (
|
||||
q string
|
||||
w []rune
|
||||
hasEnd bool
|
||||
)
|
||||
|
||||
q = dto.Query
|
||||
|
||||
if q[0:1] == `"` {
|
||||
for _, v := range []rune(q) {
|
||||
if len(w) == 0 && string(v) == `"` {
|
||||
continue
|
||||
} else if string(v) == `"` {
|
||||
hasEnd = true
|
||||
break
|
||||
} else {
|
||||
w = append(w, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasEnd {
|
||||
ok = true
|
||||
}
|
||||
|
||||
s.w = string(w)
|
||||
s.page = dto.Page
|
||||
s.size = dto.Size
|
||||
s.order = dto.Order
|
||||
return
|
||||
}
|
||||
|
||||
func (s *WithinSearch) Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error) {
|
||||
return s.repo.SearchContents(ctx, []string{s.w}, "", "", -1, s.page, s.size, s.order)
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
type SearchRepo interface {
|
||||
SearchContents(ctx context.Context, words []string, tagID, userID string, votes, page, size int, order string) (resp []schema.SearchResp, total int64, err error)
|
||||
SearchQuestions(ctx context.Context, words []string, limitNoAccepted bool, answers, page, size int, order string) (resp []schema.SearchResp, total int64, err error)
|
||||
SearchAnswers(ctx context.Context, words []string, limitAccepted bool, questionID string, page, size int, order string) (resp []schema.SearchResp, total int64, err error)
|
||||
SearchContents(ctx context.Context, words []string, tagIDs []string, userID string, votes, page, size int, order string) (resp []schema.SearchResp, total int64, err error)
|
||||
SearchQuestions(ctx context.Context, words []string, notAccepted bool, views, answers int, page, size int, order string) (resp []schema.SearchResp, total int64, err error)
|
||||
SearchAnswers(ctx context.Context, words []string, tagIDs []string, accepted bool, questionID string, page, size int, order string) (resp []schema.SearchResp, total int64, err error)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,359 @@
|
|||
package search_parser
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
|
||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||
"github.com/answerdev/answer/pkg/converter"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SearchParser struct {
|
||||
tagRepo tagcommon.TagRepo
|
||||
userCommon *usercommon.UserCommon
|
||||
}
|
||||
|
||||
func NewSearchParser(tagRepo tagcommon.TagRepo, userCommon *usercommon.UserCommon) *SearchParser {
|
||||
return &SearchParser{
|
||||
tagRepo: tagRepo,
|
||||
userCommon: userCommon,
|
||||
}
|
||||
}
|
||||
|
||||
// ParseStructure parse search structure, maybe match one of type all/questions/answers,
|
||||
// but if match two type, it will return false
|
||||
func (sp *SearchParser) ParseStructure(dto *schema.SearchDTO) (
|
||||
searchType string,
|
||||
// search all
|
||||
userID string,
|
||||
votes int,
|
||||
// search questions
|
||||
notAccepted bool,
|
||||
isQuestion bool,
|
||||
views,
|
||||
answers int,
|
||||
// search answers
|
||||
accepted bool,
|
||||
questionID string,
|
||||
isAnswer bool,
|
||||
// common fields
|
||||
tags,
|
||||
words []string,
|
||||
) {
|
||||
var (
|
||||
query = dto.Query
|
||||
currentUserID = dto.UserID
|
||||
all = 0
|
||||
q = 0
|
||||
a = 0
|
||||
withWords = []string{}
|
||||
limitWords = 5
|
||||
)
|
||||
|
||||
// match tags
|
||||
tags = sp.parseTags(&query)
|
||||
|
||||
// match all
|
||||
userID = sp.parseUserID(&query, currentUserID)
|
||||
if userID != "" {
|
||||
searchType = "all"
|
||||
all = 1
|
||||
}
|
||||
votes = sp.parseVotes(&query)
|
||||
if votes != -1 {
|
||||
searchType = "all"
|
||||
all = 1
|
||||
}
|
||||
withWords = sp.parseWithin(&query)
|
||||
if len(withWords) > 0 {
|
||||
searchType = "all"
|
||||
all = 1
|
||||
}
|
||||
|
||||
// match questions
|
||||
notAccepted = sp.parseNotAccepted(&query)
|
||||
if notAccepted {
|
||||
searchType = "question"
|
||||
q = 1
|
||||
}
|
||||
isQuestion = sp.parseIsQuestion(&query)
|
||||
if isQuestion {
|
||||
searchType = "question"
|
||||
q = 1
|
||||
}
|
||||
views = sp.parseViews(&query)
|
||||
if views != -1 {
|
||||
searchType = "question"
|
||||
q = 1
|
||||
}
|
||||
answers = sp.parseAnswers(&query)
|
||||
if answers != -1 {
|
||||
searchType = "question"
|
||||
q = 1
|
||||
}
|
||||
|
||||
// match answers
|
||||
accepted = sp.parseAccepted(&query)
|
||||
if accepted {
|
||||
searchType = "answer"
|
||||
a = 1
|
||||
}
|
||||
questionID = sp.parseQuestionID(&query)
|
||||
if questionID != "" {
|
||||
searchType = "answer"
|
||||
a = 1
|
||||
}
|
||||
isAnswer = sp.parseIsAnswer(&query)
|
||||
if isAnswer {
|
||||
searchType = "answer"
|
||||
a = 1
|
||||
}
|
||||
|
||||
words = strings.Split(query, " ")
|
||||
if len(withWords) > 0 {
|
||||
words = append(withWords, words...)
|
||||
}
|
||||
|
||||
// check limit words
|
||||
if len(words) > limitWords {
|
||||
words = words[:limitWords]
|
||||
}
|
||||
|
||||
// check tags' search is all or question
|
||||
if len(tags) > 0 {
|
||||
if len(words) > 0 {
|
||||
searchType = "all"
|
||||
all = 1
|
||||
} else {
|
||||
searchType = "question"
|
||||
q = 1
|
||||
}
|
||||
}
|
||||
|
||||
// check match types greater than 1
|
||||
if all+q+a > 1 {
|
||||
searchType = ""
|
||||
}
|
||||
|
||||
// check not match
|
||||
if all+q+a == 0 && len(words) > 0 {
|
||||
searchType = "all"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseTags parse search tags, return tag ids array
|
||||
func (sp *SearchParser) parseTags(query *string) (tags []string) {
|
||||
var (
|
||||
// expire tag pattern
|
||||
exprTag = `(?m)\[([a-zA-Z0-9-\+\.#]+)\]{1}?`
|
||||
q = *query
|
||||
limit = 5
|
||||
)
|
||||
|
||||
re := regexp.MustCompile(exprTag)
|
||||
res := re.FindAllStringSubmatch(q, -1)
|
||||
if len(res) == 0 {
|
||||
return
|
||||
}
|
||||
tags = make([]string, len(res))
|
||||
for i, item := range res {
|
||||
tag, exists, err := sp.tagRepo.GetTagBySlugName(context.TODO(), item[1])
|
||||
if err != nil || !exists {
|
||||
continue
|
||||
}
|
||||
tags[i] = tag.ID
|
||||
}
|
||||
|
||||
// limit maximum 5 tags
|
||||
if len(tags) > limit {
|
||||
tags = tags[:limit]
|
||||
}
|
||||
|
||||
q = strings.TrimSpace(re.ReplaceAllString(q, ""))
|
||||
*query = q
|
||||
return
|
||||
}
|
||||
|
||||
// parseUserID return user id or current login user id
|
||||
func (sp *SearchParser) parseUserID(query *string, currentUserID string) (userID string) {
|
||||
var (
|
||||
exprUserID = `(?m)^user:([a-z0-9._-]+)`
|
||||
exprMe = "user:me"
|
||||
q = *query
|
||||
)
|
||||
|
||||
re := regexp.MustCompile(exprUserID)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
name := res[1]
|
||||
user, has, err := sp.userCommon.GetUserBasicInfoByUserName(nil, name)
|
||||
if err == nil && has {
|
||||
userID = user.ID
|
||||
q = re.ReplaceAllString(q, "")
|
||||
}
|
||||
} else if strings.Index(q, exprMe) != -1 {
|
||||
userID = currentUserID
|
||||
q = strings.ReplaceAll(q, exprMe, "")
|
||||
}
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseVotes return the votes of search query
|
||||
func (sp *SearchParser) parseVotes(query *string) (votes int) {
|
||||
var (
|
||||
expr = `(?m)^score:([0-9]+)`
|
||||
q = *query
|
||||
)
|
||||
votes = -1
|
||||
|
||||
re := regexp.MustCompile(expr)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
votes = converter.StringToInt(res[1])
|
||||
q = re.ReplaceAllString(q, "")
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseWithin parse quotes within words like: "hello world"
|
||||
func (sp *SearchParser) parseWithin(query *string) (words []string) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `(?U)(".+")`
|
||||
)
|
||||
re := regexp.MustCompile(expr)
|
||||
matches := re.FindAllStringSubmatch(q, -1)
|
||||
words = []string{}
|
||||
for _, match := range matches {
|
||||
words = append(words, match[1])
|
||||
}
|
||||
q = re.ReplaceAllString(q, "")
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseNotAccepted return the question has not accepted the answer
|
||||
func (sp *SearchParser) parseNotAccepted(query *string) (notAccepted bool) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `hasaccepted:no`
|
||||
)
|
||||
|
||||
if strings.Index(q, expr) != -1 {
|
||||
q = strings.ReplaceAll(q, expr, "")
|
||||
notAccepted = true
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseIsQuestion check the result if only limit question or not
|
||||
func (sp *SearchParser) parseIsQuestion(query *string) (isQuestion bool) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `is:question`
|
||||
)
|
||||
|
||||
if strings.Index(q, expr) == 0 {
|
||||
q = strings.ReplaceAll(q, expr, "")
|
||||
isQuestion = true
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseViews check search has views or not
|
||||
func (sp *SearchParser) parseViews(query *string) (views int) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `(?m)^views:([0-9]+)`
|
||||
)
|
||||
views = -1
|
||||
|
||||
re := regexp.MustCompile(expr)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
views = converter.StringToInt(res[1])
|
||||
q = re.ReplaceAllString(q, "")
|
||||
}
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseAnswers check whether specified answer count for question
|
||||
func (sp *SearchParser) parseAnswers(query *string) (answers int) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `(?m)^answers:([0-9]+)`
|
||||
)
|
||||
answers = -1
|
||||
|
||||
re := regexp.MustCompile(expr)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
answers = converter.StringToInt(res[1])
|
||||
q = re.ReplaceAllString(q, "")
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseAccepted check the search is limit accepted answer or not
|
||||
func (sp *SearchParser) parseAccepted(query *string) (accepted bool) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `isaccepted:yes`
|
||||
)
|
||||
|
||||
if strings.Index(q, expr) != -1 {
|
||||
accepted = true
|
||||
strings.ReplaceAll(q, expr, "")
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseQuestionID check whether specified question's id
|
||||
func (sp *SearchParser) parseQuestionID(query *string) (questionID string) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `(?m)^inquestion:([0-9]+)`
|
||||
)
|
||||
|
||||
re := regexp.MustCompile(expr)
|
||||
res := re.FindStringSubmatch(q)
|
||||
if len(res) == 2 {
|
||||
questionID = res[1]
|
||||
q = re.ReplaceAllString(q, "")
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
||||
|
||||
// parseIsAnswer check the result if only limit answer or not
|
||||
func (sp *SearchParser) parseIsAnswer(query *string) (isAnswer bool) {
|
||||
var (
|
||||
q = *query
|
||||
expr = `is:answer`
|
||||
)
|
||||
|
||||
if strings.Index(q, expr) != -1 {
|
||||
isAnswer = true
|
||||
q = strings.ReplaceAll(q, expr, "")
|
||||
}
|
||||
|
||||
*query = strings.TrimSpace(q)
|
||||
return
|
||||
}
|
|
@ -2,92 +2,61 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
"github.com/answerdev/answer/internal/service/activity_common"
|
||||
"github.com/answerdev/answer/internal/service/search"
|
||||
"github.com/answerdev/answer/internal/service/search_common"
|
||||
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
|
||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||
"github.com/answerdev/answer/internal/service/search_parser"
|
||||
)
|
||||
|
||||
type Search interface {
|
||||
Parse(dto *schema.SearchDTO) (ok bool)
|
||||
Search(ctx context.Context) (resp []schema.SearchResp, total int64, err error)
|
||||
}
|
||||
|
||||
type SearchService struct {
|
||||
searchRepo search_common.SearchRepo
|
||||
tagSearch *search.TagSearch
|
||||
withinSearch *search.WithinSearch
|
||||
authorSearch *search.AuthorSearch
|
||||
scoreSearch *search.ScoreSearch
|
||||
answersSearch *search.AnswersSearch
|
||||
notAcceptedQuestion *search.NotAcceptedQuestion
|
||||
acceptedAnswerSearch *search.AcceptedAnswerSearch
|
||||
inQuestionSearch *search.InQuestionSearch
|
||||
questionSearch *search.QuestionSearch
|
||||
answerSearch *search.AnswerSearch
|
||||
viewsSearch *search.ViewsSearch
|
||||
objectSearch *search.ObjectSearch
|
||||
searchParser *search_parser.SearchParser
|
||||
searchRepo search_common.SearchRepo
|
||||
}
|
||||
|
||||
func NewSearchService(
|
||||
searchParser *search_parser.SearchParser,
|
||||
searchRepo search_common.SearchRepo,
|
||||
tagRepo tagcommon.TagRepo,
|
||||
userCommon *usercommon.UserCommon,
|
||||
followCommon activity_common.FollowRepo,
|
||||
) *SearchService {
|
||||
return &SearchService{
|
||||
searchRepo: searchRepo,
|
||||
tagSearch: search.NewTagSearch(searchRepo, tagRepo, followCommon),
|
||||
withinSearch: search.NewWithinSearch(searchRepo),
|
||||
authorSearch: search.NewAuthorSearch(searchRepo, userCommon),
|
||||
scoreSearch: search.NewScoreSearch(searchRepo),
|
||||
answersSearch: search.NewAnswersSearch(searchRepo),
|
||||
acceptedAnswerSearch: search.NewAcceptedAnswerSearch(searchRepo),
|
||||
notAcceptedQuestion: search.NewNotAcceptedQuestion(searchRepo),
|
||||
inQuestionSearch: search.NewInQuestionSearch(searchRepo),
|
||||
questionSearch: search.NewQuestionSearch(searchRepo),
|
||||
answerSearch: search.NewAnswerSearch(searchRepo),
|
||||
viewsSearch: search.NewViewsSearch(searchRepo),
|
||||
objectSearch: search.NewObjectSearch(searchRepo),
|
||||
searchParser: searchParser,
|
||||
searchRepo: searchRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// Search search contents
|
||||
func (ss *SearchService) Search(ctx context.Context, dto *schema.SearchDTO) (resp []schema.SearchResp, total int64, extra interface{}, err error) {
|
||||
extra = nil
|
||||
if dto.Page < 1 {
|
||||
dto.Page = 1
|
||||
}
|
||||
|
||||
switch {
|
||||
case ss.tagSearch.Parse(dto):
|
||||
resp, total, err = ss.tagSearch.Search(ctx)
|
||||
extra = ss.tagSearch.Extra
|
||||
case ss.withinSearch.Parse(dto):
|
||||
resp, total, err = ss.withinSearch.Search(ctx)
|
||||
case ss.authorSearch.Parse(dto):
|
||||
resp, total, err = ss.authorSearch.Search(ctx)
|
||||
case ss.scoreSearch.Parse(dto):
|
||||
resp, total, err = ss.scoreSearch.Search(ctx)
|
||||
case ss.answersSearch.Parse(dto):
|
||||
resp, total, err = ss.answersSearch.Search(ctx)
|
||||
case ss.acceptedAnswerSearch.Parse(dto):
|
||||
resp, total, err = ss.acceptedAnswerSearch.Search(ctx)
|
||||
case ss.notAcceptedQuestion.Parse(dto):
|
||||
resp, total, err = ss.notAcceptedQuestion.Search(ctx)
|
||||
case ss.inQuestionSearch.Parse(dto):
|
||||
resp, total, err = ss.inQuestionSearch.Search(ctx)
|
||||
case ss.questionSearch.Parse(dto):
|
||||
resp, total, err = ss.questionSearch.Search(ctx)
|
||||
case ss.answerSearch.Parse(dto):
|
||||
resp, total, err = ss.answerSearch.Search(ctx)
|
||||
case ss.viewsSearch.Parse(dto):
|
||||
resp, total, err = ss.viewsSearch.Search(ctx)
|
||||
default:
|
||||
ss.objectSearch.Parse(dto)
|
||||
resp, total, err = ss.objectSearch.Search(ctx)
|
||||
// search type
|
||||
searchType,
|
||||
// search all
|
||||
userID,
|
||||
votes,
|
||||
// search questions
|
||||
notAccepted,
|
||||
_,
|
||||
views,
|
||||
answers,
|
||||
// search answers
|
||||
accepted,
|
||||
questionID,
|
||||
_,
|
||||
// common fields
|
||||
tags,
|
||||
words := ss.searchParser.ParseStructure(dto)
|
||||
|
||||
switch searchType {
|
||||
case "all":
|
||||
resp, total, err = ss.searchRepo.SearchContents(ctx, words, tags, userID, votes, dto.Page, dto.Size, dto.Order)
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
}
|
||||
case "question":
|
||||
resp, total, err = ss.searchRepo.SearchQuestions(ctx, words, notAccepted, views, answers, dto.Page, dto.Size, dto.Order)
|
||||
case "answer":
|
||||
resp, total, err = ss.searchRepo.SearchAnswers(ctx, words, tags, accepted, questionID, dto.Page, dto.Size, dto.Order)
|
||||
}
|
||||
return resp, total, extra, err
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue