This is an automated email from the ASF dual-hosted git repository. kumfo pushed a commit to branch feat/1.3.6/hottest in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
commit 795febe0ee683997ad2f23085d61394b7074c14d Author: kumfo <[email protected]> AuthorDate: Thu Jul 11 17:27:03 2024 +0800 feat(hot): change frequent to hot --- cmd/wire_gen.go | 2 +- docs/docs.go | 2 +- i18n/af_ZA.yaml | 2 +- i18n/ar_SA.yaml | 2 +- i18n/az_AZ.yaml | 2 +- i18n/bal_BA.yaml | 2 +- i18n/ban_ID.yaml | 2 +- i18n/bn_BD.yaml | 2 +- i18n/bs_BA.yaml | 2 +- i18n/ca_ES.yaml | 2 +- i18n/cs_CZ.yaml | 2 +- i18n/cy_GB.yaml | 2 +- i18n/da_DK.yaml | 2 +- i18n/de_DE.yaml | 2 +- i18n/el_GR.yaml | 2 +- i18n/es_ES.yaml | 2 +- i18n/fa_IR.yaml | 2 +- i18n/fi_FI.yaml | 2 +- i18n/fr_FR.yaml | 2 +- i18n/he_IL.yaml | 2 +- i18n/hi_IN.yaml | 2 +- i18n/hu_HU.yaml | 2 +- i18n/hy_AM.yaml | 2 +- i18n/id_ID.yaml | 2 +- i18n/it_IT.yaml | 2 +- i18n/ja_JP.yaml | 2 +- i18n/ko_KR.yaml | 2 +- i18n/nl_NL.yaml | 2 +- i18n/no_NO.yaml | 2 +- i18n/pl_PL.yaml | 2 +- i18n/pt_BR.yaml | 2 +- i18n/pt_PT.yaml | 2 +- i18n/ro_RO.yaml | 2 +- i18n/ru_RU.yaml | 2 +- i18n/sk_SK.yaml | 2 +- i18n/sq_AL.yaml | 2 +- i18n/sr_SP.yaml | 2 +- i18n/sv_SE.yaml | 2 +- i18n/te_IN.yaml | 2 +- i18n/tr_TR.yaml | 2 +- i18n/uk_UA.yaml | 2 +- i18n/vi_VN.yaml | 2 +- i18n/zh_TW.yaml | 2 +- internal/base/cron/cron.go | 10 +++ internal/entity/question_entity.go | 1 + internal/repo/answer/answer_repo.go | 11 +++ internal/repo/question/question_repo.go | 4 +- internal/schema/question_schema.go | 11 ++- internal/service/answer_common/answer.go | 1 + .../service/content/question_hottest_service.go | 89 ++++++++++++++++++++++ internal/service/content/question_service.go | 10 ++- 51 files changed, 173 insertions(+), 50 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index e7ff464c..e9967e83 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -194,7 +194,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, externalNotificationService := notification.NewExternalNotificationService(dataData, userNotificationConfigRepo, followRepo, emailService, userRepo, externalNotificationQueueService, userExternalLoginRepo, siteInfoCommonService) reviewRepo := review.NewReviewRepo(dataData) reviewService := review2.NewReviewService(reviewRepo, objService, userCommon, userRepo, questionRepo, answerRepo, userRoleRelService, externalNotificationQueueService, tagCommonService, notificationQueueService, siteInfoCommonService) - questionService := content.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, userRepo, userRoleRelService, revisionService, metaCommonService, collectionCommon, answerActivityService, emailService, notificationQueueService, externalNotificationQueueService, activityQueueService, siteInfoCommonService, externalNotificationService, reviewService, configService) + questionService := content.NewQuestionService(questionRepo, answerRepo, tagCommonService, questionCommon, userCommon, userRepo, userRoleRelService, revisionService, metaCommonService, collectionCommon, answerActivityService, emailService, notificationQueueService, externalNotificationQueueService, activityQueueService, siteInfoCommonService, externalNotificationService, reviewService, configService) answerService := content.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, notificationQueueService, externalNotificationQueueService, activityQueueService, reviewService) reportHandle := report_handle.NewReportHandle(questionService, answerService, commentService) reportService := report2.NewReportService(reportRepo, objService, userCommon, answerRepo, questionRepo, commentCommonRepo, reportHandle, configService) diff --git a/docs/docs.go b/docs/docs.go index ec6aafce..b734123f 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -8833,7 +8833,7 @@ const docTemplate = `{ "enum": [ "newest", "active", - "frequent", + "hot", "score", "unanswered" ] diff --git a/i18n/af_ZA.yaml b/i18n/af_ZA.yaml index 8227460c..efef6068 100644 --- a/i18n/af_ZA.yaml +++ b/i18n/af_ZA.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/ar_SA.yaml b/i18n/ar_SA.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/ar_SA.yaml +++ b/i18n/ar_SA.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/az_AZ.yaml b/i18n/az_AZ.yaml index 2252bdcd..a667823b 100644 --- a/i18n/az_AZ.yaml +++ b/i18n/az_AZ.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/bal_BA.yaml b/i18n/bal_BA.yaml index 2252bdcd..a667823b 100644 --- a/i18n/bal_BA.yaml +++ b/i18n/bal_BA.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/ban_ID.yaml b/i18n/ban_ID.yaml index 2252bdcd..a667823b 100644 --- a/i18n/ban_ID.yaml +++ b/i18n/ban_ID.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/bn_BD.yaml b/i18n/bn_BD.yaml index 2252bdcd..a667823b 100644 --- a/i18n/bn_BD.yaml +++ b/i18n/bn_BD.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/bs_BA.yaml b/i18n/bs_BA.yaml index 2252bdcd..a667823b 100644 --- a/i18n/bs_BA.yaml +++ b/i18n/bs_BA.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/ca_ES.yaml b/i18n/ca_ES.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/ca_ES.yaml +++ b/i18n/ca_ES.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/cs_CZ.yaml b/i18n/cs_CZ.yaml index 4414f945..00f9f990 100644 --- a/i18n/cs_CZ.yaml +++ b/i18n/cs_CZ.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/cy_GB.yaml b/i18n/cy_GB.yaml index b3c696fa..833cb090 100644 --- a/i18n/cy_GB.yaml +++ b/i18n/cy_GB.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/da_DK.yaml b/i18n/da_DK.yaml index 85ead2ab..fe4bf6ab 100644 --- a/i18n/da_DK.yaml +++ b/i18n/da_DK.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/de_DE.yaml b/i18n/de_DE.yaml index c82a4255..c8dac06c 100644 --- a/i18n/de_DE.yaml +++ b/i18n/de_DE.yaml @@ -1249,7 +1249,7 @@ ui: answers: Antworten newest: Neueste active: Aktiv - frequent: Häufig + hot: Hot score: Punktzahl unanswered: Unbeantwortet modified: geändert diff --git a/i18n/el_GR.yaml b/i18n/el_GR.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/el_GR.yaml +++ b/i18n/el_GR.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/es_ES.yaml b/i18n/es_ES.yaml index f1696bce..551f80e0 100644 --- a/i18n/es_ES.yaml +++ b/i18n/es_ES.yaml @@ -1249,7 +1249,7 @@ ui: answers: Respuestas newest: Más reciente active: Activo - frequent: Frecuente + hot: Hot score: Puntuación unanswered: Sin respuesta modified: modificada diff --git a/i18n/fa_IR.yaml b/i18n/fa_IR.yaml index e84840d3..f6d8c47c 100644 --- a/i18n/fa_IR.yaml +++ b/i18n/fa_IR.yaml @@ -1249,7 +1249,7 @@ ui: answers: پاسخ ها newest: جدیدترین active: فعال - frequent: پرتکرار + hot: Hot score: امتیاز unanswered: بدون پاسخ modified: تغییر یافته diff --git a/i18n/fi_FI.yaml b/i18n/fi_FI.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/fi_FI.yaml +++ b/i18n/fi_FI.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/fr_FR.yaml b/i18n/fr_FR.yaml index 4adf0807..7fab3d3b 100644 --- a/i18n/fr_FR.yaml +++ b/i18n/fr_FR.yaml @@ -1249,7 +1249,7 @@ ui: answers: Réponses newest: Les plus récents active: Actif - frequent: Fréquents + hot: Hot score: Score unanswered: Sans réponse modified: modifié diff --git a/i18n/he_IL.yaml b/i18n/he_IL.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/he_IL.yaml +++ b/i18n/he_IL.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/hi_IN.yaml b/i18n/hi_IN.yaml index 85ead2ab..fe4bf6ab 100644 --- a/i18n/hi_IN.yaml +++ b/i18n/hi_IN.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/hu_HU.yaml b/i18n/hu_HU.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/hu_HU.yaml +++ b/i18n/hu_HU.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/hy_AM.yaml b/i18n/hy_AM.yaml index 2252bdcd..a667823b 100644 --- a/i18n/hy_AM.yaml +++ b/i18n/hy_AM.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/id_ID.yaml b/i18n/id_ID.yaml index 4dead453..2053e9ea 100644 --- a/i18n/id_ID.yaml +++ b/i18n/id_ID.yaml @@ -1249,7 +1249,7 @@ ui: answers: Jawaban newest: Terbaru active: Aktif - frequent: Sering + hot: Hot score: Nilai unanswered: Belum dijawab modified: diubah diff --git a/i18n/it_IT.yaml b/i18n/it_IT.yaml index 9b39853a..4a33c69b 100644 --- a/i18n/it_IT.yaml +++ b/i18n/it_IT.yaml @@ -1249,7 +1249,7 @@ ui: answers: Risposte newest: Più recenti active: Attivo - frequent: Frequenti + hot: Hot score: Punteggio unanswered: Senza risposta modified: Modificato diff --git a/i18n/ja_JP.yaml b/i18n/ja_JP.yaml index 045b06bf..db7175d6 100644 --- a/i18n/ja_JP.yaml +++ b/i18n/ja_JP.yaml @@ -1249,7 +1249,7 @@ ui: answers: 回答 newest: 最新 active: 有効 - frequent: 頻繁 + hot: Hot score: スコア unanswered: 未回答 modified: 修正済み diff --git a/i18n/ko_KR.yaml b/i18n/ko_KR.yaml index 9e6f3571..3778d5c7 100644 --- a/i18n/ko_KR.yaml +++ b/i18n/ko_KR.yaml @@ -1249,7 +1249,7 @@ ui: answers: 답변 newest: 최신순 active: 활성순 - frequent: 자주 본 질문 + hot: Hot score: 평점순 unanswered: 답변이 없는 질문 modified: 수정됨 diff --git a/i18n/nl_NL.yaml b/i18n/nl_NL.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/nl_NL.yaml +++ b/i18n/nl_NL.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/no_NO.yaml b/i18n/no_NO.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/no_NO.yaml +++ b/i18n/no_NO.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/pl_PL.yaml b/i18n/pl_PL.yaml index edcf60c4..d43b1a6b 100644 --- a/i18n/pl_PL.yaml +++ b/i18n/pl_PL.yaml @@ -1249,7 +1249,7 @@ ui: answers: Odpowiedzi newest: Najnowsze active: Aktywne - frequent: Częste + hot: Hot score: Ocena unanswered: Bez odpowiedzi modified: zmodyfikowane diff --git a/i18n/pt_BR.yaml b/i18n/pt_BR.yaml index 11b8920c..4210d5bd 100644 --- a/i18n/pt_BR.yaml +++ b/i18n/pt_BR.yaml @@ -855,7 +855,7 @@ ui: answers: Respostas newest: Mais recente active: Ativo - frequent: Frequente + hot: Hot score: Pontuação unanswered: Não Respondido modified: modificado diff --git a/i18n/pt_PT.yaml b/i18n/pt_PT.yaml index a7f3fedd..b825f6e9 100644 --- a/i18n/pt_PT.yaml +++ b/i18n/pt_PT.yaml @@ -1249,7 +1249,7 @@ ui: answers: Respostas newest: Mais recente active: Ativo - frequent: Frequente + hot: Hot score: Pontuação unanswered: Não Respondido modified: modificado diff --git a/i18n/ro_RO.yaml b/i18n/ro_RO.yaml index 20599ec5..db6ccbbd 100644 --- a/i18n/ro_RO.yaml +++ b/i18n/ro_RO.yaml @@ -1249,7 +1249,7 @@ ui: answers: Răspunsuri newest: Cele mai noi active: Activ - frequent: Frecvent + hot: Hot score: Scor unanswered: Fără răspuns modified: modificat diff --git a/i18n/ru_RU.yaml b/i18n/ru_RU.yaml index d9d01648..d9f03407 100644 --- a/i18n/ru_RU.yaml +++ b/i18n/ru_RU.yaml @@ -1249,7 +1249,7 @@ ui: answers: Ответы newest: Последние active: Активные - frequent: Популярные + hot: Hot score: Оценка unanswered: Без ответа modified: изменён diff --git a/i18n/sk_SK.yaml b/i18n/sk_SK.yaml index 3b4731d2..ffe0f7f6 100644 --- a/i18n/sk_SK.yaml +++ b/i18n/sk_SK.yaml @@ -1249,7 +1249,7 @@ ui: answers: Odpovede newest: Najnovšie active: Aktívne - frequent: Časté + hot: Hot score: Skóre unanswered: Nezodpovedané modified: upravené diff --git a/i18n/sq_AL.yaml b/i18n/sq_AL.yaml index 2252bdcd..a667823b 100644 --- a/i18n/sq_AL.yaml +++ b/i18n/sq_AL.yaml @@ -850,7 +850,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/sr_SP.yaml b/i18n/sr_SP.yaml index a6c48ffa..c91f56b0 100644 --- a/i18n/sr_SP.yaml +++ b/i18n/sr_SP.yaml @@ -858,7 +858,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/sv_SE.yaml b/i18n/sv_SE.yaml index 99c3494b..a0f992c5 100644 --- a/i18n/sv_SE.yaml +++ b/i18n/sv_SE.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/te_IN.yaml b/i18n/te_IN.yaml index 650cbfc1..e0a42ddd 100644 --- a/i18n/te_IN.yaml +++ b/i18n/te_IN.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/tr_TR.yaml b/i18n/tr_TR.yaml index d3d0d959..f7ba5a89 100644 --- a/i18n/tr_TR.yaml +++ b/i18n/tr_TR.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/uk_UA.yaml b/i18n/uk_UA.yaml index ef15bc12..4634d2cd 100644 --- a/i18n/uk_UA.yaml +++ b/i18n/uk_UA.yaml @@ -1249,7 +1249,7 @@ ui: answers: Відповіді newest: Найновіші active: Активні - frequent: Frequent + hot: Hot score: Оцінка unanswered: Без відповідей modified: modified diff --git a/i18n/vi_VN.yaml b/i18n/vi_VN.yaml index 1a286506..1e883778 100644 --- a/i18n/vi_VN.yaml +++ b/i18n/vi_VN.yaml @@ -1249,7 +1249,7 @@ ui: answers: Answers newest: Newest active: Active - frequent: Frequent + hot: Hot score: Score unanswered: Unanswered modified: modified diff --git a/i18n/zh_TW.yaml b/i18n/zh_TW.yaml index 364f8c02..1f2db470 100644 --- a/i18n/zh_TW.yaml +++ b/i18n/zh_TW.yaml @@ -1249,7 +1249,7 @@ ui: answers: 回答 newest: 最新的 active: 活躍的 - frequent: 瀏覽量 + hot: 熱門 score: 評分 unanswered: 未回答 modified: 修改於 diff --git a/internal/base/cron/cron.go b/internal/base/cron/cron.go index b7b05c26..0d08e50f 100644 --- a/internal/base/cron/cron.go +++ b/internal/base/cron/cron.go @@ -59,5 +59,15 @@ func (s *ScheduledTaskManager) Run() { if err != nil { log.Error(err) } + + _, err = c.AddFunc("0 */1 * * *", func() { + ctx := context.Background() + fmt.Println("refresh hottest cron execution") + s.questionService.RefreshHottestCron(ctx) + }) + if err != nil { + log.Error(err) + } + c.Start() } diff --git a/internal/entity/question_entity.go b/internal/entity/question_entity.go index 280cc670..1931282c 100644 --- a/internal/entity/question_entity.go +++ b/internal/entity/question_entity.go @@ -66,6 +66,7 @@ type Question struct { UniqueViewCount int `xorm:"not null default 0 INT(11) unique_view_count"` VoteCount int `xorm:"not null default 0 INT(11) vote_count"` AnswerCount int `xorm:"not null default 0 INT(11) answer_count"` + HotScore int `xorm:"not null default 0 INT(11) hot_score"` CollectionCount int `xorm:"not null default 0 INT(11) collection_count"` FollowCount int `xorm:"not null default 0 INT(11) follow_count"` AcceptedAnswerID string `xorm:"not null default 0 BIGINT(20) accepted_answer_id"` diff --git a/internal/repo/answer/answer_repo.go b/internal/repo/answer/answer_repo.go index 3edbec34..79dac140 100644 --- a/internal/repo/answer/answer_repo.go +++ b/internal/repo/answer/answer_repo.go @@ -430,6 +430,17 @@ func (ar *answerRepo) AdminSearchList(ctx context.Context, req *schema.AdminAnsw return resp, total, nil } +// SumVotesByQuestionID sum votes by question id +func (ar *answerRepo) SumVotesByQuestionID(ctx context.Context, questionID string) (float64, error) { + questionID = uid.DeShortID(questionID) + var resp entity.Answer + count, err := ar.data.DB.Context(ctx).Where("question_id = ? and status = ?", questionID, entity.AnswerStatusAvailable).Sum(&resp, "vote_count") + if err != nil { + return count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } + return count, nil +} + // updateSearch update search, if search plugin not enable, do nothing func (ar *answerRepo) updateSearch(ctx context.Context, answerID string) (err error) { answerID = uid.DeShortID(answerID) diff --git a/internal/repo/question/question_repo.go b/internal/repo/question/question_repo.go index 4dcfc8f8..5a683af7 100644 --- a/internal/repo/question/question_repo.go +++ b/internal/repo/question/question_repo.go @@ -380,8 +380,8 @@ func (qr *questionRepo) GetQuestionPage(ctx context.Context, page, pageSize int, } session.And("question.post_update_time > ?", time.Now().AddDate(0, 0, -90)) session.OrderBy("question.pin desc,question.post_update_time DESC, question.updated_at DESC") - case "frequent": - session.OrderBy("question.pin desc,question.view_count DESC") + case "hot": + session.OrderBy("question.pin desc,question.hot_score DESC") case "score": session.OrderBy("question.pin desc,question.vote_count DESC, question.view_count DESC") case "unanswered": diff --git a/internal/schema/question_schema.go b/internal/schema/question_schema.go index f915d5ea..a4c6ee8c 100644 --- a/internal/schema/question_schema.go +++ b/internal/schema/question_schema.go @@ -343,16 +343,19 @@ type UserQuestionInfo struct { const ( QuestionOrderCondNewest = "newest" QuestionOrderCondActive = "active" - QuestionOrderCondFrequent = "frequent" + QuestionOrderCondHot = "hot" QuestionOrderCondScore = "score" QuestionOrderCondUnanswered = "unanswered" + + // HotInDays limit max days of the hottest question + HotInDays = 90 ) // QuestionPageReq query questions page type QuestionPageReq struct { Page int `validate:"omitempty,min=1" form:"page"` PageSize int `validate:"omitempty,min=1" form:"page_size"` - OrderCond string `validate:"omitempty,oneof=newest active frequent score unanswered" form:"order"` + OrderCond string `validate:"omitempty,oneof=newest active hot score unanswered" form:"order"` Tag string `validate:"omitempty,gt=0,lte=100" form:"tag"` Username string `validate:"omitempty,gt=0,lte=100" form:"username"` InDays int `validate:"omitempty,min=1" form:"in_days"` @@ -475,7 +478,7 @@ type AdminUpdateQuestionStatusReq struct { type PersonalQuestionPageReq struct { Page int `validate:"omitempty,min=1" form:"page"` PageSize int `validate:"omitempty,min=1" form:"page_size"` - OrderCond string `validate:"omitempty,oneof=newest active frequent score unanswered" form:"order"` + OrderCond string `validate:"omitempty,oneof=newest active hot score unanswered" form:"order"` Username string `validate:"omitempty,gt=0,lte=100" form:"username"` LoginUserID string `json:"-"` IsAdmin bool `json:"-"` @@ -484,7 +487,7 @@ type PersonalQuestionPageReq struct { type PersonalAnswerPageReq struct { Page int `validate:"omitempty,min=1" form:"page"` PageSize int `validate:"omitempty,min=1" form:"page_size"` - OrderCond string `validate:"omitempty,oneof=newest active frequent score unanswered" form:"order"` + OrderCond string `validate:"omitempty,oneof=newest active hot score unanswered" form:"order"` Username string `validate:"omitempty,gt=0,lte=100" form:"username"` LoginUserID string `json:"-"` IsAdmin bool `json:"-"` diff --git a/internal/service/answer_common/answer.go b/internal/service/answer_common/answer.go index af2be2f0..1517b22d 100644 --- a/internal/service/answer_common/answer.go +++ b/internal/service/answer_common/answer.go @@ -49,6 +49,7 @@ type AnswerRepo interface { UpdateAnswerStatus(ctx context.Context, answerID string, status int) (err error) GetAnswerCount(ctx context.Context) (count int64, err error) RemoveAllUserAnswer(ctx context.Context, userID string) (err error) + SumVotesByQuestionID(ctx context.Context, questionID string) (float64, error) } // AnswerCommon user service diff --git a/internal/service/content/question_hottest_service.go b/internal/service/content/question_hottest_service.go new file mode 100644 index 00000000..6a37d3b3 --- /dev/null +++ b/internal/service/content/question_hottest_service.go @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package content + +import ( + "context" + "github.com/apache/incubator-answer/internal/entity" + "github.com/apache/incubator-answer/internal/schema" + "github.com/segmentfault/pacman/log" + "math" + "time" +) + +func (q *QuestionService) RefreshHottestCron(ctx context.Context) { + + var ( + page = 1 + pageSize = 100 + ) + + for { + questionList, _, err := q.questionRepo.GetQuestionPage( + ctx, + page, pageSize, + []string{}, + "", "newest", + schema.HotInDays, + false, false) + if err != nil { + return + } + + for _, question := range questionList { + updatedAt := question.UpdatedAt.Unix() + if updatedAt < 0 { + updatedAt = question.CreatedAt.Unix() + } + + qAgeInHours := (time.Now().Unix() - question.CreatedAt.Unix()) / 3600 + qUpdated := (time.Now().Unix() - updatedAt) / 3600 + + aScores, err := q.answerRepo.SumVotesByQuestionID(ctx, question.ID) + if err != nil { + aScores = 0 + } + + score := q.getScore(float64(question.ViewCount), float64(question.AnswerCount), float64(question.VoteCount), aScores, float64(qAgeInHours), float64(qUpdated)) + if score < 0 { + score = 0 + } + + questioninfo := &entity.Question{} + questioninfo.ID = question.ID + questioninfo.HotScore = int(math.Ceil(score * 10000)) + err = q.questionRepo.UpdateQuestion(ctx, questioninfo, []string{"hot_score"}) + if err != nil { + log.Error("update question hot score error,question ID:", question.ID, " error: ", err) + } + } + + if len(questionList) < pageSize { + break + } + page++ + } +} + +func (q *QuestionService) getScore(qViews, qAnswers, qScore, aScores, qAgeInHours, qUpdated float64) (score float64) { + score = ((math.Log(qViews) * 4) + ((qAnswers * qScore) / 5) + aScores) / + math.Pow(((qAgeInHours+1)-((qAgeInHours-qUpdated)/2)), 1.5) + return score +} diff --git a/internal/service/content/question_service.go b/internal/service/content/question_service.go index e11a608b..6d8b37ba 100644 --- a/internal/service/content/question_service.go +++ b/internal/service/content/question_service.go @@ -22,6 +22,7 @@ package content import ( "encoding/json" "fmt" + answercommon "github.com/apache/incubator-answer/internal/service/answer_common" "strings" "time" @@ -65,6 +66,7 @@ import ( // QuestionService user service type QuestionService struct { questionRepo questioncommon.QuestionRepo + answerRepo answercommon.AnswerRepo tagCommon *tagcommon.TagCommonService questioncommon *questioncommon.QuestionCommon userCommon *usercommon.UserCommon @@ -86,6 +88,7 @@ type QuestionService struct { func NewQuestionService( questionRepo questioncommon.QuestionRepo, + answerRepo answercommon.AnswerRepo, tagCommon *tagcommon.TagCommonService, questioncommon *questioncommon.QuestionCommon, userCommon *usercommon.UserCommon, @@ -106,6 +109,7 @@ func NewQuestionService( ) *QuestionService { return &QuestionService{ questionRepo: questionRepo, + answerRepo: answerRepo, tagCommon: tagCommon, questioncommon: questioncommon, userCommon: userCommon, @@ -1264,7 +1268,7 @@ func (qs *QuestionService) SimilarQuestion(ctx context.Context, questionID strin tagNames = append(tagNames, tag.SlugName) } search := &schema.QuestionPageReq{} - search.OrderCond = "frequent" + search.OrderCond = "hot" search.Page = 0 search.PageSize = 6 if len(tagNames) > 0 { @@ -1328,6 +1332,10 @@ func (qs *QuestionService) GetQuestionPage(ctx context.Context, req *schema.Ques req.UserIDBeSearched = userinfo.ID } + if req.OrderCond == schema.QuestionOrderCondHot { + req.InDays = schema.HotInDays + } + questionList, total, err := qs.questionRepo.GetQuestionPage(ctx, req.Page, req.PageSize, tagIDs, req.UserIDBeSearched, req.OrderCond, req.InDays, showHidden, req.ShowPending) if err != nil {
