recommend.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package model
  2. import (
  3. "math"
  4. "trading-go/common"
  5. )
  6. type vector struct {
  7. v []Pair
  8. }
  9. type recommendList struct {
  10. list map[uint]float64
  11. }
  12. type Pair struct {
  13. CategoryId uint `db:"category_id"`
  14. Score int `db:"score"`
  15. }
  16. func Recommend(uid, goodsId uint) error {
  17. db := common.DB
  18. var cIds []int64
  19. sqlStr := "SELECT category_id FROM category_of_goods WHERE goods_id = ?"
  20. err := db.Select(&cIds, sqlStr, goodsId)
  21. if err != nil {
  22. return err
  23. }
  24. sqlStr = "INSERT INTO feedback(uid, category_id, score) VALUE (?, ?, 1) ON DUPLICATE KEY update score=score + 1"
  25. for _, id := range cIds {
  26. _, err := db.Exec(sqlStr, uid, id)
  27. if err != nil {
  28. return err
  29. }
  30. }
  31. return nil
  32. }
  33. func NewRecommend(uid uint, categoryId []uint) error {
  34. db := common.DB
  35. sqlStr := "INSERT INTO feedback(uid, category_id, score) VALUE (?, ?, 1) ON DUPLICATE KEY update score=score + 1"
  36. for _, id := range categoryId {
  37. _, err := db.Exec(sqlStr, uid, id)
  38. if err != nil {
  39. return err
  40. }
  41. }
  42. return nil
  43. }
  44. func GetRecommend(uid uint, cnt int) (goods []uint, err error) {
  45. var rList recommendList
  46. rList.list = make(map[uint]float64)
  47. userV, err := getUserVector(uid)
  48. if err != nil {
  49. return nil, err
  50. }
  51. mx := userV.max()
  52. goodsIds, err := getGoodsIds()
  53. if err != nil {
  54. return nil, err
  55. }
  56. for _, id := range goodsIds {
  57. itemV, err := getItemVector(id, uint(mx))
  58. if err != nil {
  59. return nil, err
  60. }
  61. rList.list[id] = userV.similarity(itemV)
  62. }
  63. goods = rList.Sort(cnt)
  64. return
  65. }
  66. func getUserVector(uid uint) (vector, error) {
  67. var p []Pair
  68. db := common.DB
  69. sqlStr := "SELECT category_id, score FROM feedback WHERE uid = ? ORDER BY category_id DESC"
  70. err := db.Select(&p, sqlStr, uid)
  71. if err != nil {
  72. return vector{}, err
  73. }
  74. return vector{v: p}, err
  75. }
  76. func getItemVector(id uint, maxId uint) (vector, error) {
  77. var p []Pair
  78. var cIds []uint
  79. db := common.DB
  80. sqlStr := "SELECT category_id FROM category_of_goods WHERE goods_id = ? AND category_id <= ?"
  81. err := db.Select(&cIds, sqlStr, id, maxId)
  82. if err != nil {
  83. return vector{}, err
  84. }
  85. for i := 0; i < len(cIds); i++ {
  86. p = append(p, Pair{
  87. CategoryId: cIds[i],
  88. Score: 1,
  89. })
  90. }
  91. return vector{p}, err
  92. }
  93. func (v vector) similarity(other vector) float64 {
  94. user, item := make(map[uint]int), make(map[uint]int)
  95. for _, pair := range v.v {
  96. user[pair.CategoryId] = pair.Score
  97. }
  98. for _, pair := range other.v {
  99. item[pair.CategoryId] = 1
  100. }
  101. a, b, cnt := 0, 0, 0
  102. for ke, va := range user {
  103. if _, ok := item[ke]; ok {
  104. cnt++
  105. a += va
  106. }
  107. b += va * va
  108. }
  109. if cnt == 0 {
  110. return 0
  111. }
  112. return float64(a) / (math.Sqrt(float64(b)) * math.Sqrt(float64(cnt)))
  113. }
  114. func (v vector) max() uint {
  115. return v.v[0].CategoryId
  116. }
  117. func (r recommendList) Sort(n int) []uint {
  118. ids := make([]uint, 0, len(r.list))
  119. scores := make([]float64, 0, len(r.list))
  120. result := make([]uint, 0, n)
  121. for id, score := range r.list {
  122. ids = append(ids, id)
  123. scores = append(scores, score)
  124. }
  125. for i := 0; i < n; i++ {
  126. mxid := uint(i)
  127. for j := 0; j < len(ids); j++ {
  128. if scores[j] > scores[mxid] {
  129. mxid = uint(j)
  130. }
  131. }
  132. scores[mxid] = -1
  133. result = append(result, ids[mxid])
  134. }
  135. return result
  136. }