sort.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package service
  2. import (
  3. "context"
  4. "sort"
  5. "time"
  6. artmdl "go-common/app/interface/openplatform/article/model"
  7. "go-common/app/job/openplatform/article/dao"
  8. "go-common/app/job/openplatform/article/model"
  9. "go-common/library/log"
  10. )
  11. var (
  12. _recommendCategory = int64(0)
  13. )
  14. // UpdateSort update sort
  15. func (s *Service) UpdateSort(c context.Context) (err error) {
  16. ids := []int64{_recommendCategory}
  17. for id := range s.categoriesMap {
  18. ids = append(ids, id)
  19. }
  20. var (
  21. cache bool
  22. allArts map[int64]map[int][][2]int64
  23. )
  24. for _, categoryID := range ids {
  25. for _, field := range artmdl.SortFields {
  26. if (categoryID == _recommendCategory) && (field != artmdl.FieldNew) {
  27. continue
  28. }
  29. if cache, err = s.dao.ExpireSortCache(c, categoryID, field); err != nil {
  30. dao.PromError("recommends:更新文章排序")
  31. return
  32. }
  33. // cache不存在才更新
  34. if cache {
  35. continue
  36. }
  37. dao.PromInfo("sort:初始化排序缓存")
  38. if allArts == nil {
  39. allArts, _ = s.loadSortArts(context.TODO())
  40. }
  41. if field == artmdl.FieldNew {
  42. s.updateNewArts(c, categoryID)
  43. } else {
  44. s.updateStatSort(c, allArts, categoryID, field)
  45. }
  46. }
  47. }
  48. return
  49. }
  50. func (s *Service) updateNewArts(c context.Context, categoryID int64) (err error) {
  51. var arts [][2]int64
  52. if categoryID == _recommendCategory {
  53. if arts, err = s.dao.NewestArtIDs(c, s.c.Job.MaxNewArtsNum); err == nil {
  54. log.Info("s.updateNewArts() len: %v", len(arts))
  55. // 不异步
  56. err = s.dao.AddSortCaches(c, _recommendCategory, artmdl.FieldNew, arts, s.c.Job.MaxNewArtsNum)
  57. }
  58. return
  59. }
  60. ids := []int64{}
  61. cs := s.categoriesReverseMap[categoryID]
  62. if len(cs) == 0 {
  63. // 二级分区
  64. ids = append(ids, categoryID)
  65. } else {
  66. // 一级分区聚合子分区
  67. for _, s := range cs {
  68. ids = append(ids, s.ID)
  69. }
  70. }
  71. if arts, err = s.dao.NewestArtIDByCategory(c, ids, s.c.Job.MaxNewArtsNum); err == nil {
  72. // 不异步
  73. err = s.dao.AddSortCaches(c, categoryID, artmdl.FieldNew, arts, s.c.Job.MaxNewArtsNum)
  74. }
  75. return
  76. }
  77. func (s *Service) updateStatSort(c context.Context, allArts map[int64]map[int][][2]int64, categoryID int64, field int) (err error) {
  78. if allArts == nil {
  79. return
  80. }
  81. if categoryID == _recommendCategory {
  82. //推荐下没有排序
  83. return
  84. }
  85. arts := trimArts(allArts[categoryID][field], int(s.c.Job.MaxSortArtsNum))
  86. err = s.dao.AddSortCaches(c, categoryID, field, arts, s.c.Job.MaxSortArtsNum)
  87. return
  88. }
  89. func trimArts(arts [][2]int64, max int) (res [][2]int64) {
  90. sort.Slice(arts, func(i, j int) bool {
  91. return arts[i][1] > arts[j][1]
  92. })
  93. if len(arts) > max {
  94. return arts[:max]
  95. }
  96. return arts
  97. }
  98. func (s *Service) loadSortArts(c context.Context) (res map[int64]map[int][][2]int64, err error) {
  99. // init category and field
  100. res = make(map[int64]map[int][][2]int64)
  101. for id := range s.categoriesMap {
  102. res[id] = make(map[int][][2]int64)
  103. }
  104. var (
  105. arts []*model.SearchArticle
  106. limitTime = time.Now().Unix() - s.sortLimitTime
  107. )
  108. if arts, err = s.dao.SearchArts(c, limitTime); err != nil {
  109. dao.PromError("sort:初始化排序计数失败")
  110. return
  111. }
  112. for _, art := range arts {
  113. if artmdl.NoDistributeAttr(art.Attributes) || artmdl.NoRegionAttr(art.Attributes) {
  114. continue
  115. }
  116. if res[art.CategoryID] == nil {
  117. res[art.CategoryID] = make(map[int][][2]int64)
  118. }
  119. res[art.CategoryID][artmdl.FieldFav] = append(res[art.CategoryID][artmdl.FieldFav], [2]int64{art.ID, art.StatsFavorite})
  120. res[art.CategoryID][artmdl.FieldLike] = append(res[art.CategoryID][artmdl.FieldLike], [2]int64{art.ID, art.StatsLikes})
  121. res[art.CategoryID][artmdl.FieldReply] = append(res[art.CategoryID][artmdl.FieldReply], [2]int64{art.ID, art.StatsReply})
  122. res[art.CategoryID][artmdl.FieldView] = append(res[art.CategoryID][artmdl.FieldView], [2]int64{art.ID, art.StatsView})
  123. var parentID int64
  124. if id, ok := s.categoriesMap[art.CategoryID]; ok {
  125. parentID = id.ParentID
  126. } else {
  127. continue
  128. }
  129. if res[parentID] == nil {
  130. res[parentID] = make(map[int][][2]int64)
  131. }
  132. res[parentID][artmdl.FieldFav] = append(res[parentID][artmdl.FieldFav], [2]int64{art.ID, art.StatsFavorite})
  133. res[parentID][artmdl.FieldLike] = append(res[parentID][artmdl.FieldLike], [2]int64{art.ID, art.StatsLikes})
  134. res[parentID][artmdl.FieldReply] = append(res[parentID][artmdl.FieldReply], [2]int64{art.ID, art.StatsReply})
  135. res[parentID][artmdl.FieldView] = append(res[parentID][artmdl.FieldView], [2]int64{art.ID, art.StatsView})
  136. }
  137. return
  138. }
  139. func (s *Service) loadCategoriesproc() {
  140. for {
  141. time.Sleep(time.Minute * 10)
  142. s.loadCategories()
  143. }
  144. }
  145. func (s *Service) loadCategories() {
  146. for {
  147. c, err := s.articleRPC.CategoriesMap(context.TODO(), &artmdl.ArgIP{})
  148. if err != nil || len(c) == 0 {
  149. dao.PromError("service:获取分类")
  150. log.Error("s.articleRPC.CategoriesMap err %v", err)
  151. time.Sleep(time.Second)
  152. continue
  153. }
  154. s.categoriesMap = c
  155. s.categoriesReverseMap = transformReverseCategory(c)
  156. return
  157. }
  158. }
  159. // 生成某个分类下的所有子分类
  160. func transformReverseCategory(cs map[int64]*artmdl.Category) (res map[int64][]*artmdl.Category) {
  161. res = make(map[int64][]*artmdl.Category)
  162. for _, c := range cs {
  163. n := c
  164. old := c
  165. for (n != nil) && (n.ParentID != 0) {
  166. res[n.ParentID] = append(res[n.ParentID], old)
  167. n = cs[n.ParentID]
  168. }
  169. }
  170. return
  171. }