in internal/repo/search_common/search_repo.go [245:353]
func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, tagIDs [][]string, notAccepted bool, views, answers int, page, pageSize int, order string) (resp []*schema.SearchResult, total int64, err error) {
words = filterWords(words)
var (
qfs = qFields
args = []interface{}{}
)
if order == "relevance" {
if len(words) > 0 {
qfs, args = addRelevanceField([]string{"title", "original_text"}, words, qfs)
} else {
order = "newest"
}
}
b := builder.MySQL().Select(qfs...).From("question")
b.Where(builder.Lt{"`question`.`status`": entity.QuestionStatusDeleted}).And(builder.Eq{"`question`.`show`": entity.QuestionShow})
args = append(args, entity.QuestionStatusDeleted, entity.QuestionShow)
likeConQ := builder.NewCond()
for _, word := range words {
likeConQ = likeConQ.Or(builder.Like{"title", word}).
Or(builder.Like{"original_text", word})
args = append(args, "%"+word+"%")
args = append(args, "%"+word+"%")
}
b.Where(likeConQ)
// check tag
for ti, tagID := range tagIDs {
ast := "tag_rel" + strconv.Itoa(ti)
b.Join("INNER", "tag_rel as "+ast, "question.id = "+ast+".object_id").
And(builder.Eq{
ast + ".status": entity.TagRelStatusAvailable,
}).
And(builder.In(ast+".tag_id", tagID))
args = append(args, entity.TagRelStatusAvailable)
for _, t := range tagID {
args = append(args, t)
}
}
// check need filter has not accepted
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)
} else if answers > 0 {
b.And(builder.Gte{"answer_count": answers})
args = append(args, answers)
}
queryArgs := []interface{}{}
countArgs := []interface{}{}
countSQL, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
if err != nil {
return
}
startNum := (page - 1) * pageSize
querySQL, _, err := b.OrderBy(sr.parseOrder(ctx, order)).Limit(pageSize, startNum).ToSQL()
if err != nil {
return
}
queryArgs = append(queryArgs, querySQL)
queryArgs = append(queryArgs, args...)
countArgs = append(countArgs, countSQL)
countArgs = append(countArgs, args...)
res, err := sr.data.DB.Context(ctx).Query(queryArgs...)
if err != nil {
return
}
tr, err := sr.data.DB.Context(ctx).Query(countArgs...)
if err != nil {
return
}
if len(tr) != 0 {
total = converter.StringToInt64(string(tr[0]["total"]))
}
resp, err = sr.parseResult(ctx, res, words)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}