feat: SEO backend output (2/4)
This commit is contained in:
1 parent
0eb46b0d74
commit
eb9876fde3
32 files changed
+3859
-65
No files matched your search
@@ -6,6 +6,7 @@ import (
|
||||
"RenewCMS/internal/infrastructure/persistence/mappers"
|
||||
entity "RenewCMS/internal/infrastructure/persistence/models"
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"strings"
|
||||
"unicode"
|
||||
@@ -59,6 +60,7 @@ var sortColumns = map[domain.SortField]string{
|
||||
domain.SortByStatus: "is_online",
|
||||
domain.SortByCreatedAt: "created_at",
|
||||
domain.SortByUpdatedAt: "updated_at",
|
||||
domain.SortByID: "id",
|
||||
}
|
||||
|
||||
var sortDirections = map[domain.SortDirection]string{
|
||||
@@ -72,6 +74,9 @@ func orderClause(sort domain.Sort) string {
|
||||
if !ok || !directionOk {
|
||||
column, direction = sortColumns[domain.SortByUpdatedAt], sortDirections[domain.SortDesc]
|
||||
}
|
||||
if sort.Field == domain.SortByID {
|
||||
return column + " " + direction
|
||||
}
|
||||
return column + " " + direction + ", id DESC"
|
||||
}
|
||||
|
||||
@@ -87,7 +92,11 @@ func (a *ArticleRepository) FindPage(filters domain.Filters) (domain.PageResult,
|
||||
return domain.PageResult{}, err
|
||||
}
|
||||
var entityArticles []entity.Article
|
||||
err := a.scoped(filters).Order(orderClause(filters.Sort)).Limit(filters.Size).Offset((filters.Page - 1) * filters.Size).Find(&entityArticles).Error
|
||||
ordered := a.scoped(filters).Order(orderClause(filters.Sort))
|
||||
if !filters.Unpaged {
|
||||
ordered = ordered.Limit(filters.Size).Offset((filters.Page - 1) * filters.Size)
|
||||
}
|
||||
err := ordered.Find(&entityArticles).Error
|
||||
if err != nil {
|
||||
return domain.PageResult{}, err
|
||||
}
|
||||
@@ -110,16 +119,23 @@ func (a *ArticleRepository) findMatchingTitle(filters domain.Filters) (domain.Pa
|
||||
matchingIds = append(matchingIds, candidate.ID)
|
||||
}
|
||||
}
|
||||
start := min((filters.Page-1)*filters.Size, len(matchingIds))
|
||||
end := min(start+filters.Size, len(matchingIds))
|
||||
pageIds := matchingIds[start:end]
|
||||
pageIds := matchingIds
|
||||
if !filters.Unpaged {
|
||||
start := min((filters.Page-1)*filters.Size, len(matchingIds))
|
||||
end := min(start+filters.Size, len(matchingIds))
|
||||
pageIds = matchingIds[start:end]
|
||||
}
|
||||
page := domain.PageResult{Items: []domain.Article{}, Total: len(matchingIds)}
|
||||
if len(pageIds) == 0 {
|
||||
return page, nil
|
||||
}
|
||||
var entityArticles []entity.Article
|
||||
if err := a.db.Model(&entity.Article{}).Where("id IN ?", pageIds).Find(&entityArticles).Error; err != nil {
|
||||
return domain.PageResult{}, err
|
||||
for _, chunk := range chunkIDs(pageIds) {
|
||||
var loaded []entity.Article
|
||||
if err := a.db.Model(&entity.Article{}).Where("id IN ?", chunk).Find(&loaded).Error; err != nil {
|
||||
return domain.PageResult{}, err
|
||||
}
|
||||
entityArticles = append(entityArticles, loaded...)
|
||||
}
|
||||
byId := make(map[uint32]entity.Article, len(entityArticles))
|
||||
for _, entityArticle := range entityArticles {
|
||||
@@ -186,15 +202,35 @@ func (a *ArticleRepository) withAuthorsOne(db *gorm.DB, article domain.Article)
|
||||
return loaded[0], nil
|
||||
}
|
||||
|
||||
const idChunkSize = 500
|
||||
|
||||
func chunkIDs(ids []uint32) [][]uint32 {
|
||||
chunks := make([][]uint32, 0, len(ids)/idChunkSize+1)
|
||||
for start := 0; start < len(ids); start += idChunkSize {
|
||||
chunks = append(chunks, ids[start:min(start+idChunkSize, len(ids))])
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
func loadBylines(db *gorm.DB, articleIDs []uint32) (map[uint32][]authordomain.Byline, error) {
|
||||
bylines := make(map[uint32][]authordomain.Byline, len(articleIDs))
|
||||
if len(articleIDs) == 0 {
|
||||
return bylines, nil
|
||||
}
|
||||
var credits []entity.ArticleAuthor
|
||||
if err := db.Where("article_id IN ?", articleIDs).Order("position ASC, id ASC").Find(&credits).Error; err != nil {
|
||||
return nil, err
|
||||
for _, chunk := range chunkIDs(articleIDs) {
|
||||
var loaded []entity.ArticleAuthor
|
||||
if err := db.Where("article_id IN ?", chunk).Order("position ASC, id ASC").Find(&loaded).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credits = append(credits, loaded...)
|
||||
}
|
||||
sort.SliceStable(credits, func(i, j int) bool {
|
||||
if credits[i].Position != credits[j].Position {
|
||||
return credits[i].Position < credits[j].Position
|
||||
}
|
||||
return credits[i].ID < credits[j].ID
|
||||
})
|
||||
if len(credits) == 0 {
|
||||
return bylines, nil
|
||||
}
|
||||
@@ -203,8 +239,12 @@ func loadBylines(db *gorm.DB, articleIDs []uint32) (map[uint32][]authordomain.By
|
||||
authorIDs = append(authorIDs, credit.AuthorID)
|
||||
}
|
||||
var found []entity.Author
|
||||
if err := db.Where("id IN ?", authorIDs).Find(&found).Error; err != nil {
|
||||
return nil, err
|
||||
for _, chunk := range chunkIDs(authorIDs) {
|
||||
var loaded []entity.Author
|
||||
if err := db.Where("id IN ?", chunk).Find(&loaded).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
found = append(found, loaded...)
|
||||
}
|
||||
byID := make(map[uint32]entity.Author, len(found))
|
||||
for _, model := range found {
|
||||
|
||||
Reference in new issue
Block a user