Skip to content

Commit

Permalink
feat(question): add linked count feature to question
Browse files Browse the repository at this point in the history
  • Loading branch information
LinkinStars committed Nov 19, 2024
1 parent c39fd89 commit 5cbd190
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 2 deletions.
1 change: 1 addition & 0 deletions internal/entity/question_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type Question struct {
LastAnswerID string `xorm:"not null default 0 BIGINT(20) last_answer_id"`
PostUpdateTime time.Time `xorm:"post_update_time TIMESTAMP"`
RevisionID string `xorm:"not null default 0 BIGINT(20) revision_id"`
LinkedCount int `xorm:"not null default 0 INT(11) linked_count"`
}

// TableName question table name
Expand Down
1 change: 1 addition & 0 deletions internal/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ var migrations = []Migration{
NewMigration("v1.3.6", "add hot score to question table", addQuestionHotScore, true),
NewMigration("v1.4.0", "add badge/badge_group/badge_award table", addBadges, true),
NewMigration("v1.4.1", "add question link", addQuestionLink, true),
NewMigration("v1.4.2", "add the number of question links", addQuestionLinkedCount, false),
}

func GetMigrations() []Migration {
Expand Down
34 changes: 34 additions & 0 deletions internal/migrations/v24.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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 migrations

import (
"context"
"github.com/apache/incubator-answer/internal/entity"

"xorm.io/xorm"
)

func addQuestionLinkedCount(ctx context.Context, x *xorm.Engine) error {
type Question struct {
LinkedCount int `xorm:"not null default 0 INT(11) linked_count"`
}
return x.Context(ctx).Sync(new(entity.Question))
}
40 changes: 40 additions & 0 deletions internal/repo/question/question_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,8 @@ func (qr *questionRepo) GetQuestionPage(ctx context.Context, page, pageSize int,
case "unanswered":
session.Where("question.answer_count = 0")
session.OrderBy("question.pin desc,question.created_at DESC")
case "frequent":
session.OrderBy("question.pin DESC, question.linked_count DESC")
}

total, err = pager.Help(page, pageSize, &questionList, &entity.Question{}, session)
Expand Down Expand Up @@ -708,6 +710,42 @@ func (qr *questionRepo) LinkQuestion(ctx context.Context, link ...*entity.Questi
return
}

// UpdateQuestionLinkCount update question link count
func (qr *questionRepo) UpdateQuestionLinkCount(ctx context.Context, questionID string) (err error) {
// count the number of links
count, err := qr.data.DB.Context(ctx).
Where("to_question_id = ?", questionID).
Where("status = ?", entity.QuestionLinkStatusAvailable).
Count(&entity.QuestionLink{})
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}

// update the number of links
_, err = qr.data.DB.Context(ctx).ID(questionID).
Cols("linked_count").Update(&entity.Question{LinkedCount: int(count)})
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}

// GetLinkedQuestionIDs get linked question ids
func (qr *questionRepo) GetLinkedQuestionIDs(ctx context.Context, questionID string, status int) (
questionIDs []string, err error) {
questionIDs = make([]string, 0)
err = qr.data.DB.Context(ctx).
Select("to_question_id").
Table(new(entity.QuestionLink).TableName()).
Where("from_question_id = ?", questionID).
Where("status = ?", status).
Find(&questionIDs)
if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return questionIDs, nil
}

// RecoverQuestionLink batch recover question link
func (qr *questionRepo) RecoverQuestionLink(ctx context.Context, links ...*entity.QuestionLink) (err error) {
return qr.UpdateQuestionLinkStatus(ctx, entity.QuestionLinkStatusAvailable, links...)
Expand Down Expand Up @@ -784,6 +822,8 @@ func (qr *questionRepo) GetQuestionLink(ctx context.Context, page, pageSize int,
case "unanswered":
session.Where("question.answer_count = 0")
session.OrderBy("question.pin desc,question.created_at DESC")
case "frequent":
session.OrderBy("question.pin DESC, question.linked_count DESC")
}

if page > 0 && pageSize > 0 {
Expand Down
4 changes: 2 additions & 2 deletions internal/schema/question_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ const (
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 hot score unanswered recommend" form:"order"`
OrderCond string `validate:"omitempty,oneof=newest active hot score unanswered recommend frequent" 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"`
Expand Down Expand Up @@ -504,7 +504,7 @@ type GetQuestionLinkReq struct {
Page int `validate:"omitempty,min=1" form:"page"`
PageSize int `validate:"omitempty,min=1,max=100" form:"page_size"`
QuestionID string `validate:"required" form:"question_id"`
OrderCond string `validate:"omitempty,oneof=newest active hot score unanswered recommend" form:"order"`
OrderCond string `validate:"omitempty,oneof=newest active hot score unanswered recommend frequent" form:"order"`
InDays int `validate:"omitempty,min=1" form:"in_days"`

LoginUserID string `json:"-"`
Expand Down
23 changes: 23 additions & 0 deletions internal/service/question_common/question.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ type QuestionRepo interface {
RemoveAllUserQuestion(ctx context.Context, userID string) (err error)
UpdateSearch(ctx context.Context, questionID string) (err error)
LinkQuestion(ctx context.Context, link ...*entity.QuestionLink) (err error)
GetLinkedQuestionIDs(ctx context.Context, questionID string, status int) (questionIDs []string, err error)
UpdateQuestionLinkCount(ctx context.Context, questionID string) (err error)
RemoveQuestionLink(ctx context.Context, link ...*entity.QuestionLink) (err error)
RecoverQuestionLink(ctx context.Context, link ...*entity.QuestionLink) (err error)
UpdateQuestionLinkStatus(ctx context.Context, status int, links ...*entity.QuestionLink) (err error)
Expand Down Expand Up @@ -704,6 +706,17 @@ func (qs *QuestionCommon) UpdateQuestionLink(ctx context.Context, questionID, an
if err != nil {
return parsedText, err
}
// Update the number of question links that have been removed
linkedQuestionIDs, err := qs.questionRepo.GetLinkedQuestionIDs(ctx, questionID, entity.QuestionLinkStatusDeleted)
if err != nil {
log.Errorf("get linked question ids error %v", err)
} else {
for _, id := range linkedQuestionIDs {
if err := qs.questionRepo.UpdateQuestionLinkCount(ctx, id); err != nil {
log.Errorf("update question link count error %v", err)
}
}
}

links := checker.GetQuestionLink(originalText)
if len(links) == 0 {
Expand Down Expand Up @@ -799,6 +812,16 @@ func (qs *QuestionCommon) UpdateQuestionLink(ctx context.Context, questionID, an
}
}

// update question linked count
for _, link := range validLinks {
if len(link.ToQuestionID) == 0 {
continue
}
if err := qs.questionRepo.UpdateQuestionLinkCount(ctx, link.ToQuestionID); err != nil {
log.Errorf("update question link count error %v", err)
}
}

return parsedText, nil
}

Expand Down

0 comments on commit 5cbd190

Please sign in to comment.