newestBidding.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package model
  2. import (
  3. "app.yhyue.com/moapp/jybase/redis"
  4. "encoding/json"
  5. "fmt"
  6. "jyBXBase/rpc/bxbase"
  7. IC "jyBXBase/rpc/init"
  8. "log"
  9. "strings"
  10. "time"
  11. MC "app.yhyue.com/moapp/jybase/common"
  12. ME "app.yhyue.com/moapp/jybase/encrypt"
  13. elastic "app.yhyue.com/moapp/jybase/es"
  14. "app.yhyue.com/moapp/jybase/mongodb"
  15. "app.yhyue.com/moapp/jybase/mysql"
  16. "github.com/zeromicro/go-zero/core/logx"
  17. "go.mongodb.org/mongo-driver/bson/primitive"
  18. )
  19. const (
  20. search_index = "bidding"
  21. search_type = "bidding"
  22. mongodb_fields = `{"_id":1,"area":1,"publishtime":1,"s_subscopeclass":1,"subtype":1,"title":1,"toptype":1,"type":1, "buyerclass":1,"budget":1,"bidamount":1,"s_winner":1,"bidopentime":1,"buyer":1,"projectname":1,"spidercode":1,"site":1}`
  23. query = `{"query":{"terms":{"_id":["%s"]}},"_source":["_id","area", "publishtime", "s_subscopeclass", "subtype", "title", "toptype", "type", "buyerclass","bidamount","budget","projectname","buyer","bidopentime","s_winner","filetext","spidercode","site"],"from":0,"size":%d}`
  24. multi_match = `{"multi_match": {"query": %s,"type": "phrase", "fields": ["title"]}}`
  25. query_bool_must = `{"terms":{"%s":[%s]}}`
  26. query_bool_must_and = `{"bool":{"must":[%s],"must_not":[%s]}}`
  27. search_field = `"_id","area", "publishtime", "s_subscopeclass", "subtype", "title", "toptype", "type", "buyerclass","bidamount","budget","projectname","buyer","bidopentime","s_winner","filetext","isValidFile","spidercode","site"`
  28. query_city_hkeys = `{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match":%d}},"highlight": {"pre_tags": ["<a>"],"post_tags": ["</a>"],"fields": {"title": {"fragment_size": 0,"number_of_fragments": 1}}},"_source":[` + search_field + `],"sort":[{"publishtime":"desc"},{"budget":"desc"}],"from":0,"size":%d}`
  29. Pushbidding = "global_common_data.dws_f_bid_baseinfo"
  30. Province = "province"
  31. StatusNoLogin = 1 // 1-未登录用户
  32. StatusLoginUser = 2 // 2-用户自己的key
  33. StatusLogin = 3 // 3-登录用户最新标讯
  34. StatusCache = 0 // 0 -不存缓存 本来查的就是缓存的数据
  35. )
  36. type NewestInfo struct {
  37. TableName string
  38. UserId string
  39. MysqlDb *mysql.Mysql
  40. NewUserId int64
  41. PushMysql *mysql.Mysql
  42. NewsLimitNum int64 // 最新标讯数量条数限制
  43. }
  44. var mysqlTables = map[string]string{
  45. "f": "push.pushsubscribe",
  46. "v": "push.pushsubscribe",
  47. "m": "push.pushmember",
  48. "e": "push.pushentniche",
  49. }
  50. func GetRoleNewestInfoService(AppId, MgoUserId string, NewUserId, AccountId, EntId, EntUserId, PositionType, PositionId int64) (roleNewestInfo *NewestInfo, flag string) {
  51. powerCheck := IC.Middleground.PowerCheckCenter.Check(AppId, MgoUserId, NewUserId, AccountId, EntId, PositionType, PositionId)
  52. if powerCheck.Member.Status > 0 {
  53. // 大会员
  54. flag = "m"
  55. if PositionType == int64(1) {
  56. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(EntUserId), "e", EntUserId)
  57. } else {
  58. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(NewUserId), "m", NewUserId)
  59. }
  60. } else if powerCheck.Entniche.Status > 0 && powerCheck.Entniche.PowerSource != 1 && powerCheck.Entniche.IsEntPower == 1 {
  61. // 商机管理
  62. flag = "e"
  63. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(EntUserId), "e", EntUserId)
  64. } else if powerCheck.Vip.Status > 0 {
  65. // 超级订阅
  66. flag = "v"
  67. if PositionType == int64(1) {
  68. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(EntUserId), "e", EntUserId)
  69. } else {
  70. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(NewUserId), "v", NewUserId)
  71. }
  72. } else {
  73. // 普通用户
  74. flag = "f"
  75. if PositionType == int64(1) {
  76. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(EntUserId), "e", EntUserId)
  77. } else {
  78. roleNewestInfo = GetNewestInfo(MC.InterfaceToStr(NewUserId), "f", NewUserId)
  79. }
  80. }
  81. return roleNewestInfo, flag
  82. }
  83. func GetNewestInfo(userId, userType string, newUserId int64) *NewestInfo {
  84. nt := &NewestInfo{
  85. UserId: userId,
  86. TableName: mysqlTables[userType],
  87. MysqlDb: IC.BaseServiceMysql,
  88. NewUserId: newUserId,
  89. NewsLimitNum: IC.C.NewsLimitNum,
  90. }
  91. return nt
  92. }
  93. // GetPushHistoryCount 缓存code 配置最新的redis code;可以感觉redis内存大小 调节redis存储;
  94. // 根据GetPushHistoryCount 返回值 作为列表缓存key中一个参数
  95. func (n *NewestInfo) GetPushHistoryCount() int64 {
  96. countKey := fmt.Sprintf("push_count_%s_%s", n.TableName, n.UserId)
  97. if b, err := redis.Exists("other", countKey); err == nil && b {
  98. return 1
  99. }
  100. countSql := "SELECT COUNT(1) FROM (SELECT 1 FROM %s WHERE userid = %d LIMIT 1) AS ph"
  101. //countSql := "select count(1) from %s a where a.userid=%d order by a.id desc"
  102. countSql = fmt.Sprintf(countSql, n.TableName, n.NewUserId)
  103. if c := n.MysqlDb.CountBySql(countSql); c > 0 {
  104. redis.Put("other", countKey, c, 60) //过期时间走配置,比最新标讯列表缓存时间 要短1/10 尽量不超过两分钟
  105. return c
  106. }
  107. return 0
  108. }
  109. func (n *NewestInfo) GetPushHistory() (res []*bxbase.NewestList) {
  110. findSQL := "select a.infoid,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.attachment_count,a.budget,a.bidamount from %s a where a.userid=%d and a.date>=%d order by a.id desc limit ?"
  111. findSQL = fmt.Sprintf(findSQL, n.TableName, n.NewUserId, time.Now().AddDate(0, 0, -7).Unix())
  112. logx.Info(n.TableName, "-------", n.NewUserId, ",findSQL:", findSQL)
  113. list := n.MysqlDb.SelectBySql(findSQL, n.NewsLimitNum)
  114. if len(*list) > 0 && list != nil {
  115. m := map[string]bool{}
  116. es_ids := []string{}
  117. infos := map[string]*bxbase.NewestList{}
  118. for _, v := range *list {
  119. infoId := MC.ObjToString(v["infoid"])
  120. if m[infoId] {
  121. continue
  122. }
  123. es_ids = append(es_ids, infoId)
  124. m[MC.ObjToString(v["infoid"])] = true
  125. //
  126. infos[infoId] = &bxbase.NewestList{
  127. Id: ME.EncodeArticleId2ByCheck(MC.ObjToString(v["infoid"])),
  128. Matchkeys: strings.Split(MC.ObjToString(v["matchkeys"]), " "),
  129. Budget: MC.Int64All(v["budget"]),
  130. Bidamount: MC.Int64All(v["bidamount"]),
  131. FileExists: MC.Int64All(v["attachment_count"]) > 0,
  132. }
  133. }
  134. if len(es_ids) > 0 {
  135. list := elastic.Get(search_index, search_type, fmt.Sprintf(query, strings.Join(es_ids, `","`), len(es_ids)))
  136. if list != nil {
  137. for _, v := range *list {
  138. _id := MC.ObjToString(v["_id"])
  139. bn := infos[_id]
  140. bn.Title = MC.ObjToString(v["title"])
  141. bn.PublishTime = MC.Int64All(v["publishtime"])
  142. bn.Subtype = MC.If(v["subtype"] != nil, MC.ObjToString(v["subtype"]), MC.ObjToString(v["toptype"])).(string)
  143. bn.Area = MC.If(MC.ObjToString(v["area"]) == "A", "全国", MC.ObjToString(v["area"])).(string)
  144. bn.Buyerclass = MC.ObjToString(v["buyerclass"])
  145. bn.City = MC.ObjToString(v["city"])
  146. bn.Industry = MC.If(MC.ObjToString(v["s_subscopeclass"]) != "", strings.Split(strings.Split(MC.ObjToString(v["s_subscopeclass"]), ",")[0], "_")[0], "").(string)
  147. bn.SpiderCode = MC.ObjToString(v["spidercode"])
  148. bn.Site = MC.ObjToString(v["site"])
  149. }
  150. }
  151. }
  152. //mongodb bidding
  153. mgo_ids := []primitive.ObjectID{}
  154. for _, v := range es_ids {
  155. if infos[v].Title == "" {
  156. mgo_ids = append(mgo_ids, mongodb.StringTOBsonId(v))
  157. }
  158. }
  159. if len(mgo_ids) > 0 {
  160. list, ok := IC.MgoBidding.Find("bidding", map[string]interface{}{"_id": map[string]interface{}{"$in": mgo_ids}}, nil, mongodb_fields, false, -1, -1)
  161. if ok && *list != nil {
  162. for _, v := range *list {
  163. _id := mongodb.BsonIdToSId(v["_id"])
  164. bn := infos[_id]
  165. bn.Title = MC.ObjToString(v["title"])
  166. bn.PublishTime = MC.Int64All(v["publishtime"])
  167. bn.Subtype = MC.If(v["subtype"] != nil, MC.ObjToString(v["subtype"]), MC.ObjToString(v["toptype"])).(string)
  168. bn.Area = MC.If(MC.ObjToString(v["area"]) == "A", "全国", MC.ObjToString(v["area"])).(string)
  169. bn.Buyerclass = MC.ObjToString(v["buyerclass"])
  170. bn.City = MC.ObjToString(v["city"])
  171. bn.Industry = MC.If(MC.ObjToString(v["s_subscopeclass"]) != "", strings.Split(strings.Split(MC.ObjToString(v["s_subscopeclass"]), ",")[0], "_")[0], "").(string)
  172. bn.SpiderCode = MC.ObjToString(v["spidercode"])
  173. bn.Site = MC.ObjToString(v["site"])
  174. }
  175. }
  176. }
  177. //mongodb bidding_back
  178. mgo_back_ids := []primitive.ObjectID{}
  179. for _, v := range mgo_ids {
  180. if infos[mongodb.BsonIdToSId(v)].Title == "" {
  181. mgo_back_ids = append(mgo_back_ids, v)
  182. }
  183. }
  184. if len(mgo_back_ids) > 0 {
  185. list, ok := IC.MgoBidding.Find("bidding_back", map[string]interface{}{"_id": map[string]interface{}{"$in": mgo_back_ids}}, nil, mongodb_fields, false, -1, -1)
  186. if ok && *list != nil {
  187. for _, v := range *list {
  188. _id := mongodb.BsonIdToSId(v["_id"])
  189. bn := infos[_id]
  190. bn.Title = MC.ObjToString(v["title"])
  191. bn.PublishTime = MC.Int64All(v["publishtime"])
  192. bn.Subtype = MC.If(v["subtype"] != nil, MC.ObjToString(v["subtype"]), MC.ObjToString(v["toptype"])).(string)
  193. bn.Area = MC.If(MC.ObjToString(v["area"]) == "A", "全国", MC.ObjToString(v["area"])).(string)
  194. bn.Buyerclass = MC.ObjToString(v["buyerclass"])
  195. bn.City = MC.ObjToString(v["city"])
  196. bn.Industry = MC.If(MC.ObjToString(v["s_subscopeclass"]) != "", strings.Split(strings.Split(MC.ObjToString(v["s_subscopeclass"]), ",")[0], "_")[0], "").(string)
  197. bn.SpiderCode = MC.ObjToString(v["spidercode"])
  198. bn.Site = MC.ObjToString(v["site"])
  199. }
  200. }
  201. }
  202. //
  203. for _, v := range infos {
  204. res = append(res, v)
  205. }
  206. }
  207. return
  208. }
  209. // 根据定位或者搜索历史 查es
  210. func NewestQuery(city, keys, subtype string) (str string) {
  211. var musts, bools []string
  212. if keys != "" {
  213. for _, v := range strings.Split(keys, ",") {
  214. keys := strings.Split(v, " ") //历史搜索 空格划分
  215. must_tmp := []string{}
  216. for _, key := range keys {
  217. must_tmp = append(must_tmp, fmt.Sprintf(multi_match, "\""+key+"\""))
  218. }
  219. bools = append(bools, fmt.Sprintf(query_bool_must_and, strings.Join(must_tmp, ","), ""))
  220. }
  221. }
  222. if city != "" {
  223. musts = append(musts, fmt.Sprintf(query_bool_must, "city", `"`+city+`"`))
  224. }
  225. //未登录首页推送数据限制
  226. if subtype != "" {
  227. musts = append(musts, fmt.Sprintf(query_bool_must, "subtype", subtype))
  228. }
  229. minimum_should_match := 0
  230. if len(bools) > 0 {
  231. minimum_should_match = 1
  232. }
  233. str = fmt.Sprintf(query_city_hkeys, strings.Join(musts, ","), strings.Join(bools, ","), minimum_should_match, IC.C.NewsLimitNum)
  234. logx.Info("str:", str)
  235. return
  236. }
  237. // es查询
  238. func NewestES(doSearchStr string) (res []*bxbase.NewestList) {
  239. list := elastic.Get(search_index, search_type, doSearchStr)
  240. if list != nil && len(*list) > 0 {
  241. for _, v := range *list {
  242. _id := mongodb.BsonIdToSId(v["_id"])
  243. isValidFile, _ := v["isValidFile"].(bool)
  244. res = append(res, &bxbase.NewestList{
  245. Id: ME.EncodeArticleId2ByCheck(_id),
  246. Title: MC.ObjToString(v["title"]),
  247. Subtype: MC.If(v["subtype"] != nil, MC.ObjToString(v["subtype"]), MC.ObjToString(v["toptype"])).(string),
  248. Area: MC.If(MC.ObjToString(v["area"]) == "A", "全国", MC.ObjToString(v["area"])).(string),
  249. Buyerclass: MC.ObjToString(v["buyerclass"]),
  250. City: MC.ObjToString(v["city"]),
  251. Industry: MC.If(MC.ObjToString(v["s_subscopeclass"]) != "", strings.Split(strings.Split(MC.ObjToString(v["s_subscopeclass"]), ",")[0], "_")[0], "").(string),
  252. Budget: MC.Int64All(v["budget"]),
  253. Bidamount: MC.Int64All(v["bidamount"]),
  254. FileExists: isValidFile, //附件
  255. PublishTime: MC.Int64All(v["publishtime"]),
  256. Site: MC.ObjToString(v["site"]),
  257. SpiderCode: MC.ObjToString(v["spidercode"]),
  258. })
  259. }
  260. }
  261. return
  262. }
  263. // GetRedisKeyTimeout 获取缓存的key 和超时时间
  264. func GetRedisKeyTimeout(status int, positionId int64) (redisKey string, timeout int) {
  265. switch status {
  266. case StatusNoLogin:
  267. redisKey = "p1_indexMessage_new_noLogin_%d_%d_%d"
  268. redisKey = fmt.Sprintf(redisKey, time.Now().Year(), time.Now().Month(), time.Now().Day())
  269. timeout = 60 * 60 * 24
  270. case StatusLoginUser:
  271. redisKey = "p1_indexMessage_new_%d_%d_%d_%d" // 登录用户使用的缓存key
  272. redisKey = fmt.Sprintf(redisKey, positionId, time.Now().Year(), time.Now().Month(), time.Now().Day())
  273. timeout = 15 * 60
  274. case StatusLogin:
  275. redisKey = "p1_indexMessage_new_login_%d_%d_%d" // 登录用户使用的最新标讯缓存key
  276. redisKey = fmt.Sprintf(redisKey, time.Now().Year(), time.Now().Month(), time.Now().Day())
  277. timeout = 15 * 60
  278. }
  279. return
  280. }
  281. // PutNewsCache 存缓存
  282. func PutNewsCache(redisKey string, redisTimeout int, list []*bxbase.NewestList) {
  283. b, err := json.Marshal(list)
  284. if err != nil {
  285. log.Printf("保存缓存 序列化异常,data:%s,err:%s\n", list, err.Error())
  286. return
  287. }
  288. if err = redis.PutBytes("other", redisKey, &b, redisTimeout); err != nil {
  289. log.Printf("保存缓存 redis 异常,key:%s,err:%s\n", redisKey, err.Error())
  290. }
  291. }
  292. // GetNewsCache 取缓存
  293. func GetNewsCache(redisKey string) (list []*bxbase.NewestList, err error) {
  294. redisByte, err := redis.GetBytes("other", redisKey)
  295. if err != nil || redisByte == nil || len(*redisByte) == 0 {
  296. return list, err
  297. }
  298. err = json.Unmarshal(*redisByte, &list)
  299. if err != nil {
  300. logx.Info(fmt.Sprintf("读取缓存 序列化异常,err:%s", err.Error()))
  301. return nil, err
  302. }
  303. return list, nil
  304. }