search.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package entity
  2. import (
  3. MC "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/redis"
  5. "app.yhyue.com/moapp/jypkg/common/src/qfw/util/jy"
  6. "encoding/json"
  7. "fmt"
  8. IC "jyBXCore/rpc/init"
  9. "jyBXCore/rpc/service"
  10. "jyBXCore/rpc/type/bxcore"
  11. "jyBXCore/rpc/util"
  12. "log"
  13. "strconv"
  14. "strings"
  15. "time"
  16. )
  17. var (
  18. SearchCacheKey = "searchDataCache_%d_%s_%s_%s"
  19. SearchCacheNoLoginKey = "searchDataCacheNoLogin_%d_%s_%s_%s"
  20. SearchCacheCount = "searchCountCache_%d_%s_%s_%s"
  21. SearchCacheCountNoLogin = "searchCountCacheNoLogin_%d_%s_%s_%s"
  22. )
  23. type KeyWordsSearch struct{}
  24. func NewKeyWordsSearch() *KeyWordsSearch {
  25. return &KeyWordsSearch{}
  26. }
  27. // IsEmptySearch 是否是空搜索,如果是空搜索查缓存数据
  28. func (kws *KeyWordsSearch) IsEmptySearch(in *bxcore.SearchReq) bool {
  29. //有主关键词 或 选择了行业,都不是空搜索
  30. if strings.TrimSpace(in.KeyWords) != "" || strings.TrimSpace(in.Industry) != "" || strings.TrimSpace(in.AdditionalWords) != "" {
  31. return false
  32. }
  33. //所有的未登录空搜索 缓存都最多查500条数据
  34. return true
  35. }
  36. // GetBidSearchListByCache 查询缓存数据
  37. // 未登录用户默认搜索和关键词搜索改成500条和免费用户保持一致--需求调整P260来自产品经理杨蘭20220116
  38. func (kws *KeyWordsSearch) GetBidSearchListByCache(in *bxcore.SearchReq) (list []*bxcore.SearchList, count, total int64) {
  39. //缓存数据 最大量是5000条 100页数据
  40. l, c := func(in *bxcore.SearchReq) (list []*bxcore.SearchList, count int64) {
  41. //缓存数据总量 - 当前平台
  42. redisCountKey := fmt.Sprintf(SearchCacheCount, in.SearchGroup, MC.If(in.IsPay, "v", "f").(string), MC.If(in.BidField != "", in.BidField, "n").(string), in.Platform)
  43. //缓存数据: SearchGroup-全部;招标信息;超前项目信息;kws.PageNum-当前页 免费用户 or 付费用户
  44. redisDataKey := fmt.Sprintf(SearchCacheKey, in.SearchGroup, MC.If(in.IsPay, "v", "f").(string), MC.If(in.BidField != "", in.BidField, "n").(string), in.Platform)
  45. if in.UserId == "" {
  46. // 未登录用户查的不是一个库 缓存也分开
  47. //缓存数据总量 - 当前平台
  48. redisCountKey = fmt.Sprintf(SearchCacheCountNoLogin, in.SearchGroup, MC.If(in.IsPay, "v", "f").(string), MC.If(in.BidField != "", in.BidField, "n").(string), in.Platform)
  49. //缓存数据: SearchGroup-全部;招标信息;超前项目信息;kws.PageNum-当前页 免费用户 or 付费用户
  50. redisDataKey = fmt.Sprintf(SearchCacheNoLoginKey, in.SearchGroup, MC.If(in.IsPay, "v", "f").(string), MC.If(in.BidField != "", in.BidField, "n").(string), in.Platform)
  51. }
  52. count = int64(redis.GetInt(util.RedisNameNew, redisCountKey))
  53. sCache, err := redis.GetNewBytes(util.RedisNameNew, redisDataKey)
  54. log.Println("-------------------------redisDataKey--------------------------------:", redisDataKey)
  55. if err == nil {
  56. if sCache != nil && len(*sCache) > 0 {
  57. err = json.Unmarshal(*sCache, &list)
  58. if err == nil {
  59. return
  60. } else {
  61. log.Println("缓存序列化异常")
  62. }
  63. }
  64. }
  65. //无缓存数据 或 缓存数据查询异常
  66. //查库>存redis缓存
  67. //查询缓存数据 参数初始化
  68. kws.DefaultSearchParamsAuto(in)
  69. //缓存数据
  70. count, list = service.GetBidSearchData(in, true)
  71. if len(list) > 0 {
  72. redis.Put(util.RedisNameNew, redisCountKey, count, MC.If(IC.C.DefaultSearchCacheTime > 0, IC.C.DefaultSearchCacheTime*60*60, 24*60*60).(int))
  73. b, err := json.Marshal(list)
  74. if err == nil {
  75. redis.PutBytes(util.RedisNameNew, redisDataKey, &b, MC.If(IC.C.DefaultSearchCacheTime > 0, IC.C.DefaultSearchCacheTime*60*60, 24*60*60).(int))
  76. } else {
  77. log.Println("默认搜索查询结果保存redis缓存异常")
  78. }
  79. } else {
  80. log.Println("默认搜索 暂无数据")
  81. }
  82. return
  83. }(in)
  84. if len(l) > 0 {
  85. total = c
  86. limitCount := int64(util.SearchPageSize * MC.If(in.IsPay, util.SearchMaxPageNum_PAYED, util.SearchMaxPageNum).(int))
  87. count = c
  88. if count > limitCount {
  89. count = limitCount
  90. }
  91. list = l[(in.PageNum-1)*in.PageSize : in.PageNum*in.PageSize]
  92. //是否收藏
  93. util.MakeCollection(in.UserId, list)
  94. }
  95. return
  96. }
  97. // DefaultSearchParamsAuto 缓存查询条件初始化
  98. func (kws *KeyWordsSearch) DefaultSearchParamsAuto(in *bxcore.SearchReq) {
  99. in.TopType = ""
  100. in.City = ""
  101. in.Industry = ""
  102. in.FileExists = ""
  103. in.WinnerTel = ""
  104. in.BuyerTel = ""
  105. in.BuyerClass = ""
  106. in.Price = ""
  107. in.SelectType = "title"
  108. in.Province = ""
  109. }
  110. // SaveKeyWordsToHistory 保存历史记录
  111. func (kws *KeyWordsSearch) SaveKeyWordsToHistory(in *bxcore.SearchReq) {
  112. if in.KeyWords != "" {
  113. //历史记录
  114. history := redis.GetStr("other", "s_"+in.UserId)
  115. keys := util.SearchHistory(history, in.KeyWords, in.AdditionalWords)
  116. if len(keys) > 0 {
  117. if b := redis.Put("other", "s_"+in.UserId, strings.Join(keys, ","), -1); !b {
  118. log.Println("保存搜索记录异常,用户id:", in.UserId)
  119. }
  120. }
  121. }
  122. }
  123. // GetSearchKeyWordsQueryStr 关键词和附加词处理 获取关键词查询条件;是否进行分词查询
  124. func (kws *KeyWordsSearch) GetSearchKeyWordsQueryStr(in *bxcore.SearchReq) (searchWords []string) {
  125. // in.SearchMode 搜索模式:0:精准搜索;1:模糊搜索
  126. // 精准搜索:不分词,完全匹配;(中间带空格的关键词组自动分词)
  127. // 模糊搜索:对用户输入的单个关键词进行分词处理,但必须都存在;
  128. //主关键词词组
  129. if in.KeyWords != "" {
  130. if in.SearchMode == 1 {
  131. if ikWords := util.HttpEs(in.KeyWords, "ik_smart", IC.DB.Es.Addr); ikWords != "" {
  132. in.KeyWords = jy.KeywordsProcessing(ikWords, IC.C.JYKeyMark)
  133. }
  134. }
  135. searchWords = append(searchWords, in.KeyWords)
  136. }
  137. //多组附加词,每组间,号隔开。每组内如果关键词中间有空格,自动分词
  138. if in.AdditionalWords != "" {
  139. if in.SearchMode == 1 {
  140. var (
  141. addWords []string
  142. )
  143. for _, awv := range strings.Split(in.AdditionalWords, ",") {
  144. if strings.TrimSpace(awv) != "" {
  145. if ikWords := util.HttpEs(awv, "ik_smart", IC.DB.Es.Addr); ikWords != "" {
  146. addWords = append(addWords, jy.KeywordsProcessing(ikWords, IC.C.JYKeyMark))
  147. }
  148. }
  149. }
  150. if len(addWords) > 0 {
  151. in.AdditionalWords = strings.Join(addWords, ",")
  152. }
  153. }
  154. searchWords = append(searchWords, strings.Split(in.AdditionalWords, ",")...)
  155. }
  156. return
  157. }
  158. // SearchParamsHandle 搜索条件 处理
  159. func (kws *KeyWordsSearch) SearchParamsHandle(in *bxcore.SearchReq) []string {
  160. baseUserId, _ := strconv.ParseInt(in.NewUserId, 10, 64)
  161. accountId, _ := strconv.ParseInt(in.AccountId, 10, 64)
  162. positionType, _ := strconv.ParseInt(in.PositionType, 10, 64)
  163. positionId, _ := strconv.ParseInt(in.PositionId, 10, 64)
  164. //判断用户身份
  165. userInfo := IC.Middleground.PowerCheckCenter.Check(in.AppId, in.MgoUserId, baseUserId, accountId, in.EntId, positionType, positionId)
  166. //是否是付费用户
  167. in.IsPay = !userInfo.Free.IsFree
  168. //默认搜索范围
  169. if in.SelectType == "" {
  170. in.SelectType = "title,content"
  171. }
  172. queryItems := util.GetQueryItems(in.SelectType, IC.C.BidSearchOldUserLimit, userInfo.Free.Registedate, in.IsPay)
  173. in.SelectType = strings.Join(queryItems, ",")
  174. // in.SearchGroup 搜索分组 搜索分组:默认0:全部;1:招标采购公告;2:超前项目
  175. // 详情页判断是否能使用超前项目 老版超级订阅、大会员、商机管理有权限
  176. if in.SearchGroup < 0 || in.SearchGroup > 2 {
  177. in.SearchGroup = 1
  178. }
  179. //信息类型
  180. if in.Subtype == "" && in.TopType == "" {
  181. //(免费用户和新版超级订阅用户 有搜索权限,但是没有查看权限)免费用户与未登录用户支持 拟建,采购意向搜索
  182. if in.SearchGroup > 0 && len(IC.C.DefaultTopTypes) >= int(in.SearchGroup) {
  183. in.Subtype = IC.C.DefaultTopTypes[in.SearchGroup-1]
  184. }
  185. }
  186. // in.SearchMode 搜索模式 搜索模式:0:精准搜索;1:模糊搜索
  187. // 精准搜索:不分词,完全匹配;(中间带空格的关键词组自动分词)
  188. // 模糊搜索:对用户输入的单个关键词进行分词处理,但必须都存在;
  189. if in.SearchMode < 0 || in.SearchMode > 1 {
  190. in.SearchMode = 0
  191. }
  192. // in.WordsMode 搜索关键词模式;默认0:包含所有,1:包含任意
  193. if in.WordsMode < 0 || in.WordsMode > 1 {
  194. in.WordsMode = 0
  195. }
  196. //查询时间publishTime
  197. if in.PublishTime == "" {
  198. //付费用户最新5年;免费用户||未登录用户最新1年
  199. in.PublishTime = fmt.Sprintf("%d-%d", time.Now().AddDate(-1, 0, 0).Unix(), time.Now().Unix())
  200. if in.IsPay {
  201. in.PublishTime = fmt.Sprintf("%d-%d", time.Now().AddDate(-5, 0, 0).Unix(), time.Now().Unix())
  202. }
  203. }
  204. //默认每页数据量
  205. if in.PageSize <= 0 {
  206. in.PageSize = 50
  207. }
  208. //第一页
  209. if in.PageNum <= 0 {
  210. in.PageNum = 1
  211. }
  212. count := MC.If(in.IsPay, IC.C.DefaultBidInfo.PayCount, IC.C.DefaultBidInfo.Count).(int)
  213. if in.PageNum > int64(count)/in.PageSize {
  214. in.PageNum = -1
  215. in.PageSize = -1
  216. }
  217. //行业格式化
  218. if in.Industry != "" {
  219. in.Industry = strings.TrimSpace(in.Industry)
  220. }
  221. //免费用户:高级筛选 采购单位类型、采购单位联系方式、中标企业联系方式、排除词、城市
  222. if userInfo.Free.IsFree {
  223. in.BuyerClass = ""
  224. in.BuyerTel = ""
  225. in.WinnerTel = ""
  226. in.ExclusionWords = ""
  227. in.City = ""
  228. in.ExclusionWords = ""
  229. }
  230. //判断是否有关键词
  231. if in.KeyWords != "" {
  232. //关键词处理
  233. in.KeyWords = strings.TrimSpace(in.KeyWords)
  234. in.InterceptKeyWords, in.InterceptOtherWords, in.KeyWords = util.InterceptSearchKW(in.KeyWords, MC.IntAllDef(IC.C.KeywordsLimit, 35), true) // len(in.Industry) == 0
  235. }
  236. //附加词 每组附加词不能超过15个字符
  237. if in.AdditionalWords != "" {
  238. var additionalWords []string
  239. for _, ak := range strings.Split(in.AdditionalWords, ",") {
  240. if len([]rune(ak)) > 15 {
  241. additionalWords = append(additionalWords, string([]rune(ak)[:15]))
  242. } else {
  243. additionalWords = append(additionalWords, ak)
  244. }
  245. }
  246. in.AdditionalWords = strings.Join(additionalWords, ",") //分组不变
  247. }
  248. //更新关键词搜索历史记录
  249. go kws.SaveKeyWordsToHistory(in)
  250. //排除词 每组排除词不能超过15个字符
  251. if in.ExclusionWords != "" {
  252. var exclusionWords []string
  253. for _, ak := range strings.Split(in.ExclusionWords, ",") {
  254. if len([]rune(ak)) > 15 {
  255. exclusionWords = append(exclusionWords, string([]rune(ak)[:15]))
  256. } else {
  257. exclusionWords = append(exclusionWords, ak)
  258. }
  259. }
  260. in.ExclusionWords = strings.Join(exclusionWords, IC.C.JYKeyMark) //util.MatchSpace.ReplaceAllString(in.ExclusionWords, IC.C.JYKeyMark)
  261. }
  262. return kws.GetSearchKeyWordsQueryStr(in) //格式化关键词
  263. }
  264. // GetBidSearchList 非空搜索 查询
  265. func (kws *KeyWordsSearch) GetBidSearchList(in *bxcore.SearchReq) (count, total int64, list []*bxcore.SearchList) {
  266. //排除异常in.PageNum参数
  267. count, list = service.GetBidSearchData(in, false)
  268. util.MakeCollection(in.UserId, list)
  269. total = count //返回数据总量提示信息
  270. limitCount := MC.If(in.IsPay, int64(util.SearchPageSize*util.SearchMaxPageNum_PAYED), int64(util.SearchPageSize*util.SearchMaxPageNum)).(int64)
  271. if count > limitCount {
  272. count = limitCount //付费用户count 最多5000条,100页数据,每页50条;免费用户count 最多500条,10页数据,每页50条。
  273. }
  274. return
  275. }
  276. // 聚合搜索
  277. func (kws *KeyWordsSearch) PolymerizeSearch(in *bxcore.PolymerizeSearchReq) *bxcore.SearchReturn {
  278. data := &bxcore.SearchReturn{}
  279. //powerCheck := IC.Middleground.PowerCheckCenter.Check(in.AppId, in.UserId, in.NewUserId, in.AccountId, in.EntId, in.PositionType, in.PositionId)
  280. //企业搜索
  281. now1 := time.Now().Unix()
  282. entList := &bxcore.SearchMap{}
  283. entList.Data, entList.Count = service.EntSearch(in.SearchCode)
  284. data.EntList = entList
  285. now2 := time.Now().Unix()
  286. //采购单位搜搜索
  287. procureList := &bxcore.SearchMap{}
  288. procureList.Data, procureList.Count = service.ProcureSearch(in.SearchCode)
  289. data.ProcureList = procureList
  290. now3 := time.Now().Unix()
  291. log.Println("企业查询耗时", now2-now1)
  292. log.Println("采购单位搜搜索", now3-now2)
  293. /*if in.AccountId > 0 {
  294. //菜单搜索
  295. data.MenuList = service.MenuSearch(in)
  296. //标讯搜索
  297. now4 := time.Now().Unix()
  298. subscribeList := &bxcore.SearchMap{}
  299. subscribeList.Data = service.SubscribeSearch(in.SearchCode, powerCheck)
  300. data.SubscribeList = subscribeList
  301. now4 := time.Now().Unix()
  302. log.Println("菜单搜索", now4-now3)
  303. }*/
  304. return data
  305. }