func()

in internal/repo/search_common/search_repo.go [356:448]


func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs [][]string, accepted bool, questionID string, page, pageSize int, order string) (resp []*schema.SearchResult, total int64, err error) {
	words = filterWords(words)

	var (
		afs  = aFields
		args = []interface{}{}
	)
	if order == "relevance" {
		if len(words) > 0 {
			afs, args = addRelevanceField([]string{"`answer`.`original_text`"}, words, afs)
		} else {
			order = "newest"
		}
	}

	b := builder.MySQL().Select(afs...).From("`answer`").
		LeftJoin("`question`", "`question`.id = `answer`.question_id")

	b.Where(builder.Lt{"`question`.`status`": entity.QuestionStatusDeleted}).
		And(builder.Lt{"`answer`.`status`": entity.AnswerStatusDeleted}).And(builder.Eq{"`question`.`show`": entity.QuestionShow})
	args = append(args, entity.QuestionStatusDeleted, entity.AnswerStatusDeleted, entity.QuestionShow)

	likeConA := builder.NewCond()
	for _, word := range words {
		likeConA = likeConA.Or(builder.Like{"`answer`.original_text", word})
		args = append(args, "%"+word+"%")
	}

	b.Where(likeConA)

	// 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 limit accepted
	if accepted {
		b.Where(builder.Eq{"adopted": schema.AnswerAcceptedEnable})
		args = append(args, schema.AnswerAcceptedEnable)
	}

	// check question id
	if questionID != "" {
		b.Where(builder.Eq{"question_id": questionID})
		args = append(args, questionID)
	}

	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
	}

	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
}