package model import ( "encoding/json" "fmt" "go.mongodb.org/mongo-driver/bson" IC "jyBXSubscribe/rpc/init" ms "jyBXSubscribe/rpc/model/service" "jyBXSubscribe/rpc/type/bxsubscribe" "jyBXSubscribe/rpc/util" "log" "strconv" "strings" "sync" "time" "github.com/gogf/gf/v2/util/gconv" "app.yhyue.com/moapp/jybase/common" "app.yhyue.com/moapp/jybase/date" "app.yhyue.com/moapp/jybase/encrypt" elastic "app.yhyue.com/moapp/jybase/es" P "app.yhyue.com/moapp/jybase/mapping" "app.yhyue.com/moapp/jybase/mongodb" "app.yhyue.com/moapp/jybase/mysql" "app.yhyue.com/moapp/jybase/redis" "github.com/zeromicro/go-zero/core/logx" "go.mongodb.org/mongo-driver/bson/primitive" ) const ( pageSize = 100 AllSubPushCacheSize = 200 query = `{"query":{"terms":{"_id":["%s"]}},"_source":["_id","area","city", "publishtime", "s_subscopeclass", "subtype", "title", "toptype", "type", "buyerclass","bidamount","budget","projectname","buyer","bidopentime","s_winner","filetext","spidercode","site","buyertel","buyerperson","agency","agencyperson","agencytel","winnerperson","winnertel","signendtime","bidendtime","entidlist","isValidFile"],"from":0,"size":%d}` mongodb_fields = `{"_id":1,"area":1,"publishtime":1,"s_subscopeclass":1,"subtype":1,"title":1,"toptype":1,"type":1, "city":1,"buyerclass":1,"budget":1,"bidamount":1,"s_winner":1,"bidopentime":1,"buyer":1,"projectname":1,"filetext":1,"spidercode":1,"site":1,"buyertel":1,"buyerperson":1,"agency":1,"agencyperson":1,"agencytel":1,"winnerperson":1,"winnertel":1,"signendtime":1,"bidendtime":1,"entidlist":1,"isValidFile":1}` SubFreeFlag = "fType" SubVipFlag = "vType" MemberFlag = "mType" EntnicheFlag = "eType" oneDay = 24 * 60 * 60 ) var ( ennicheInsertCollKey = []string{"infoid", "matchkeys", "date", "area", "city", "district", "buyerclass", "toptype", "subtype", "subscopeclass", "budget", "bidamount", "attachment_count", "userid", "entid", "deptid", "source", "product"} subscribeInsertCollKey = []string{"infoid", "matchkeys", "date", "area", "city", "district", "buyerclass", "toptype", "subtype", "subscopeclass", "budget", "bidamount", "attachment_count", "userid", "isvip"} memberInsertCollKey = []string{"infoid", "matchkeys", "date", "area", "city", "district", "buyerclass", "toptype", "subtype", "subscopeclass", "budget", "bidamount", "attachment_count", "userid"} ) var aboutDbMsg map[string]*AboutDbMsg = map[string]*AboutDbMsg{ SubFreeFlag: &AboutDbMsg{"push.pushsubscribe", "subpush"}, SubVipFlag: &AboutDbMsg{"push.pushsubscribe", "subpush"}, MemberFlag: &AboutDbMsg{"push.pushmember", "memberpush"}, EntnicheFlag: &AboutDbMsg{"push.pushentniche", "entnichepush"}, } type AboutDbMsg struct { MysqlTable string RedisKeyFlag string } type SubPush struct { Date string Datas []*bxsubscribe.SubscribeInfo Count int64 } type PushCa struct { Date int64 InfoId string Visit int Index int64 Keys []string Type int Isvip int FileExists bool Source int64 Title string SourceAll string } // 查询参数 type SubPushQueryParam struct { Mgo_bidding mongodb.MongodbSim // Bidding string // Bidding_back string // UserId string //用户id PageNum int //页面 PageSize int //每页数量 SelectTime string //时间 Area string //区域 City string //城市 Buyerclass string //采购单位行业 Subtype string //信息类型 二级分类 Subscopeclass string //信息行业 Key string //订阅词 Export bool //导出 EntId string //企业id Price string //价格 FileExists string //是否有附件;默认全部;1:有附件;-1:无附件 EntUserId string //商机管理用户id DeptId string //商机管理用户部门id IsRead string //是否已读 Source string //信息来源 Staffs []string //分发人员 BaseServiceMysql *mysql.Mysql NewUserId int64 IsEnt bool SelectInfoIds []string BuySubject int64 UserType string PositionType int64 IsPayUser bool // 是否是付费用户 NotReturnCount int64 Item string SelectKeys []string //关键词 District string SubPushInactive int // 订阅活跃标记 } // 关键词参数 type KeyParam struct { UserId string //用户id EntUserId string //商机管理用户id DeptId string //商机管理用户部门id NewUserId int64 IsEnt bool VipPower int64 EntId string //企业id MemberPower int64 PowerSource int64 UserPower int64 PositionType int64 } func (spqp *SubPushQueryParam) IsEmpty() bool { return (spqp.SelectTime == "" || spqp.SelectTime == "all") && spqp.Area == "" && spqp.District == "" && spqp.City == "" && spqp.Buyerclass == "" && spqp.Subscopeclass == "" && spqp.Subtype == "" && spqp.Key == "" && spqp.Item == "" && spqp.Price == "" && spqp.FileExists == "" && len(spqp.Staffs) == 0 && spqp.Source == "" && spqp.IsRead == "" } type subscribePush struct { ModuleFlag string } func NewSubscribePush(module ...string) *subscribePush { m := "" if len(module) > 0 { m = module[0] } return &subscribePush{m} } // 从pushcache_2_a中取 func (s *subscribePush) GetTodayCache(userId, userType string) (*SubPush, error) { pc_a, err := redis.GetNewBytes("pushcache_2_b", s.todayKey(userId, userType)) if err != nil { return nil, err } if pc_a == nil { return nil, nil } var p *SubPush if err := json.Unmarshal(*pc_a, &p); err != nil { return nil, err } return p, nil } // 往pushcache_2_a中放 func (s *subscribePush) PutTodayCache(userId, userType string, pc_a *SubPush) { redis.Put("pushcache_2_b", s.todayKey(userId, userType), pc_a, oneDay) } // 获取redis key func (s *subscribePush) todayKey(userId, userType string) string { if s.ModuleFlag == EntnicheFlag { switch userType { case SubVipFlag: return fmt.Sprintf("%s_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, "vip", userId) case MemberFlag: return fmt.Sprintf("%s_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, "member", userId) case SubFreeFlag: return fmt.Sprintf("%s_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, "free", userId) } } return fmt.Sprintf("%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, userId) } func (s *subscribePush) allKey(userId, userType string) string { if s.ModuleFlag == EntnicheFlag { switch userType { case SubVipFlag: return fmt.Sprintf("all_%s_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, "vip", userId) case MemberFlag: return fmt.Sprintf("all_%s_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, "member", userId) case SubFreeFlag: return fmt.Sprintf("all_%s_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, "free", userId) } } return fmt.Sprintf("all_%s_%s", aboutDbMsg[s.ModuleFlag].RedisKeyFlag, userId) } // 历史推送记录中单条信息格式化 func (s *subscribePush) InfoFormat(p *PushCa, info *map[string]interface{}, isPay bool) *bxsubscribe.SubscribeInfo { area := common.ObjToString((*info)["area"]) if area == "A" { area = "全国" } industry := common.ObjToString((*info)["s_subscopeclass"]) scs := strings.Split(industry, ",") if len(scs) > 0 { industry = scs[0] if industry != "" { iss := strings.Split(industry, "_") if len(iss) > 0 { industry = iss[0] } } } infotype := common.ObjToString((*info)["subtype"]) if infotype == "" { infotype = common.ObjToString((*info)["toptype"]) } _id := p.InfoId if _id == "" { _id = common.ObjToString((*info)["_id"]) } isValidFile, _ := (*info)["isValidFile"].(bool) formatInfo := &bxsubscribe.SubscribeInfo{ XId: encrypt.EncodeArticleId2ByCheck(_id), Title: common.InterfaceToStr((*info)["title"]), Area: area, City: common.InterfaceToStr((*info)["city"]), BuyerClass: common.InterfaceToStr((*info)["buyerclass"]), Subtype: infotype, Industry: industry, PublishTime: common.Int64All((*info)["publishtime"]), CaIndex: p.Index, CaDate: p.Date, CaIsvisit: int64(p.Visit), CaIsvip: int64(p.Isvip), CaType: int64(p.Type), MatchKeys: p.Keys, Budget: common.Float64All((*info)["budget"]), BidAmount: common.Float64All((*info)["bidamount"]), Buyer: common.InterfaceToStr((*info)["buyer"]), ProjectName: common.InterfaceToStr((*info)["projectname"]), Winner: common.InterfaceToStr((*info)["s_winner"]), BidOpenTime: common.Int64All((*info)["bidopentime"]), CaFileExists: p.FileExists, Source: p.Source, Site: common.InterfaceToStr((*info)["site"]), SpiderCode: common.InterfaceToStr((*info)["spidercode"]), Toptype: common.InterfaceToStr((*info)["toptype"]), IsValidFile: isValidFile, SourceAll: p.SourceAll, } // 免费用户返回精简列表字段 if !isPay { return formatInfo } winnerList := common.InterfaceToStr((*info)["s_winner"]) //中标企业名称集合 if winnerList != "" && len(strings.Split(winnerList, ",")) > 0 { for wk, wv := range strings.Split(winnerList, ",") { var ( winnerId = "" ) if (*info)["entidlist"] != nil { if entIdList := common.ObjArrToStringArr((*info)["entidlist"].([]interface{})); len(entIdList) > wk { //中标企业id集合 winnerId = entIdList[wk] } } formatInfo.WinnerInfo = append(formatInfo.WinnerInfo, &bxsubscribe.WinnerInfo{ Winner: wv, //中标企业 需要单独处理 WinnerTel: common.ObjToString((*info)["winnertel"]), //中标企业联系电话 WinnerPerson: common.ObjToString((*info)["winnerperson"]), //中标企业联系人 WinnerId: common.If(winnerId != "" && len([]rune(winnerId)) > 12, encrypt.EncodeArticleId2ByCheck(winnerId), "").(string), //中标企业加密id 存在winnerId 异常的情况 }) } } // 付费用户返回详细列表字段 formatInfo.BuyerTel = common.ObjToString((*info)["buyertel"]) formatInfo.BuyerPerson = common.ObjToString((*info)["buyerperson"]) formatInfo.Agency = common.ObjToString((*info)["agency"]) formatInfo.AgencyPerson = common.ObjToString((*info)["agencyperson"]) formatInfo.AgencyTel = common.ObjToString((*info)["agencytel"]) formatInfo.SignendTime = common.Int64All((*info)["signendtime"]) formatInfo.BidendTime = common.Int64All((*info)["bidendtime"]) return formatInfo } func (s *subscribePush) Datas(spqp *SubPushQueryParam, bsp *ViewCondition) (hasNextPage bool, total int64, result []*bxsubscribe.SubscribeInfo) { logx.Info(spqp.UserId, spqp.NewUserId, s.ModuleFlag, "subscribePush query param:", "SelectTime:", spqp.SelectTime, "Area:", spqp.Area, "District:", spqp.District, "City:", spqp.City, "Subtype:", spqp.Subtype, "Subscopeclass:", spqp.Subscopeclass, "Buyerclass:", spqp.Buyerclass, "Key:", spqp.Key, "PageNum:", spqp.PageNum, "Price:", spqp.Price, "FileExists:", spqp.FileExists) if spqp.UserId == "" { return } //不活跃用户处理 if spqp.UserType == "" && spqp.PositionType == 0 { } if spqp.PageNum < 1 { spqp.PageNum = 1 } if spqp.PageSize < 1 || spqp.PageSize > pageSize { if !spqp.Export { spqp.PageSize = pageSize } else { //数据导出查询20000条限制 if spqp.PageSize < 1 || spqp.PageSize > 20000 { spqp.PageSize = 20000 } } } starttime, endtime := int64(0), int64(0) if len(strings.Split(spqp.SelectTime, "_")) == 2 { st := strings.Split(spqp.SelectTime, "_")[0] et := strings.Split(spqp.SelectTime, "_")[1] if st != "" && et != "" { starttime, _ = strconv.ParseInt(st, 0, 64) endtime, _ = strconv.ParseInt(et, 0, 64) if endtime > 0 { etTime := time.Unix(endtime, 0) endtime = time.Date(etTime.Year(), etTime.Month(), etTime.Day(), 23, 59, 59, 0, time.Local).Unix() } } } nowFormat := date.NowFormat(date.Date_Short_Layout) start := (spqp.PageNum - 1) * spqp.PageSize end := start + spqp.PageSize //时间是今天,没有别的过滤条件--首先读取当前推送缓存数据 其次查询数据库 if nowFormat == date.FormatDateByInt64(&starttime, date.Date_Short_Layout) && spqp.Area == "" && spqp.City == "" && spqp.District == "" && spqp.Buyerclass == "" && spqp.Subscopeclass == "" && spqp.Subtype == "" && spqp.Key == "" && spqp.Item == "" && spqp.Price == "" && spqp.FileExists == "" && len(spqp.Staffs) == 0 && spqp.Source == "" && spqp.IsRead == "" && len(spqp.SelectInfoIds) == 0 { subPush := &SubPush{} var err error if spqp.IsEnt == false { subPush, err = s.GetTodayCache(spqp.UserId, spqp.UserType) } if err != nil { logx.Info(spqp.UserId, "GetTodayCache Error", err) } if err != nil || subPush == nil || subPush.Date != nowFormat || len(subPush.Datas) == 0 { list, countSearch := s.getDatasFromMysql(spqp, starttime, endtime, spqp.PageSize, false) subPush = &SubPush{ Date: nowFormat, Datas: list, Count: countSearch, } if spqp.IsEnt == false && spqp.NotReturnCount == 0 { s.PutTodayCache(spqp.UserId, spqp.UserType, subPush) } } length := len(subPush.Datas) if end > length { end = length } if start < length { result = subPush.Datas[start:end] } else { result = subPush.Datas } total = int64(length) //全部,没有过滤条件 之前缓存500 } else if spqp.IsEmpty() && (spqp.PageNum-1)*spqp.PageSize < 200 && len(spqp.SelectInfoIds) == 0 && !spqp.Export { //全部,没有过滤条件 之前缓存5页*50条=250 非数据导出 allCache := &SubPush{} var err error if !spqp.IsEnt { allCache, err = s.GetAllCache(spqp.UserId, spqp.UserType) } if err != nil { logx.Info(spqp.UserId, "GetAllCache Error", err) } if err != nil || allCache == nil || allCache.Date != nowFormat || len(allCache.Datas) == 0 { list, countSearch := []*bxsubscribe.SubscribeInfo{}, int64(0) if spqp.IsEnt { list, countSearch = s.getDatasFromMysql(spqp, starttime, endtime, spqp.PageSize, true) } else { spqp.PageNum = 1 list, countSearch = s.getDatasFromMysql(spqp, starttime, endtime, AllSubPushCacheSize, true) } allCache = &SubPush{ Date: nowFormat, Datas: list, Count: countSearch, } if spqp.IsEnt == false && spqp.NotReturnCount == 0 { s.PutAllCache(spqp.UserId, spqp.UserType, allCache) } } length := len(allCache.Datas) if end > length { end = length } if start < length { result = allCache.Datas[start:end] } else { result = allCache.Datas } total = allCache.Count } else { result, total = s.getDatasFromMysql(spqp, starttime, endtime, spqp.PageSize, true) } if result == nil { result = []*bxsubscribe.SubscribeInfo{} } hasNextPage = len(result) >= spqp.PageSize return } func (s *subscribePush) getDatasFromMysql(spqp *SubPushQueryParam, starttime, endtime int64, size int, isLimit bool) (result []*bxsubscribe.SubscribeInfo, count int64) { start := time.Now().Unix() querys := []string{} userStr := " 1=1 " var ( countSql, findSql string list []map[string]interface{} ) querys = append(querys, " ") if spqp.SelectInfoIds != nil && len(spqp.SelectInfoIds) > 0 { var ( selectInfoIds []string ) for _, sId := range spqp.SelectInfoIds { selectInfoIds = append(selectInfoIds, sId) if len(selectInfoIds) == 50 { findSelectSql := fmt.Sprintf("select a.id,a.date,a.infoid,a.isvisit,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.type,a.attachment_count from %s a where %s order by a.date desc,a.id desc", aboutDbMsg[s.ModuleFlag].MysqlTable, fmt.Sprintf("a.id in ('%s')", strings.Join(selectInfoIds, "','"))) logx.Info(spqp.NewUserId, "subscribePush info ids query sql:", findSelectSql) list = append(list, *spqp.BaseServiceMysql.SelectBySql(findSelectSql)...) selectInfoIds = []string{} } } if len(selectInfoIds) > 0 { findSelectSql := fmt.Sprintf("select a.id,a.date,a.infoid,a.isvisit,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.type,a.attachment_count from %s a where %s order by a.date desc,a.id desc", aboutDbMsg[s.ModuleFlag].MysqlTable, fmt.Sprintf("a.id in ('%s')", strings.Join(selectInfoIds, "','"))) logx.Info(spqp.NewUserId, "subscribePush info ids query sql:", findSelectSql) list = append(list, *spqp.BaseServiceMysql.SelectBySql(findSelectSql)...) selectInfoIds = []string{} } //countSql = fmt.Sprintf("select count(1) as count from %s a where %s", aboutDbMsg[s.ModuleFlag].MysqlTable, fmt.Sprintf("a.id in ('%s')", strings.Join(spqp.SelectInfoIds, "','"))) //logx.Info("countSql", countSql) //findSql = fmt.Sprintf("select a.id,a.date,a.infoid,a.isvisit,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.type,a.attachment_count from %s a where %s order by a.date desc,a.id desc", aboutDbMsg[s.ModuleFlag].MysqlTable, fmt.Sprintf("a.id in ('%s')", strings.Join(spqp.SelectInfoIds, "','"))) ////查询总数 //count = spqp.BaseServiceMysql.CountBySql(countSql) } else { //公共查询条件 //时间 if starttime > 0 && endtime > 0 { querys = append(querys, fmt.Sprintf(" a.date>=%d and a.date<=%d", starttime, endtime)) } else if starttime > 0 && endtime == 0 { querys = append(querys, fmt.Sprintf(" a.date>=%d", starttime)) } else if starttime == 0 && endtime > 0 { querys = append(querys, fmt.Sprintf(" a.date<=%d", endtime)) } else { querys = append(querys, " a.date>0") } var regionArr = []string{} if spqp.Area != "" || spqp.City != "" || spqp.District != "" { //城市 city := []string{} for _, v := range strings.Split(spqp.City, ",") { if P.BidCodeMapping.City[v] != "" { city = append(city, fmt.Sprint(P.BidCodeMapping.City[v])) } } if len(city) > 0 { regionArr = append(regionArr, fmt.Sprintf(" a.city in (%s) ", strings.Join(city, ","))) } //区域 area := []string{} for _, v := range strings.Split(spqp.Area, ",") { if P.BidCodeMapping.Area[v] != "" { area = append(area, fmt.Sprint(P.BidCodeMapping.Area[v])) } } if len(area) > 0 { regionArr = append(regionArr, fmt.Sprintf(" a.area in (%s) ", strings.Join(area, ","))) } //区域 district := []string{} if spqp.District != "" { for _, v := range strings.Split(spqp.District, ",") { cityName := strings.Split(v, "_")[0] districtName := strings.Split(v, "_")[1] if P.BidCodeMapping.District[cityName][districtName] != "" { district = append(district, fmt.Sprint(P.BidCodeMapping.District[cityName][districtName])) } } } if len(district) > 0 { regionArr = append(regionArr, fmt.Sprintf(" a.district in (%s) ", strings.Join(district, ","))) } if len(regionArr) > 0 { querys = append(querys, fmt.Sprintf("(%s)", strings.Join(regionArr, "or"))) } } //采购单位行业 if spqp.Buyerclass != "" { buyerclass := []string{} for _, v := range strings.Split(spqp.Buyerclass, ",") { if fmt.Sprint(P.BidCodeMapping.Buyerclass[v]) != "" { buyerclass = append(buyerclass, fmt.Sprint(P.BidCodeMapping.Buyerclass[v])) } } if len(buyerclass) == 1 { buyerclass = append(buyerclass, "9999") } if len(buyerclass) > 0 { querys = append(querys, fmt.Sprintf("a.buyerclass in (%s)", strings.Join(buyerclass, ","))) } } //信息类型 if spqp.Subtype != "" { subtype := []string{} for _, v := range strings.Split(spqp.Subtype, ",") { subtype = append(subtype, P.BidCodeMapping.Subtype[v]) } if len(subtype) == 1 { subtype = append(subtype, "9999") } if len(subtype) > 0 { querys = append(querys, fmt.Sprintf("subtype in (%s)", strings.Join(subtype, ","))) } } //信息行业 if spqp.Subscopeclass != "" { find_in_set := []string{} for _, v := range strings.Split(spqp.Subscopeclass, ",") { find_in_set = append(find_in_set, fmt.Sprintf("find_in_set('%s',a.subscopeclass)", P.BidCodeMapping.Subscopeclass[v])) } if len(find_in_set) == 1 { querys = append(querys, find_in_set[0]) } else if len(find_in_set) > 1 { querys = append(querys, fmt.Sprintf("(%s)", strings.Join(find_in_set, " or "))) } } //关键词 find_in_set := []string{} if spqp.IsEnt { if spqp.Key != "" { for _, v := range strings.Split(spqp.Key, ",") { find_in_set = append(find_in_set, fmt.Sprintf("find_in_set('%s',replace(a.matchkeys,' ',','))", v)) } } if spqp.Item != "" { for _, v := range strings.Split(spqp.Item, ",") { find_in_set = append(find_in_set, fmt.Sprintf("find_in_set('%s',replace(a.matchitems,' ',','))", v)) } } } else { if spqp.Key != "" { for _, v := range strings.Split(spqp.Key, ",") { find_in_set = append(find_in_set, fmt.Sprintf("find_in_set('%s',replace(a.matchkeys,' ',','))", v)) } } if spqp.Item != "" { //通过分类名搜索 keyArr := s.ItemToKey(spqp) for _, v := range strings.Split(keyArr, ",") { find_in_set = append(find_in_set, fmt.Sprintf("find_in_set('%s',replace(a.matchkeys,' ',','))", v)) } } } if len(find_in_set) == 1 { querys = append(querys, find_in_set[0]) } else if len(find_in_set) > 1 { querys = append(querys, fmt.Sprintf("(%s)", strings.Join(find_in_set, " or "))) } //价格- 预算和中标金额 if spqp.Price != "" && strings.Contains(spqp.Price, "-") { minPriceStr, maxPriceStr := strings.Split(spqp.Price, "-")[0], strings.Split(spqp.Price, "-")[1] minPrice := common.Int64All(common.Float64All(minPriceStr) * 10000) //换成元 maxPrice := common.Int64All(common.Float64All(maxPriceStr) * 10000) //换成元 if minPriceStr != "" && maxPriceStr != "" { querys = append(querys, fmt.Sprintf("((a.bidamount>=%d and a.bidamount<=%d) or (a.budget>=%d and a.budget<=%d and a.bidamount is null))", minPrice, maxPrice, minPrice, maxPrice)) } else if minPriceStr != "" { querys = append(querys, fmt.Sprintf("(a.bidamount>=%d or (a.budget>=%d and a.bidamount is null))", minPrice, minPrice)) } else if maxPriceStr != "" { querys = append(querys, fmt.Sprintf("(a.bidamount<=%d or (a.budget<=%d and a.bidamount is null))", maxPrice, maxPrice)) } } //附件 if spqp.FileExists != "" { if spqp.FileExists == "1" { querys = append(querys, fmt.Sprintf("a.attachment_count is not null")) } else if spqp.FileExists == "-1" { querys = append(querys, fmt.Sprintf("a.attachment_count is null")) } } // 是否已读 if spqp.IsRead != "" { if spqp.IsRead == "0" { querys = append(querys, " a.isvisit IS NULL") } else if spqp.IsRead == "1" { querys = append(querys, " a.isvisit=1") } } // 信息来源 if spqp.Source == "1" || spqp.Source == "2" || spqp.Source == "3" { querys = append(querys, " a.source="+spqp.Source) } if spqp.IsEnt { var staffs []string userStr += fmt.Sprintf(" and a.entid='%s' ", spqp.EntId) //判断是企业管理员还是部门管理员 部门管理员获取所有子部门 userEnt := EntInfo(common.IntAll(spqp.EntId), common.IntAll(spqp.EntUserId)) if !(userEnt.Role_admin_system || userEnt.Role_admin_department) { result = []*bxsubscribe.SubscribeInfo{} return } if userEnt.Role_admin_department { // // 部门管理员 获取所有部门和子部门员工 users := GetDisUsers(common.IntAll(spqp.EntId), userEnt.Dept.Id) if users != nil && len(*users) > 0 { for _, v := range *users { if len(spqp.Staffs) > 0 { for _, vv := range spqp.Staffs { if fmt.Sprintf("%d", v.Id) == vv { staffs = append(staffs, common.InterfaceToStr(v.Id)) } } } else { staffs = append(staffs, common.InterfaceToStr(v.Id)) } } } else { log.Printf("部门管理员为获取到部门员工:%s", spqp.EntUserId) result = []*bxsubscribe.SubscribeInfo{} return } } else if len(spqp.Staffs) > 0 { staffs = spqp.Staffs } // 无查询分配人员、是否已读 if spqp.IsRead == "" && len(staffs) == 0 { //查询数量(需要去重) countSql = fmt.Sprintf("select count(1) from %s a where %s %s ", aboutDbMsg[s.ModuleFlag].MysqlTable, userStr, strings.Join(querys, " and ")) //列表查询 findSql = fmt.Sprintf("select a.id,a.infoid,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.attachment_count, IF(a.source is NULL,1,a.source) as source from %s a where %s %s order by a.date desc,a.id desc", aboutDbMsg[s.ModuleFlag].MysqlTable, userStr, strings.Join(querys, " and ")) } else { //查询分配人员或是否已读 staffQuery := " and 1=1 " if len(spqp.Staffs) > 0 { staffQuery += fmt.Sprintf(" and a.userid in ('%s') ", strings.Join(staffs, "','")) } else if len(staffs) > 0 { staffQuery += fmt.Sprintf(" and a.userid in (0,'%s') ", strings.Join(staffs, "','")) } countSql = fmt.Sprintf("select count(1) from %s a where %s %s %s ", aboutDbMsg[s.ModuleFlag].MysqlTable, userStr, strings.Join(querys, " and "), staffQuery) //列表查询 findSql = fmt.Sprintf("select a.id,a.infoid,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.attachment_count,IF(a.source is NULL,1,a.source) as source from %s a where %s %s %s order by a.date desc,a.id desc ", aboutDbMsg[s.ModuleFlag].MysqlTable, userStr, strings.Join(querys, " and "), staffQuery) } } else { // 是否已读 if spqp.IsRead != "" { if spqp.IsRead == "0" { querys = append(querys, " a.isvisit IS NULL") } else if spqp.IsRead == "1" { querys = append(querys, " a.isvisit=1") } } // 信息来源 if spqp.Source == "1" || spqp.Source == "2" || spqp.Source == "3" { querys = append(querys, " a.source="+spqp.Source) } if spqp.PositionType == 1 { //企业主体是企业的个人查询 if spqp.UserType == SubVipFlag { userStr += fmt.Sprintf(" and a.userid='%s' and ( a.product=1 or a.product=3 or a.source>1 ) ", common.If(s.ModuleFlag == EntnicheFlag, spqp.EntUserId, common.InterfaceToStr(spqp.NewUserId))) } else if spqp.UserType == MemberFlag { userStr += fmt.Sprintf(" and a.userid='%s' and ( a.product=2 or a.product=3 or a.source>1 ) ", common.If(s.ModuleFlag == EntnicheFlag, spqp.EntUserId, common.InterfaceToStr(spqp.NewUserId))) } else if spqp.UserType == EntnicheFlag { userStr += fmt.Sprintf(" and a.userid='%s' and ( a.product is null or a.product=3 or a.source>1 ) ", common.If(s.ModuleFlag == EntnicheFlag, spqp.EntUserId, common.InterfaceToStr(spqp.NewUserId))) } else { userStr += fmt.Sprintf(" and a.userid='%s' ", common.If(s.ModuleFlag == EntnicheFlag, spqp.EntUserId, common.InterfaceToStr(spqp.NewUserId))) } } else { if s.ModuleFlag == EntnicheFlag { //老商机管理个人订阅查询 userStr += fmt.Sprintf(" and a.userid='%s' and a.product is null", common.If(s.ModuleFlag == EntnicheFlag, spqp.EntUserId, common.InterfaceToStr(spqp.NewUserId))) } else { //个人订阅查询 userStr += fmt.Sprintf(" and a.userid='%s'", common.If(s.ModuleFlag == EntnicheFlag, spqp.EntUserId, common.InterfaceToStr(spqp.NewUserId))) } } //查询数量 countSql = fmt.Sprintf("select count(1) as count from %s a where %s %s", aboutDbMsg[s.ModuleFlag].MysqlTable, userStr, strings.Join(querys, " and ")) //列表查询语句 findSql = "select a.id,a.date,a.infoid,a.isvisit,REPLACE(a.matchkeys,'+',' ') as matchkeys,a.type,a.attachment_count" if s.ModuleFlag == EntnicheFlag { findSql += ", IF(a.source is NULL,1,a.source) as source " } if s.ModuleFlag != MemberFlag && s.ModuleFlag != EntnicheFlag { findSql += ",a.isvip" } findSql = fmt.Sprintf("%s from %s a where %s %s "+ " order by a.date desc,a.id desc", findSql, aboutDbMsg[s.ModuleFlag].MysqlTable, userStr, strings.Join(querys, " and ")) } //查询总数 logx.Info("countSql", countSql) if spqp.NotReturnCount == 0 { count = spqp.BaseServiceMysql.CountBySql(countSql) } log.Println("数据总数查询", count) if isLimit { findSql += fmt.Sprintf(" limit %d,%d", (spqp.PageNum-1)*size, size) } list = *spqp.BaseServiceMysql.SelectBySql(findSql) logx.Info(spqp.NewUserId, "subscribePush query sql:", findSql) } end1 := time.Now().Unix() log.Println("mysql查询用时:", end1-start) if list != nil && len(list) > 0 { pushCas := s.GetJyPushs(list) if !spqp.Export { result = s.GetInfoByIds(spqp.Mgo_bidding, spqp.Bidding, spqp.Bidding_back, pushCas, spqp.IsPayUser) } else { result = s.GetOnlyExportInfo(pushCas) } } else { result = []*bxsubscribe.SubscribeInfo{} } end2 := time.Now().Unix() log.Println("处理数据用时:", end2-end1) log.Println("总用时用时:", end2-start) return } // GetOnlyInfoId 获取信息id func (s *subscribePush) GetOnlyExportInfo(pushCas []*PushCa) []*bxsubscribe.SubscribeInfo { array := make([]*bxsubscribe.SubscribeInfo, len(pushCas)) for k, v := range pushCas { array[k] = &bxsubscribe.SubscribeInfo{XId: encrypt.EncodeArticleId2ByCheck(v.InfoId), MatchKeys: v.Keys} } return array } // 根据id取内容 func (s *subscribePush) GetInfoByIds(Mgo_bidding mongodb.MongodbSim, bidding, bidding_back string, pushCas []*PushCa, isPay bool) []*bxsubscribe.SubscribeInfo { array := make([]*bxsubscribe.SubscribeInfo, len(pushCas)) if len(pushCas) == 0 { return array } m := map[string]bool{} ids := []string{} for _, v := range pushCas { if m[v.InfoId] { continue } m[v.InfoId] = true ids = append(ids, v.InfoId) } infos := map[string]map[string]interface{}{} //redis pool := make(chan bool, 3) wait := &sync.WaitGroup{} lock := &sync.Mutex{} es_ids := []string{} for _, vv := range ids { pool <- true wait.Add(1) go func(v string) { defer func() { <-pool wait.Done() }() //剑鱼程序未找到赋值 位置;猜测在推送程序中 info_i := redis.Get("pushcache_1", fmt.Sprintf("info_%s", v)) lock.Lock() defer lock.Unlock() if info_i != nil { info_m, _ := info_i.(map[string]interface{}) info_m["_id"] = v infos[v] = info_m } else { es_ids = append(es_ids, v) } }(vv) } wait.Wait() log.Println("ESSSS") //elasticsearch if len(es_ids) > 0 { list := elastic.Get("bidding", "bidding", fmt.Sprintf(query, strings.Join(es_ids, `","`), len(es_ids))) if list != nil { for _, v := range *list { _id := common.ObjToString(v["_id"]) infos[_id] = v } } } log.Println("mongodb") //mongodb bidding mgo_ids := []primitive.ObjectID{} for _, v := range es_ids { if infos[v] == nil { _id, _ := primitive.ObjectIDFromHex(v) mgo_ids = append(mgo_ids, _id) } } if len(mgo_ids) > 0 { list, ok := Mgo_bidding.Find(bidding, map[string]interface{}{"_id": map[string]interface{}{"$in": mgo_ids}}, nil, mongodb_fields, false, -1, -1) if ok && *list != nil { for _, v := range *list { _id := mongodb.BsonIdToSId(v["_id"]) v["_id"] = _id infos[_id] = v } } } log.Println("bidding_back") //mongodb bidding_back mgo_back_ids := []primitive.ObjectID{} for _, v := range mgo_ids { if infos[mongodb.BsonIdToSId(v)] == nil { mgo_back_ids = append(mgo_back_ids, v) } } if len(mgo_back_ids) > 0 { list, ok := Mgo_bidding.Find(bidding_back, map[string]interface{}{"_id": map[string]interface{}{"$in": mgo_back_ids}}, nil, mongodb_fields, false, -1, -1) if ok && *list != nil { for _, v := range *list { _id := mongodb.BsonIdToSId(v["_id"]) v["_id"] = _id infos[_id] = v } } } for k, v := range pushCas { info := infos[v.InfoId] if info == nil { info = map[string]interface{}{} } array[k] = s.InfoFormat(v, &info, isPay) } return array } // 获取历史推送 func (s *subscribePush) GetJyPushs(datas []map[string]interface{}) (pushCas []*PushCa) { pushCas = []*PushCa{} for _, v := range datas { keys := []string{} if matchkeys := common.ObjToString(v["matchkeys"]); matchkeys != "" { keys = strings.Split(matchkeys, " ") } pushCas = append(pushCas, &PushCa{ Date: common.Int64All(v["date"]), InfoId: common.ObjToString(v["infoid"]), Visit: common.IntAll(v["isvisit"]), Index: common.Int64All(v["id"]), Keys: keys, Type: common.IntAll(v["type"]), Isvip: common.IntAll(v["isvip"]), FileExists: common.IntAll(v["attachment_count"]) > 0, Source: common.Int64All(v["source"]), SourceAll: common.ObjToString(v["sourceAll"]), }) } return } // 查看全部列表缓存 func (s *subscribePush) PutAllCache(userId, userType string, datas *SubPush) { log.Println("pushcache_2_a", s.allKey(userId, userType), datas, oneDay) redis.Put("pushcache_2_a", s.allKey(userId, userType), datas, oneDay) } func (s *subscribePush) GetAllCache(userId, userType string) (*SubPush, error) { return s.GetCache("pushcache_2_a", s.allKey(userId, userType)) } func (s *subscribePush) GetCache(code, key string) (*SubPush, error) { pc_a, err := redis.GetNewBytes(code, key) if err != nil { return nil, err } if pc_a == nil { return nil, nil } var p *SubPush if err := json.Unmarshal(*pc_a, &p); err != nil { return nil, err } return p, nil } // 是否收藏 func (s *subscribePush) MakeCollection(userId string, list []*bxsubscribe.SubscribeInfo) { if list == nil || len(list) == 0 { return } param := []interface{}{userId} wh := []string{} for _, v := range list { array := encrypt.DecodeArticleId2ByCheck(v.XId) if len(array) == 1 && array[0] != "" { param = append(param, array[0]) wh = append(wh, "?") } } if len(wh) > 0 { result := IC.MainMysql.SelectBySql(`select bid from bdcollection where userid=? and bid in (`+strings.Join(wh, ",")+`)`, param...) bid_map := map[string]bool{} if result != nil { for _, v := range *result { bid_map[encrypt.EncodeArticleId2ByCheck(common.ObjToString(v["bid"]))] = true } } for _, v := range list { if bid_map[v.XId] { v.Collection = 1 } } } } // 仅移动端首页使用,历史推送7天信息 func (s *subscribePush) sevenDayKey(userId string) string { return fmt.Sprintf("7day_subpush_%s", userId) } func (s *subscribePush) PutSevenDayCache(userId string, datas []*bxsubscribe.SubscribeInfo) { redis.Put("pushcache_2_a", s.sevenDayKey(userId), SubPush{Datas: datas}, 7*24*60*60) } // 从pushcache_2_a中取 func (s *subscribePush) GetSevenDayCache(userId string) ([]*bxsubscribe.SubscribeInfo, error) { allPush, _ := s.GetCache("pushcache_2_a", s.sevenDayKey(userId)) if allPush != nil && allPush.Datas != nil && len(allPush.Datas) > 0 { return allPush.Datas, nil } return nil, nil } // 历史推送记录中单条信息格式化 func InfoFormats(info map[string]interface{}, tmp map[string]interface{}) map[string]interface{} { area := common.ObjToString(info["area"]) if area == "A" { area = "全国" } industry := common.ObjToString(info["s_subscopeclass"]) scs := strings.Split(industry, ",") if len(scs) > 0 { industry = scs[0] if industry != "" { iss := strings.Split(industry, "_") if len(iss) > 0 { industry = iss[0] } } } infotype := common.ObjToString(info["subtype"]) if infotype == "" { infotype = common.ObjToString(info["toptype"]) } if infotype == "" { infotype = common.ObjToString(info["type"]) if infotype == "tender" { infotype = "招标" } else if infotype == "bid" { infotype = "中标" } } info["type"] = infotype return info } // UpdateUserPushUnread 更新app未读标识为已读 func UpdateUserPushUnread(userid string, vt string) { if vt == MemberFlag { IC.Mgo.UpdateById("user", userid, map[string]interface{}{"$set": map[string]interface{}{"i_member_apppushunread": 0}}) } else if vt == EntnicheFlag { IC.Mgo.UpdateById("user", userid, map[string]interface{}{"$set": map[string]interface{}{"i_entniche_apppushunread": 0}}) } else { IC.Mgo.UpdateById("user", userid, map[string]interface{}{"$set": map[string]interface{}{"i_apppushunread": 0}}) } } func (s *subscribePush) SetRead(newUserId, id int64, userId, entUserId, entId string, isEnt bool, userType string) error { if id <= 0 && newUserId == 0 { return nil } if newUserId == 0 { return nil } IC.BaseServiceMysql.UpdateOrDeleteBySql(fmt.Sprintf("update %s set isvisit=1,visittime=now() where userid=? and id=?", aboutDbMsg[s.ModuleFlag].MysqlTable), common.If(s.ModuleFlag == EntnicheFlag, entUserId, newUserId), id) if s.ModuleFlag == EntnicheFlag { userId = entUserId } todaySubPush, err := s.GetTodayCache(userId, userType) //当天数据处理 if err == nil && todaySubPush != nil { for _, v := range todaySubPush.Datas { if v.CaIndex == id { v.CaIsvisit = 1 break } } s.PutTodayCache(userId, userType, todaySubPush) } //全部数据处理 allSubPush, err := s.GetAllCache(userId, userType) if err == nil && allSubPush != nil { for _, v := range allSubPush.Datas { if v.CaIndex == id { v.CaIsvisit = 1 break } } s.PutAllCache(userId, userType, allSubPush) } return nil } // UserInfo 获取用户信息 func (s *subscribePush) UserInfo(baseUserId int64) (*map[string]interface{}, int64) { user, ok := IC.Mgo.FindOneByField("user", map[string]interface{}{"base_user_id": baseUserId}, `{"i_ts_guide":1,"s_m_openid":1,"a_m_openid":1,"s_phone":1,"a_mergeorder":1,"o_jy":1,"l_firstpushtime":1,"i_vip_status":1,"l_vip_endtime":1,"o_vipjy":1,"i_member_status":1,"o_member_jy":1}`) if !ok || user == nil { return nil, 0 } return user, common.Int64All((*user)["l_firstpushtime"]) } // GetKeySet 是否有订阅词 func GetKeySet(t string, u *map[string]interface{}, data []string) (bool, []string) { var industry_ = []string{} if u != nil { if t == SubFreeFlag { o_jy, _ := (*u)["o_jy"].(map[string]interface{}) a_key, _ := o_jy["a_key"].([]interface{}) return len(a_key) > 0, industry_ } else { var obj map[string]interface{} if t == SubVipFlag { obj, _ = (*u)["o_vipjy"].(map[string]interface{}) } else if t == MemberFlag { obj, _ = (*u)["o_member_jy"].(map[string]interface{}) } else if t == EntnicheFlag { if len(data) > 0 { return true, data } else { return false, data } } if obj != nil { if buyerclassObj, ok := obj["a_buyerclass"].([]interface{}); ok { industry_ = common.ObjArrToStringArr(buyerclassObj) } itmes, _ := obj["a_items"].([]interface{}) for _, v := range itmes { item, _ := v.(map[string]interface{}) keys, _ := item["a_key"].([]interface{}) if len(keys) > 0 { return true, industry_ } } } } } return false, industry_ } const ( INDEX = "bidding" TYPE = "bidding" bidField = `"_id","title","publishtime","toptype","subtype","type","area","city","s_subscopeclass","buyerclass","budget","bidamount","filetext","spidercode","site","buyer","bidopentime","buyertel","buyerperson","agency","agencyperson","agencytel","s_winner","winnerperson","winnertel","signendtime","bidendtime","entidlist"` bidTime = `{"range":{"publishtime":{"gt":%d}}}` bidSort = `{"publishtime":"desc"}` findfields = `"title"` ) // 首次访问推送页面 默认生成推送数据 // 默认匹配es 7天内数据 func (s *subscribePush) DefaultDatas(spqp *SubPushQueryParam, bsp *ViewCondition, userType string) (hasNextPage bool, total int64, result []*bxsubscribe.SubscribeInfo) { if spqp.UserId == "" { return false, 0, nil } logx.Info("userId:", spqp.UserId, "newUserId:", spqp.NewUserId) t1 := time.Now() if len(bsp.Keyword) > 0 { logx.Info("--bsp:", bsp) //获取查询语句 qstr := s.getDefaultDatasSQL(bsp) list := elastic.GetAllByNgram(INDEX, TYPE, qstr, findfields, bidSort, bidField, 0, bsp.Size, 500, false) logx.Info(time.Since(t1), "list count:", len(*list)) if list != nil && len(*list) > 0 { var mlist []map[string]interface{} esM := listHistory(spqp) if len(esM) > 0 { for _, m := range *list { if !esM[common.ObjToString(m["_id"])] { mlist = append(mlist, m) } } } else { mlist = *list } logx.Info(time.Since(t1), "mlist count:", len(mlist)) total = int64(len(mlist)) result = s.listManager(spqp, mlist, bsp.Keyword) if len(result) > pageSize { result = result[:pageSize] hasNextPage = true } } } if spqp.SubPushInactive == -1 && spqp.PositionType == 0 && (userType == "vType" || userType == "fType") { IC.Mgo.UpdateById("user", spqp.UserId, bson.M{"$set": bson.M{"subpush_inactive": -2}}) } logx.Info("请求耗时:", time.Since(t1)) return } // 历史订阅消息 func listHistory(spqp *SubPushQueryParam) map[string]bool { m := make(map[string]bool) sql := "SELECT infoid FROM push.pushsubscribe where userid = ? order by date desc, id desc limit 1000;" info := spqp.BaseServiceMysql.SelectBySql(sql, spqp.NewUserId) for _, m1 := range *info { m[common.ObjToString(m1["infoid"])] = true } return m } // 保存推送表 func (s *subscribePush) listManager(spqp *SubPushQueryParam, list []map[string]interface{}, keyword []ViewKeyWord) (resultList []*bxsubscribe.SubscribeInfo) { now := time.Now().Unix() length := len(list) resultList = make([]*bxsubscribe.SubscribeInfo, length) pushInsert := []interface{}{} var product interface{} if spqp.UserType == SubVipFlag { product = 1 } else if spqp.UserType == MemberFlag { product = 2 } for i := length - 1; i >= 0; i-- { v := list[i] title := strings.Replace(common.ObjToString(v["title"]), " ", "", -1) infoid := common.InterfaceToStr(v["_id"]) matchkeys := getKeys(title, keyword) matchkey := strings.Join(matchkeys, " ") subscopeclassStr := "" area := common.If(v["area"] == nil, nil, common.If(common.ObjToString(v["area"]) == "A", 0, common.If(P.BidCodeMapping.Area[common.ObjToString(v["area"])] != "", P.BidCodeMapping.Area[common.ObjToString(v["area"])], 0))) city := common.If(P.BidCodeMapping.City[common.ObjToString(v["city"])] == "", nil, P.BidCodeMapping.City[common.ObjToString(v["city"])]) cityName := common.ObjToString(v["city"]) district := "" districtName := common.ObjToString(v["city"]) if cityName != "" && districtName != "" { district = gconv.String(common.If(P.BidCodeMapping.District[cityName][districtName] == "", nil, P.BidCodeMapping.District[cityName][districtName])) } subtype := common.If(P.BidCodeMapping.Subtype[common.ObjToString(v["subtype"])] == "", nil, P.BidCodeMapping.Subtype[common.ObjToString(v["subtype"])]) toptype := common.If(P.BidCodeMapping.Toptype[common.ObjToString(v["toptype"])] == "", nil, P.BidCodeMapping.Toptype[common.ObjToString(v["toptype"])]) buyerclass := common.If(P.BidCodeMapping.Buyerclass[common.ObjToString(v["buyerclass"])] == "", nil, P.BidCodeMapping.Buyerclass[common.ObjToString(v["buyerclass"])]) attachment_count := 0 if v["isValidFile"] != nil { isValidFile, _ := v["isValidFile"].(bool) attachment_count = common.If(isValidFile, 1, 0).(int) } bidamount := common.If(v["bidamount"] == nil, nil, v["bidamount"]) budget := common.If(v["budget"] == nil, nil, v["budget"]) if s_subscopeclass := common.ObjToString(v["s_subscopeclass"]); s_subscopeclass != "" { subscopeclass := []string{} for _, v := range strings.Split(s_subscopeclass, ",") { if subscopeclass_mapping, ok := P.BidCodeMapping.Subscopeclass[v]; ok { subscopeclass = append(subscopeclass, fmt.Sprint(subscopeclass_mapping)) } } if len(subscopeclass) > 0 { subscopeclassStr = strings.Join(subscopeclass, ",") } } entid := spqp.EntId entUserId := spqp.EntUserId deptid := spqp.DeptId //公共字段处理 pushInsert = append(pushInsert, common.InterfaceToStr(infoid), matchkey, now, area, city, district, buyerclass, toptype, subtype, subscopeclassStr, budget, bidamount, attachment_count) switch s.ModuleFlag { case EntnicheFlag: pushInsert = append(pushInsert, entUserId, entid, deptid, 1, product) case MemberFlag: pushInsert = append(pushInsert, common.InterfaceToStr(spqp.NewUserId)) case SubVipFlag: pushInsert = append(pushInsert, common.InterfaceToStr(spqp.NewUserId), 1) case SubFreeFlag: pushInsert = append(pushInsert, common.InterfaceToStr(spqp.NewUserId), 0) } redis.Put("pushcache_2_a", fmt.Sprintf("pushinfo_%s_%s", spqp.UserId, common.ObjToString(v["_id"])), 1, 86400) redis.Put("pushcache_2_c", fmt.Sprintf("inactiveChange_%s_%s", spqp.UserId, common.ObjToString(v["_id"])), 1, 86400) resultList[i] = s.InfoFormat(&PushCa{ InfoId: infoid, Date: time.Now().Unix(), Keys: matchkeys, FileExists: v["filetext"] != nil, }, &v, spqp.IsPayUser) } id := int64(0) switch s.ModuleFlag { case EntnicheFlag: _, id = spqp.BaseServiceMysql.InsertIgnoreBatch(aboutDbMsg[s.ModuleFlag].MysqlTable, ennicheInsertCollKey, pushInsert) case MemberFlag: _, id = spqp.BaseServiceMysql.InsertIgnoreBatch(aboutDbMsg[s.ModuleFlag].MysqlTable, memberInsertCollKey, pushInsert) default: _, id = spqp.BaseServiceMysql.InsertIgnoreBatch(aboutDbMsg[s.ModuleFlag].MysqlTable, subscribeInsertCollKey, pushInsert) } for i := length - 1; i >= 0; i-- { resultList[i].CaIndex = id id++ } return } // 获取匹配得关键词 func getKeys(title string, keywords []ViewKeyWord) (str []string) { if len(keywords) > 0 { L: for _, v := range keywords { for _, vk := range v.Keyword { if strings.Contains(title, vk) { str = append(str, v.Keyword...) break L } } for _, va := range v.Appended { if strings.Contains(title, va) { str = append(str, v.Appended...) break L } } } } return } // 获取查询语句 func (s *subscribePush) getDefaultDatasSQL(bsp *ViewCondition) (str string) { query := `{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}}}` query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}` multi_match := `{"multi_match": {"query": %s,"type": "phrase", "fields": [%s]}}` query_bool_must_and := `{"bool":{"must":[%s]%s}}` query_bool_must_and_district := `{"bool":{"must":[{"terms":{"city":["%s"]}},{"terms":{"district":["%s"]}}]}}` bools := []string{} musts := []string{} //发布时间最新7天(正式环境需要修改) musts = append(musts, fmt.Sprintf(bidTime, time.Now().AddDate(0, 0, -15).Unix())) //省份 areaCity := []string{} if len(bsp.Area) > 0 { areaquery := `{"terms":{"area":[` for k, v := range bsp.Area { if k > 0 { areaquery += `,` } areaquery += `"` + v + `"` } areaquery += `]}}` areaCity = append(areaCity, areaquery) } //城市 if len(bsp.City) > 0 { areaquery := `{"terms":{"city":[` for k, v := range bsp.City { if k > 0 { areaquery += `,` } areaquery += `"` + v + `"` } areaquery += `]}}` areaCity = append(areaCity, areaquery) } //区域处理 if len(bsp.District) > 0 { for _, v := range bsp.District { cityName := strings.Split(v, "_")[0] districtName := strings.Split(v, "_")[1] areaCity = append(areaCity, fmt.Sprintf(query_bool_must_and_district, cityName, districtName)) } } if len(areaCity) > 0 { musts = append(musts, fmt.Sprintf(query_bool_should, strings.Join(areaCity, ","))) } if len(bsp.Subtype) > 0 { subquery := `{"terms":{"subtype":[` for k, v := range bsp.Subtype { if k > 0 { subquery += `,` } subquery += `"` + v + `"` } subquery += `]}}` musts = append(musts, subquery) } if len(bsp.Buyerclass) > 0 { Buyerclass := `{"terms":{"buyerclass":[` for k, v := range bsp.Buyerclass { if k > 0 { Buyerclass += `,` } Buyerclass += `"` + v + `"` } Buyerclass += `]}}` musts = append(musts, Buyerclass) } boolsNum := 0 //should if len(bsp.Keyword) > 0 { boolsNum = 1 if bsp.SelectType == "" || bsp.SelectType == "2" { bsp.SelectType = "detail\", \"title" } else { bsp.SelectType = "title" } multi_match = fmt.Sprintf(multi_match, "%s", "\""+bsp.SelectType+"\"") for _, v := range bsp.Keyword { shoulds := []string{} must_not := []string{} //附加词 for _, vv := range v.Keyword { vv = strings.TrimSpace(vv) if vv == "" { continue } shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vv+"\"")) } for _, vv := range v.Appended { vv = strings.TrimSpace(vv) if vv == "" { continue } shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vv+"\"")) } //排除词 for _, vv := range v.Exclude { vv = strings.TrimSpace(vv) if vv == "" { continue } must_not = append(must_not, fmt.Sprintf(multi_match, "\""+vv+"\"")) } //添加 if len(shoulds) > 0 { notStr := "" if len(must_not) > 0 { notStr = fmt.Sprintf(`,"must_not":[%s]`, strings.Join(must_not, ",")) } bools = append(bools, fmt.Sprintf(query_bool_must_and, strings.Join(shoulds, ","), notStr)) } } } qstr := fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(bools, ","), boolsNum) logx.Info("----", qstr) return qstr } /*已选条件--关键词*/ type ViewKeyWord struct { Keyword []string `json:"key"` //关键词 Appended []string `json:"appendkey"` //附加词 Exclude []string `json:"notkey"` //排除词 MatchWay int `json:"matchway"` //匹配模式 } /*已选条件*/ type ViewCondition struct { Area []string //地区-省份 City []string //地区-城市 District []string //区县 Buyerclass []string //采购行业 Keyword []ViewKeyWord //关键词 SelectType string //筛选(正文 or 标题) Subtype []string //信息类型 Size int //数量 } // 获取用户信息 func (s *subscribePush) GetUserInfo(spqp *SubPushQueryParam) (vc *ViewCondition) { var isPayBool = false var tmpInfo = struct { Items []interface{} BuyerClass []interface{} SubType []interface{} Area map[string]interface{} District map[string]interface{} SelectType string }{} switch s.ModuleFlag { case MemberFlag: userMap, ok := IC.Mgo.FindById("user", spqp.UserId, `{"o_member_jy":1,"i_member_status":1,"subpush_inactive":1}`) spqp.SubPushInactive = common.IntAll((*userMap)["subpush_inactive"]) if !ok || userMap == nil || len(*userMap) == 0 { return &ViewCondition{} } //大会员 if common.IntAll((*userMap)["i_member_status"]) > 0 { isPayBool = true o_member_jy, _ := (*userMap)["o_member_jy"].(map[string]interface{}) tmpInfo.Items, _ = o_member_jy["a_items"].([]interface{}) tmpInfo.BuyerClass, _ = o_member_jy["a_buyerclass"].([]interface{}) tmpInfo.SubType, _ = o_member_jy["a_infotype"].([]interface{}) tmpInfo.Area, _ = o_member_jy["o_area"].(map[string]interface{}) tmpInfo.District, _ = o_member_jy["o_district"].(map[string]interface{}) } case SubVipFlag: userMap, ok := IC.Mgo.FindById("user", spqp.UserId, `{"o_vipjy":1,"i_vip_status":1,"subpush_inactive":1}`) spqp.SubPushInactive = common.IntAll((*userMap)["subpush_inactive"]) if !ok || userMap == nil || len(*userMap) == 0 { return &ViewCondition{} } if common.IntAll((*userMap)["i_vip_status"]) > 0 { isPayBool = true o_vipjy, _ := (*userMap)["o_vipjy"].(map[string]interface{}) tmpInfo.Items, _ = o_vipjy["a_items"].([]interface{}) tmpInfo.BuyerClass, _ = o_vipjy["a_buyerclass"].([]interface{}) tmpInfo.SubType, _ = o_vipjy["a_infotype"].([]interface{}) tmpInfo.Area, _ = o_vipjy["o_area"].(map[string]interface{}) tmpInfo.District, _ = o_vipjy["o_district"].(map[string]interface{}) } case EntnicheFlag: //商机管理 entUserId, _ := strconv.Atoi(spqp.EntUserId) entId, _ := strconv.Atoi(spqp.EntId) entInfo, deptId := (&ms.MatchJob{}).Start(entId, entUserId) if entInfo != nil && len(entInfo) > 0 { spqp.DeptId = strconv.Itoa(deptId) if common.IntAll(entInfo["i_type"]) == 2 { if entInfo["a_key"] != nil { tmpInfo.Items, _ = entInfo["a_key"].([]interface{}) //信息类型 tmpInfo.SubType, _ = entInfo["a_infotype"].([]interface{}) //省份 tmpInfo.Area, _ = entInfo["o_area"].(map[string]interface{}) tmpInfo.District, _ = entInfo["o_district"].(map[string]interface{}) if common.IntAllDef(entInfo["i_ppstatus"], 0) == 1 && entInfo["o_area_p"] != nil { tmpInfo.Area, _ = entInfo["o_area_p"].(map[string]interface{}) } } } else { isPayBool = true tmpInfo.Items, _ = entInfo["a_items"].([]interface{}) tmpInfo.BuyerClass, _ = entInfo["a_buyerclass"].([]interface{}) tmpInfo.SubType, _ = entInfo["a_infotype"].([]interface{}) tmpInfo.Area, _ = entInfo["o_area"].(map[string]interface{}) tmpInfo.District, _ = entInfo["o_district"].(map[string]interface{}) } } default: userMap, ok := IC.Mgo.FindById("user", spqp.UserId, `{"o_jy":1}`) if !ok || userMap == nil || len(*userMap) == 0 { return &ViewCondition{} } o_jy, _ := (*userMap)["o_jy"].(map[string]interface{}) if o_jy["a_key"] != nil { tmpInfo.Items, _ = o_jy["a_key"].([]interface{}) //信息类型 tmpInfo.SubType, _ = o_jy["a_infotype"].([]interface{}) //省份 tmpInfo.Area, _ = o_jy["o_area"].(map[string]interface{}) tmpInfo.District, _ = o_jy["o_district"].(map[string]interface{}) if common.IntAllDef(o_jy["i_ppstatus"], 0) == 1 && o_jy["o_area_p"] != nil { tmpInfo.Area, _ = o_jy["o_area_p"].(map[string]interface{}) } } } vc = &ViewCondition{ Buyerclass: common.ObjArrToStringArr(tmpInfo.BuyerClass), Subtype: common.ObjArrToStringArr(tmpInfo.SubType), Area: getStringArrFromDbResult(tmpInfo.Area, 1), City: getStringArrFromDbResult(tmpInfo.Area, 2), District: districtHandle(tmpInfo.District), SelectType: "1", } //付费用户 if isPayBool { vc.Size = IC.C.DefaulCount.Pay vc.Keyword = getKeyWordArrFromDbResult(tmpInfo.Items, "", -1) } else { vc.Size = IC.C.DefaulCount.Free vc.Keyword = getKeyWordArrFromDbResultByFree(tmpInfo.Items, "", -1) //vc.Keyword = getKeyWordArrFromDbResult(tmpInfo.Items, "", -1) } return } // 区县处理 func districtHandle(data map[string]interface{}) []string { arr := []string{} for k, v := range data { for _, v1 := range gconv.SliceAny(v) { arr = append(arr, fmt.Sprintf("%s_%s", k, v1)) } } return arr } // 关键词 附加词 排除词 func getKeyWordArrFromDbResult(a_items []interface{}, item string, index int) (arr []ViewKeyWord) { if a_items == nil { return } for _, v := range a_items { vm, _ := v.(map[string]interface{}) if item != "" && index >= 0 && item != common.ObjToString(vm["s_item"]) { continue } kwsArr := vm["a_key"] for i, k := range kwsArr.([]interface{}) { if item != "" && index >= 0 && i != index { continue } kw := ViewKeyWord{} b, e := json.Marshal(k) if e != nil { log.Println(e.Error()) } json.Unmarshal(b, &kw) if kw.MatchWay == 1 { for _, kk := range kw.Keyword { arr = append(arr, ViewKeyWord{ Keyword: []string{kk}, Exclude: kw.Exclude, }) } for _, kk := range kw.Appended { arr = append(arr, ViewKeyWord{ Keyword: []string{kk}, Exclude: kw.Exclude, }) } } else { arr = append(arr, kw) } } } return } // //关键词 附加词 排除词 省份订阅包 - 普通用户 func getKeyWordArrFromDbResultByFree(a_items []interface{}, item string, index int) (arr []ViewKeyWord) { if a_items == nil { return } for _, v := range a_items { kw := ViewKeyWord{} b, e := json.Marshal(v) if e != nil { log.Println(e.Error()) } json.Unmarshal(b, &kw) if kw.MatchWay == 1 { for _, kk := range kw.Keyword { arr = append(arr, ViewKeyWord{ Keyword: []string{kk}, Exclude: kw.Exclude, }) } for _, kk := range kw.Appended { arr = append(arr, ViewKeyWord{ Keyword: []string{kk}, Exclude: kw.Exclude, }) } } else { arr = append(arr, kw) } } return } // 地区格式化 func getStringArrFromDbResult(area map[string]interface{}, i int) (arr []string) { if area == nil { return } var eareArr []string var cityArr []string for k, v := range area { if len(v.([]interface{})) > 0 { cityArr = append(cityArr, common.ObjArrToStringArr(v.([]interface{}))...) } else { eareArr = append(eareArr, k) } } if i == 1 { arr = eareArr } else { arr = cityArr } return } // IsInTsGuide 是否进入向导 func (s *subscribePush) IsInTsGuide(userid string) bool { if userid == "" { return false } data, ok := IC.Mgo.FindById("user", userid, `{"o_jy":1,"i_ts_guide":1,"":1,"i_member_status":1,"i_vip_status":1}`) if ok { //付费用户无免费订阅,不进入订阅向导页面 if common.IntAll((*data)["i_member_status"]) > 0 || common.IntAll((*data)["i_vip_status"]) > 0 { return false } o_jy, _ := (*data)["o_jy"].(map[string]interface{}) i_ts_guide := common.IntAll((*data)["i_ts_guide"]) if i_ts_guide == 2 || (i_ts_guide == 0 && len(o_jy) == 0) { return true } } return false } func (s *subscribePush) Keys(spqp *KeyParam) (result []*bxsubscribe.KeyItems) { keyData := map[string][]interface{}{} if spqp.IsEnt { //企业关键词查找 res_, _ := IC.Mgo.Find("entniche_rule", map[string]interface{}{ "i_userid": map[string]interface{}{ "$exists": false, }, "i_entid": common.Int64All(spqp.EntId), }, "", `{"o_entniche":1}`, false, -1, -1) o_entniche := map[string]interface{}{} if res_ == nil || len(*res_) == 0 { return MapToarr(keyData) } for _, ruleV := range *res_ { o_entniche = common.StructToMapMore(ruleV["o_entniche"]) if o_entniche["a_items"] != nil { a_item := common.ObjArrToMapArr(o_entniche["a_items"].([]interface{})) for _, v := range a_item { if v["a_key"] != nil { a_key_arr := v["a_key"].([]interface{}) s_item := common.InterfaceToStr(v["s_item"]) if keyData[s_item] != nil { //第一次搜索存在 //去重 keyData[s_item] = MergeArray(a_key_arr, keyData[s_item]) } else { //第一次搜索不存在 keyData[s_item] = a_key_arr } } } } } } else { //个人关键词查找 //fType:普通用户;vType:超级订阅用户;mType:大会员用户;eType:商机管理用户 types := 2 typeKey := "" switch s.ModuleFlag { case SubVipFlag: types = 1 typeKey = "o_vipjy" case MemberFlag: types = 1 typeKey = "o_member_jy" case EntnicheFlag: types = 0 typeKey = "o_entniche" case SubFreeFlag: types = 2 typeKey = "o_jy" } if spqp.PositionType == 1 { typeKey = "o_entniche" } o_entniche := &map[string]interface{}{} if spqp.PositionType == 0 { mData, ok := IC.Mgo.FindById("user", spqp.UserId, `{"o_jy":1,"o_vipjy":1,"o_member_jy":1,""i_member_sub_status":1,"s_member_mainid":1}`) if mData == nil || len(*mData) == 0 || !ok { return nil } if s.ModuleFlag == MemberFlag { sub_status := common.Int64All((*mData)["i_member_sub_status"]) if sub_status == 1 { //大会员子账号处理 mData, ok = IC.Mgo.FindById("user", common.InterfaceToStr((*mData)["s_member_mainid"]), `{"o_jy":1,"o_vipjy":1,"o_member_jy":1,""i_member_sub_status":1,"s_member_mainid":1}`) if mData == nil || len(*mData) == 0 || !ok { return nil } } } o_entniche = common.ObjToMap((*mData)[typeKey]) } else { res_, _ := IC.Mgo.FindOneByField("entniche_rule", map[string]interface{}{ "i_userid": common.Int64All(spqp.EntUserId), "i_entid": common.Int64All(spqp.EntId), "i_type": types, }, `{"o_entniche":1}`) if res_ != nil { o_entniche = common.ObjToMap((*res_)["o_entniche"]) } } if s.ModuleFlag == SubVipFlag { //从user表中取 o_vipjy.a_items if (*o_entniche)["a_items"] != nil { a_items := common.ObjArrToMapArr((*o_entniche)["a_items"].([]interface{})) for _, v := range a_items { if v["a_key"] != nil { a_key_arr := v["a_key"].([]interface{}) keyData[common.InterfaceToStr(v["s_item"])] = a_key_arr } } } } else if s.ModuleFlag == MemberFlag { //从user表中取 o_member_jy.a_items //o_memeberjy := common.ObjToMap((*mData)["o_member_jy"]) if (*o_entniche)["a_items"] != nil { a_items := common.ObjArrToMapArr((*o_entniche)["a_items"].([]interface{})) for _, v := range a_items { if v["a_key"] != nil { a_key_arr := v["a_key"].([]interface{}) keyData[common.InterfaceToStr(v["s_item"])] = a_key_arr } } } } else if s.ModuleFlag == EntnicheFlag { res_, _ := IC.Mgo.FindOneByField("entniche_rule", map[string]interface{}{ "i_userid": common.Int64All(spqp.EntUserId), "i_entid": common.Int64All(spqp.EntId), "i_type": types, }, `{"o_entniche":1}`) o_entniche := &map[string]interface{}{} if res_ != nil { o_entniche = common.ObjToMap((*res_)["o_entniche"]) } if (*o_entniche)["a_items"] != nil { a_item := common.ObjArrToMapArr((*o_entniche)["a_items"].([]interface{})) for _, v := range a_item { if v["a_key"] != nil { a_key_arr := v["a_key"].([]interface{}) keyData[common.InterfaceToStr(v["s_item"])] = a_key_arr } } } } else { //免费用户 a_key, _ := (*o_entniche)["a_key"].([]interface{}) if len(a_key) > 0 { for _, v := range a_key { if keyData["未分类"] != nil { keyData["未分类"] = append(keyData["未分类"], v) } else { keyData["未分类"] = []interface{}{v} } } } } if spqp.PositionType == 1 && s.ModuleFlag != SubFreeFlag { //1、mysql entniche_user_rule表中获取自己的分发规则id data := IC.MainMysql.SelectBySql(`SELECT rule_id FROM entniche_user_rule a INNER JOIN entniche_department b ON a.dept_id = b.id AND a.user_id =? ORDER BY b.pid LIMIT 1 `, spqp.EntUserId) if data == nil || len(*data) == 0 { return MapToarr(keyData) } ruleId := common.ObjToString((*data)[0]["rule_id"]) //3、entniche_distribute表,查询条件:{_id:ObjectId(1结果中的分发规则id),i_status:0},取 o_entniche.a_items,这个查到的是分类名称,然后到上面1的结果中获取这个分类下的词 res, _ := IC.Mgo.FindById("entniche_distribute", ruleId, nil) if res == nil || len(*res) == 0 { return MapToarr(keyData) } entItem := (*res)["a_items"].([]interface{}) if (*res)["a_items"] == nil { return MapToarr(keyData) } //2、entniche_rule表, 企业订阅关键词查询条件: {i_entid:123,i_deptid:0},取 o_entniche.a_items deptid := common.Int64All((*res)["i_deptid"]) ruleMap := map[string]interface{}{ "i_entid": common.Int64All(spqp.EntId), } if deptid == 0 { ruleMap["i_deptid"] = map[string]interface{}{"$exists": false} ruleMap["i_userid"] = map[string]interface{}{"$exists": false} } else { ruleMap["i_deptid"] = deptid } res_, _ := IC.Mgo.FindOneByField("entniche_rule", ruleMap, `{"o_entniche":1}`) o_entniche := &map[string]interface{}{} if res_ != nil { o_entniche = common.ObjToMap((*res_)["o_entniche"]) } entnicheRule := map[string][]interface{}{} if (*o_entniche)["a_items"] != nil { a_item := common.ObjArrToMapArr((*o_entniche)["a_items"].([]interface{})) for _, v := range a_item { if v["a_key"] != nil { a_key_arr := v["a_key"].([]interface{}) entnicheRule[common.InterfaceToStr(v["s_item"])] = a_key_arr } } } for _, value := range entItem { v := common.InterfaceToStr(value) if entnicheRule[v] != nil { if keyData[v] != nil { //第一次搜索存在 //去重 keyData[v] = MergeArray(keyData[v], entnicheRule[v]) } else { //第一次搜索不存在 keyData[v] = entnicheRule[v] } } } } } return MapToarr(keyData) } // 关键词处理 func KeyHandle(a_items map[string]interface{}) []interface{} { keyArr := []interface{}{} if a_items["a_key"] != nil { a_key_arr := common.ObjArrToMapArr(a_items["a_key"].([]interface{})) for _, vv := range a_key_arr { for _, v := range vv["key"].([]interface{}) { keyArr = append(keyArr, v) } } } return keyArr } func MapToarr(data map[string][]interface{}) []*bxsubscribe.KeyItems { result := []*bxsubscribe.KeyItems{} for k, v := range data { keyArr := []*bxsubscribe.Key{} for _, m := range common.ObjArrToMapArr(v) { keys := &bxsubscribe.Key{} if m["notkey"] != nil { keys.Notkey = common.ObjArrToStringArr(m["notkey"].([]interface{})) } if m["key"] != nil { keys.Key = common.ObjArrToStringArr(m["key"].([]interface{})) } if m["matchway"] != nil { keys.Matchway = common.Int64All(m["matchway"]) } if m["appendkey"] != nil { keys.Appendkey = common.ObjArrToStringArr(m["appendkey"].([]interface{})) } keyArr = append(keyArr, keys) } result = append(result, &bxsubscribe.KeyItems{ AKey: keyArr, SItem: k, }) } return result } func MergeArray(dest []interface{}, src []interface{}) (result []interface{}) { data := map[string]interface{}{} for _, v := range common.ObjArrToMapArr(dest) { notkey := "" key := "" matchway := "" appendkey := "" if v["notkey"] != nil { otkeyArr := common.ObjArrToStringArr(v["notkey"].([]interface{})) for _, keyV := range otkeyArr { if common.InterfaceToStr(keyV) != "" { notkey += fmt.Sprintf(",%s", common.InterfaceToStr(keyV)) } } } if v["key"] != nil { keyArr := common.ObjArrToStringArr(v["key"].([]interface{})) for _, keyV := range keyArr { if common.InterfaceToStr(keyV) != "" { key += fmt.Sprintf(",%s", common.InterfaceToStr(keyV)) } } } if v["matchway"] != nil { matchway = common.InterfaceToStr(v["matchway"]) } if v["appendkey"] != nil { appendkeyArr := common.ObjArrToStringArr(v["appendkey"].([]interface{})) for _, keyV := range appendkeyArr { if common.InterfaceToStr(keyV) != "" { appendkey += fmt.Sprintf(",%s", common.InterfaceToStr(keyV)) } } } k := fmt.Sprintf("%s_____%s_____%s_____%s", notkey, key, matchway, appendkey) data[k] = v } for _, v := range common.ObjArrToMapArr(src) { notkey := "" key := "" matchway := "" appendkey := "" if v["notkey"] != nil { otkeyArr := common.ObjArrToStringArr(v["notkey"].([]interface{})) for _, keyV := range otkeyArr { if common.InterfaceToStr(keyV) != "" { notkey += fmt.Sprintf(",%s", common.InterfaceToStr(keyV)) } } } if v["key"] != nil { keyArr := common.ObjArrToStringArr(v["key"].([]interface{})) for _, keyV := range keyArr { if common.InterfaceToStr(keyV) != "" { key += fmt.Sprintf(",%s", common.InterfaceToStr(keyV)) } } } if v["matchway"] != nil { matchway = common.InterfaceToStr(v["matchway"]) } if v["appendkey"] != nil { appendkeyArr := common.ObjArrToStringArr(v["appendkey"].([]interface{})) for _, keyV := range appendkeyArr { if common.InterfaceToStr(keyV) != "" { appendkey += fmt.Sprintf(",%s", common.InterfaceToStr(keyV)) } } } k := fmt.Sprintf("%s_____%s_____%s_____%s", notkey, key, matchway, appendkey) data[k] = v } for _, v := range data { result = append(result, v) } return } func (s *subscribePush) ItemToKey(in *SubPushQueryParam) string { moduleFlag := s.ModuleFlag s.ModuleFlag = in.UserType spqp := KeyParam{ UserId: in.UserId, EntUserId: in.EntUserId, DeptId: in.DeptId, NewUserId: in.NewUserId, IsEnt: in.IsEnt, EntId: in.EntId, PositionType: in.PositionType, } //所有关键词获取 keyItemsArr := s.Keys(&spqp) s.ModuleFlag = moduleFlag keyArr := []string{} if len(keyItemsArr) > 0 { for _, k1 := range keyItemsArr { for _, k2 := range strings.Split(in.Item, ",") { if k1.SItem == k2 { if len(k1.AKey) > 0 { for _, k3 := range k1.AKey { key := "" if len(k3.Key) > 0 { key = strings.Join(k3.Key, " ") } if len(k3.Appendkey) > 0 { if key != "" { key += " " + strings.Join(k3.Appendkey, " ") } else { key = strings.Join(k3.Appendkey, " ") } } if k3.Matchway == 1 { //模糊处理 key = strings.ReplaceAll(key, " ", ",") } else { //精准处理 key = strings.ReplaceAll(key, " ", "+") } keyArr = append(keyArr, key) } } } } } } return strings.Join(keyArr, ",") } func (s *SubPushQueryParam) ExportPushFormat() (ids, keyWords []string) { if len(s.SelectInfoIds) > 0 { for ik, id := range s.SelectInfoIds { if xid := util.DecodeId(id); len(xid) > 0 { ids = append(ids, xid) if len(s.SelectKeys) > ik { keyWords = append(keyWords, strings.ReplaceAll(s.SelectKeys[ik], " ", ",")) } else { keyWords = append(keyWords, "") } } } } return }