package model import ( "app.yhyue.com/moapp/jybase/redis" "encoding/json" "fmt" IC "jyBXBuyer/rpc/init" "jyBXBuyer/rpc/type/bxbuyer" "log" "strconv" "strings" "sync" "time" MC "app.yhyue.com/moapp/jybase/common" "app.yhyue.com/moapp/jybase/encrypt" elastic "app.yhyue.com/moapp/jybase/es" "github.com/zeromicro/go-zero/core/logx" ) const ( HasContact = 1 // 采购单位是否有联系方式筛选项 1-有联系方式 NoContact = 2 // 无联系方式 ) type BScope struct { Keyword []string `json:"keyword"` AdditionalWords []string `json:"additionalWords"` ExcludedWords []string `json:"excludedWords"` } type supplyDataStruct struct { ProjectCount int64 BidCount int64 BidAmountCount float32 ContactCount int64 } // 获取采购单位查询query func BuyerListQuery(in *bxbuyer.BuyerListReq) (qstr string, CountQstr string) { query := `{%s "query":{"bool":{"must":[%s],"must_not": [{"term": {"buyer_name": ""}}],"should":[%s],"minimum_should_match": %d}} %s}` //21.1.20 为和画像保持一致 数据组要求 budget 改成 bidamount query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}` sort := "" bools := []string{} musts := []string{} musts_should := []string{} //省份 if len(in.Province) > 0 { musts_should = append(musts_should, fmt.Sprintf(`{"terms":{"province":["%s"]}}`, strings.Join(in.Province, "\",\""))) } //城市 if len(in.City) > 0 { musts_should = append(musts_should, fmt.Sprintf(`{"terms":{"city":["%s"]}}`, strings.Join(in.City, "\",\""))) } if len(musts_should) > 0 { musts = append(musts, fmt.Sprintf(query_bool_should, strings.Join(musts_should, ","))) } //采购单位名称 if in.BuyerName != "" { entNameQuery := fmt.Sprintf(`{"multi_match": {"query": "%s","type": "phrase", "fields": ["name"]}}`, in.BuyerName) musts = append(musts, entNameQuery) } else { sort = `,"sort":[{"updatetime":"desc"}]` // 仅无关键词时再 } //采购单位类型 buyerclass := in.BuyerClass if len(buyerclass) > 0 { Buyerclass := `{"terms":{"buyerclass":[` for k, v := range buyerclass { if k > 0 { Buyerclass += `,` } Buyerclass += `"` + v + `"` } Buyerclass += `]}}` musts = append(musts, Buyerclass) } // 采购单位联系方式 0-不限 1-有联系人 2-无联系人 if in.IsContact != 0 { isContact := MC.If(in.IsContact == int64(HasContact), true, false) isContactStr := `{"term":{"is_contact":` + fmt.Sprint(isContact) + `}}` musts = append(musts, isContactStr) } boolsNum := 0 qstr = fmt.Sprintf(query, fmt.Sprintf(`"from":%d,"size": %d,`, (in.PageNum-1)*in.PageSize, in.PageSize), strings.Join(musts, ","), strings.Join(bools, ","), boolsNum, sort) CountQstr = fmt.Sprintf(query, "", strings.Join(musts, ","), strings.Join(bools, ","), boolsNum, "") return } // 采购单位补充采购规模、项目数量、招标动态数量 func SupplyDataQuery(buyerList []string) (query string) { // 查近两年的数据 因为bigmember BuyerMiniPortrait 查的默认是两年 q := `{"size":0,"query": { "bool": { "must": [ {"terms": { "buyer": ["` + strings.Join(buyerList, "\",\"") + `"] }},{"range": {"jgtime": {"gte": %d,"lt": %d} }} ]}}, "aggs": { "buyerBuckets": {"terms": {"field": "buyer" },"aggs": {"bidAmountCount": {"sum": {"field": "bidamount"}}}}}}` start, end := getTimeRange() return fmt.Sprintf(q, start.Unix(), end.Unix()) } func getTimeRange() (st, et time.Time) { now := time.Now() eYear := now.Year() sYear := now.Year() - 2 //返回默认时间 sTimeStamp := time.Date(sYear, 1, 1, 0, 0, 0, 0, time.Local) eTimeStamp := time.Date(eYear, now.Month(), now.Day(), now.Hour(), now.Minute(), 0, 0, time.Local) return sTimeStamp, eTimeStamp } const ( P_INDEX = "projectset" P_TYPE = "projectset" P_redis_time = 7 * 24 * 60 * 60 //redis存7天 P_redis_key = "buyerListCache" // 存缓存 100条数据 BuyerIndex = "buyer" // 采购单位index BuyerType = "buyer" biddingIndex = "bidding" biddingType = "bidding" BuyerSupplyInfoRedisKey = "BuyerSupplyInfo_%s" // 采购单位补充信息缓存 BuyerSupplyInfoRedisTime = 2 * 60 * 60 // 采购单位补充信息缓存时间 一个小时 BuyerProjectInfoRedisKey = "BuyerProjectInfo_%s" // 采购单位补充项目信息缓存Key (项目数量采购规模) BuyerProjectInfoRedisTime = 24 * 60 * 60 // 采购单位补充项目信息缓存时间 ) // GetBuyerList 查询采购单位列表 func GetBuyerList(qstr string, CountQuery string, isCache bool) (buyerNames []string, resp *bxbuyer.BuyerListResp) { t1 := time.Now() total := elastic.Count(BuyerIndex, BuyerType, CountQuery) // 总数 logx.Info("耗时1:", time.Since(t1)) resp = &bxbuyer.BuyerListResp{ Data: &bxbuyer.BuyerData{ Count: total, List: []*bxbuyer.BuyerList{}, }, } if total == 0 { return } start := time.Now() rs := elastic.Get(BuyerIndex, BuyerType, qstr) // 采购单位列表 logx.Info("采购单位列表 es get查询耗时", time.Since(start)) if rs == nil || len(*rs) == 0 { return } for i := 0; i < len(*rs); i++ { tmp := &bxbuyer.BuyerList{ SeoId: MC.ObjToString((*rs)[i]["seo_id"]), Buyer: MC.ObjToString((*rs)[i]["name"]), Province: MC.ObjToString((*rs)[i]["province"]), City: MC.ObjToString((*rs)[i]["city"]), BuyerClass: MC.ObjToString((*rs)[i]["buyerclass"]), } buyerNames = append(buyerNames, tmp.Buyer) resp.Data.List = append(resp.Data.List, tmp) } logx.Info("耗时;", time.Since(t1).Seconds(), "秒--", time.Since(t1).Microseconds()) return } // BuyerListRedisCache 空搜索 1.查询项目数量最多的前200个 2.然后 再查buyer里确认数据有效 100个 3.项目数量和采购规模单独存缓存 1天 // // func BuyerListRedisCache(query string, in *bxbuyer.BuyerListReq) (buyerNames []string, resp *bxbuyer.BuyerListResp) { // //获取缓存数据 // resp = &bxbuyer.BuyerListResp{ // Data: &bxbuyer.BuyerData{ // List: []*bxbuyer.BuyerList{}, // }, // } // t1 := time.Now() // logx.Info("耗时1:", time.Since(t1)) // aggs := GetAggs(P_INDEX, P_TYPE, query) // logx.Info("查询语句:", query) // logx.Info("BuyerListRedisCache:", time.Since(t1)) // type BuyerAggStruct struct { // Buckets []struct { // Key string `json:"key,omitempty"` // Doc_count int64 `json:"doc_count,omitempty"` // BidAmountCount struct { // Value float32 `json:"value,omitempty"` // } `json:"bidAmountCount"` // } `json:"buckets"` // } // var buyerBuckets = BuyerAggStruct{} // saveBuyerList := []*bxbuyer.BuyerList{} //100条数据 最后存起来 // // 处理成map 用于后面格式化数据 // if aggs == nil || aggs["buyerBuckets"] == nil { // return // } // bs, err := aggs["buyerBuckets"].MarshalJSON() // if err != nil { // resp.ErrCode = -1 // resp.ErrMsg = "获取数据异常" // return // } // if len(bs) == 0 { // resp.ErrMsg = "暂无数据" // return // } // err = json.Unmarshal(bs, &buyerBuckets) // if err != nil || len(buyerBuckets.Buckets) == 0 { // resp.ErrMsg = "暂无数据" // return // } // for i := 0; i < len(buyerBuckets.Buckets); i++ { // if len(saveBuyerList) == int(IC.C.BuyerSearchLimit) { // break // } // // 查buyer 确认数据存在 补充 buyerclass 省份 城市信息 // rs := GetBuyer(buyerBuckets.Buckets[i].Key) // if rs != nil && len(*rs) > 0 { // 存在 则追加 // tmpBuyerInfo := (*rs)[0] // buyerInfo := &bxbuyer.BuyerList{ // Buyer: buyerBuckets.Buckets[i].Key, // Province: MC.ObjToString(tmpBuyerInfo["province"]), // City: MC.ObjToString(tmpBuyerInfo["city"]), // BuyerClass: MC.ObjToString(tmpBuyerInfo["buyerclass"]), // } // saveBuyerList = append(saveBuyerList, buyerInfo) // buyerNames = append(buyerNames, buyerInfo.Buyer) // // 项目数量和采购规模存缓存 1天 // projectCacheData := supplyDataStruct{ // ProjectCount: buyerBuckets.Buckets[i].Doc_count, // BidAmountCount: buyerBuckets.Buckets[i].BidAmountCount.Value, // } // go func(buyer string, data supplyDataStruct) { // b, err := json.Marshal(data) // if err == nil { // redis.PutBytes("other", fmt.Sprintf(BuyerProjectInfoRedisKey, buyer), &b, BuyerProjectInfoRedisTime+GetRand(60)) // } // }(buyerBuckets.Buckets[i].Key, projectCacheData) // // } // } // if len(saveBuyerList) > 0 { // // 100 列表存redis 7天 // go func(data []*bxbuyer.BuyerList) { // b, err := json.Marshal(data) // if err == nil { // redis.PutBytes("other", fmt.Sprintf(P_redis_key), &b, P_redis_time) // } // }(saveBuyerList) // } else { // return // } // // // 根据页码返回数据 // start := in.PageSize * (in.PageNum - 1) // end := in.PageSize * in.PageNum // resp.Data.Count = int64(len(saveBuyerList)) // if end > int64(len(saveBuyerList)-1) { // end = int64(len(saveBuyerList) - 1) // } // resp.Data.List = saveBuyerList[start:end] // return // } func BuyerListRedisCache(query string, in *bxbuyer.BuyerListReq) (buyerNames []string, resp *bxbuyer.BuyerListResp) { //获取缓存数据 resp = &bxbuyer.BuyerListResp{ Data: &bxbuyer.BuyerData{ List: []*bxbuyer.BuyerList{}, }, } t1 := time.Now() rs := elastic.Get(BuyerIndex, BuyerType, query) // 采购单位列表 logx.Info("空搜索采购单位列表 es get查询耗时", time.Since(t1)) if rs == nil || len(*rs) == 0 { return } saveBuyerList := []*bxbuyer.BuyerList{} //最后缓存起来 for i := 0; i < len(*rs); i++ { tmp := &bxbuyer.BuyerList{ SeoId: MC.ObjToString((*rs)[i]["seo_id"]), Buyer: MC.ObjToString((*rs)[i]["name"]), Province: MC.ObjToString((*rs)[i]["province"]), City: MC.ObjToString((*rs)[i]["city"]), BuyerClass: MC.ObjToString((*rs)[i]["buyerclass"]), } buyerNames = append(buyerNames, tmp.Buyer) saveBuyerList = append(saveBuyerList, tmp) } if len(saveBuyerList) > 0 { // 100 列表存redis 7天 go func(data []*bxbuyer.BuyerList) { b, err := json.Marshal(data) if err == nil { redis.PutBytes("other", fmt.Sprintf(P_redis_key), &b, P_redis_time) } }(saveBuyerList) } else { return } // 根据页码返回数据 start := in.PageSize * (in.PageNum - 1) end := in.PageSize * in.PageNum resp.Data.Count = int64(len(saveBuyerList)) if end > int64(len(saveBuyerList)) { end = int64(len(saveBuyerList)) } resp.Data.List = saveBuyerList[start:end] logx.Info("空搜索整体耗时;", time.Since(t1).Seconds(), "秒--", time.Since(t1).Microseconds()) return } // GetBuyer 查采购单位表 确认采购单位存在 func GetBuyer(buyerName string) *[]map[string]interface{} { q := `{"size":1,"_source":["buyerclass","province","city"],"query":{"bool":{"must":[{"term":{"buyer_name":"%s"}}]}}}` rs := elastic.Get(BuyerIndex, BuyerType, fmt.Sprintf(q, buyerName)) return rs } // SupplyFollowInfo 补充是否关注信息 func SupplyFollowInfo(in *bxbuyer.BuyerListReq, buyerNames []string, resp *bxbuyer.BuyerListResp) *bxbuyer.BuyerListResp { //省份和城市 是否查询已关注信息 是否查询已领取信息 //企业信用库qyxy_std 和es buyer库 查询省份和城市 //客户领取 t2 := time.Now() isRws := map[string]string{} if in.IsCheckReceive { isRws = IsReceived(buyerNames, in.EntUserId) } logx.Info("客户领取耗时:", time.Since(t2)) //客户关注 t3 := time.Now() isFws := map[string]bool{} entIdInt, _ := strconv.Atoi(in.EntId) powerCheck := IC.Middleground.PowerCheckCenter.Check(in.AppId, in.MgoUserId, in.NewUserId, in.AccountId, int64(entIdInt), in.PositionType, in.PositionId) if powerCheck != nil && (*powerCheck).Member.Status > 0 && (*powerCheck).Member.Pid != "" { in.UserId = (*powerCheck).Member.Pid } if in.IsCheckFollow { isFws = IsFollowd(buyerNames, in.UserId) } logx.Info("采购单位关注耗时:", time.Since(t3)) for _, bv := range resp.Data.List { if in.IsCheckReceive { if isRws[bv.Buyer] != "" { bv.IsReceived = true bv.RecId = isRws[bv.Buyer] } } if in.IsCheckFollow { if isFws[bv.Buyer] { bv.IsFollowed = true } } } return resp } // SupplyBuyerListData 补充字段 招标动态数量 项目数量 历史联系人数量 采购单位规模 func SupplyBuyerListData(buyerNames []string, resp *bxbuyer.BuyerListResp) *bxbuyer.BuyerListResp { //buyerNames 是否存在缓存 数据 //如果没有 放到一个新的 []string needSearchBuyer := []string{} cacheMap := map[string]supplyDataStruct{} for i := 0; i < len(buyerNames); i++ { bs, err := redis.GetBytes("other", fmt.Sprintf(BuyerSupplyInfoRedisKey, buyerNames[i])) if err == nil && bs != nil && len(*bs) > 0 { tmp := supplyDataStruct{} if err := json.Unmarshal(*bs, &tmp); err == nil { cacheMap[buyerNames[i]] = tmp // 拿到缓存的数据 } else { needSearchBuyer = append(needSearchBuyer, buyerNames[i]) // 没有缓存的数据 后边再查 } } else { needSearchBuyer = append(needSearchBuyer, buyerNames[i]) // 没有缓存的数据 后边再查 } } start := time.Now() t1 := time.Now() buyerMap := map[string]supplyDataStruct{} // 聚合的数据 if len(needSearchBuyer) > 0 { query := SupplyDataQuery(needSearchBuyer) // 项目数量、采购规模 // 聚合查 aggs := GetAggs(P_INDEX, P_TYPE, query) logx.Info("查询语句:", query) logx.Info("项目数量采购规模查询耗时:", time.Since(t1)) type BuyerAggStruct struct { Buckets []struct { Key string `json:"key,omitempty"` Doc_count int64 `json:"doc_count,omitempty"` BidAmountCount struct { Value float32 `json:"value,omitempty"` } `json:"bidAmountCount"` } `json:"buckets"` } var buyerBuckets = BuyerAggStruct{} // 处理成map 用于后面格式化数据 if aggs != nil && aggs["buyerBuckets"] != nil { bs, err := aggs["buyerBuckets"].MarshalJSON() if err != nil { resp.ErrCode = -1 resp.ErrMsg = "获取数据异常" } else { if len(bs) == 0 { resp.ErrMsg = "暂无数据" } else { err := json.Unmarshal(bs, &buyerBuckets) logx.Info(err) if len(buyerBuckets.Buckets) > 0 { for _, v := range buyerBuckets.Buckets { buyerMap[v.Key] = supplyDataStruct{ BidAmountCount: v.BidAmountCount.Value, ProjectCount: v.Doc_count, } } } } } } } ch := make(chan int, 10) ch2 := make(chan int, 10) wg := &sync.WaitGroup{} for i := 0; i < len(resp.Data.List); i++ { buyer := resp.Data.List[i].Buyer // 先查缓存 if cacheData, ok := cacheMap[buyer]; ok { resp.Data.List[i].BidAmountCount = cacheData.BidAmountCount resp.Data.List[i].ProjectCount = cacheData.ProjectCount resp.Data.List[i].BiddingCount = cacheData.BidCount resp.Data.List[i].ContactCount = cacheData.ContactCount continue } // 缓存里没有的再查数据补充 if supplyData, ok := buyerMap[buyer]; ok { resp.Data.List[i].BidAmountCount = supplyData.BidAmountCount resp.Data.List[i].ProjectCount = supplyData.ProjectCount } ch2 <- 1 wg.Add(1) go func(list *bxbuyer.BuyerList, buyer string) { defer func() { <-ch2 wg.Done() }() list.ContactCount = GetProjectContactCount(buyer) // 补充联系人字段 }(resp.Data.List[i], buyer) ch <- 1 wg.Add(1) go func(list *bxbuyer.BuyerList, buyer string) { defer func() { <-ch wg.Done() }() list.BiddingCount = GetNewBiddingCount(buyer) }(resp.Data.List[i], buyer) } wg.Wait() logx.Info("SupplyBuyerListData 整体耗时:", time.Since(start)) //得到所有数据,包括 redis里的,再存一下 go func(respList []*bxbuyer.BuyerList) { for i := 0; i < len(respList); i++ { tmp := supplyDataStruct{ ContactCount: respList[i].ContactCount, BidCount: respList[i].BiddingCount, ProjectCount: respList[i].ProjectCount, BidAmountCount: respList[i].BidAmountCount, } // 存redis b, err := json.Marshal(tmp) if err == nil { redis.PutBytes("other", fmt.Sprintf(BuyerSupplyInfoRedisKey, respList[i].Buyer), &b, BuyerSupplyInfoRedisTime+GetRand(60)) } } }(resp.Data.List) return resp } // 获取项目数量 采购单位规模 func getBuyerProjectCache(buyer string) (rs *supplyDataStruct) { bs, err := redis.GetBytes("other", fmt.Sprintf(BuyerProjectInfoRedisKey, buyer)) if err == nil && bs != nil && len(*bs) > 0 { if err := json.Unmarshal(*bs, &rs); err != nil { logx.Info("获取redis缓存,序列化异常") } else { return rs } } return } // BuyerSupplyInfo 补充字段 func BuyerSupplyInfo(buyerNames []string) (resp *bxbuyer.BuyerSupplyResp) { resp = &bxbuyer.BuyerSupplyResp{} start := time.Now() // buyerNames //buyerNames 是否存在缓存 数据 //如果没有 放到一个新的 []string needSearchBuyer := []string{} cacheMap := map[string]supplyDataStruct{} buyerMap := map[string]supplyDataStruct{} for i := 0; i < len(buyerNames); i++ { bs, err := redis.GetBytes("other", fmt.Sprintf(BuyerSupplyInfoRedisKey, buyerNames[i])) if err == nil && bs != nil && len(*bs) > 0 { tmp := supplyDataStruct{} if err := json.Unmarshal(*bs, &tmp); err == nil { cacheMap[buyerNames[i]] = tmp // 拿到缓存的数据 采购规模 项目数量 联系人数量 招标动态数量 } else { // 查缓存 cacheProject := getBuyerProjectCache(buyerNames[i]) if cacheProject != nil { buyerMap[buyerNames[i]] = *cacheProject } else { needSearchBuyer = append(needSearchBuyer, buyerNames[i]) // 没有缓存的数据 后边再查采购规模和项目数量 } } } else { // 查缓存 cacheProject := getBuyerProjectCache(buyerNames[i]) if cacheProject != nil { buyerMap[buyerNames[i]] = *cacheProject } else { needSearchBuyer = append(needSearchBuyer, buyerNames[i]) // 没有缓存的数据 后边再查采购规模和项目数量 } } } if len(needSearchBuyer) > 0 { t1 := time.Now() query := SupplyDataQuery(buyerNames) // 项目数量、采购规模 // 聚合查 aggs := GetAggs(P_INDEX, P_TYPE, query) logx.Info("查询语句:", query) logx.Info("项目数量采购规模查询耗时:", time.Since(t1)) type BuyerAggStruct struct { Buckets []struct { Key string `json:"key,omitempty"` Doc_count int64 `json:"doc_count,omitempty"` BidAmountCount struct { Value float32 `json:"value,omitempty"` } `json:"bidAmountCount"` } `json:"buckets"` } var buyerBuckets = BuyerAggStruct{} // 处理成map 用于后面格式化数据 if aggs != nil && aggs["buyerBuckets"] != nil { bs, err := aggs["buyerBuckets"].MarshalJSON() if err != nil { resp.ErrCode = -1 resp.ErrMsg = "获取数据异常" } else { if len(bs) == 0 { resp.ErrMsg = "暂无数据" } else { err := json.Unmarshal(bs, &buyerBuckets) logx.Info(err) if len(buyerBuckets.Buckets) > 0 { for _, v := range buyerBuckets.Buckets { buyerMap[v.Key] = supplyDataStruct{ BidAmountCount: v.BidAmountCount.Value, ProjectCount: v.Doc_count, } } } } } } } ch := make(chan int, 10) ch2 := make(chan int, 10) wg := &sync.WaitGroup{} for i := 0; i < len(buyerNames); i++ { buyer := buyerNames[i] resp.Data = append(resp.Data, &bxbuyer.SupplyData{ Buyer: buyer, }) // 先查缓存 if cacheData, ok := cacheMap[buyer]; ok { resp.Data[i].BidAmountCount = cacheData.BidAmountCount resp.Data[i].ProjectCount = cacheData.ProjectCount resp.Data[i].BiddingCount = cacheData.BidCount resp.Data[i].ContactCount = cacheData.ContactCount continue } // 缓存里没有的再取查数据补充 // 补充字段 if supplyData, ok := buyerMap[buyer]; ok { resp.Data[i].BidAmountCount = supplyData.BidAmountCount resp.Data[i].ProjectCount = supplyData.ProjectCount } ch2 <- 1 wg.Add(1) go func(list *bxbuyer.SupplyData, buyer string) { defer func() { <-ch2 wg.Done() }() list.ContactCount = GetProjectContactCount(buyer) // 补充联系人字段 }(resp.Data[i], buyer) ch <- 1 wg.Add(1) go func(list *bxbuyer.SupplyData, buyer string) { defer func() { <-ch wg.Done() }() list.BiddingCount = GetNewBiddingCount(buyer) }(resp.Data[i], buyer) } wg.Wait() logx.Info(" 整体耗时:", time.Since(start)) //得到所有数据,包括 redis里的,再存一下 go func(respList []*bxbuyer.SupplyData) { for i := 0; i < len(respList); i++ { tmp := supplyDataStruct{ ContactCount: respList[i].ContactCount, BidCount: respList[i].BiddingCount, ProjectCount: respList[i].ProjectCount, BidAmountCount: respList[i].BidAmountCount, } // 存redis b, err := json.Marshal(tmp) if err == nil { redis.PutBytes("other", fmt.Sprintf(BuyerSupplyInfoRedisKey, respList[i].Buyer), &b, BuyerSupplyInfoRedisTime+GetRand(60)) } } }(resp.Data) return } func GetProjectContactCount(buyerName string) int64 { start := time.Now() list := []string{} searchSql := fmt.Sprintf(`{"query":{"bool":{"filter":[{"term":{"buyer":"%s"}}]}},"_source":["list.buyerperson","list.buyertel"],"sort":[{"zbtime":"desc"}],"size":500}`, buyerName) projectList := elastic.Get(P_INDEX, P_TYPE, searchSql) logx.Info("GetProjectContactCount esget 耗时", time.Since(start), searchSql) if projectList == nil || len(*projectList) == 0 { return 0 } //根据联系人和联系方式展示 //多个项目同一个联系人;只展示最新项目 //一个项目多个联系人;拆分展示 repeatContacts := map[string]bool{} for _, rowData := range *projectList { mapList, ok := rowData["list"].([]interface{}) if !ok || len(mapList) == 0 { continue } for i := len(mapList) - 1; i >= 0; i-- { thisMsg, ok := mapList[i].(map[string]interface{}) if !ok || len(thisMsg) == 0 { continue } thisPhone, thisPerson := "", "" if thisPhone, _ = thisMsg["buyertel"].(string); thisPhone != "" { thisPerson, _ = thisMsg["buyerperson"].(string) } if thisPhone == "" { //联系人为空则不展示 dev4.7.3联系人为空展示此记录 continue } //一个项目只选取一条公告联系人 thisAddPerson := false //名字中多个联系人拆分 for _, name := range strings.Split(thisPerson, ",") { thisName := strings.TrimSpace(name) if thisName == "" && thisAddPerson { //联系人为空则不展示 continue } thisAddPerson = true repeatKey := fmt.Sprintf("%s_%s", thisName, thisPhone) if repeatContacts[repeatKey] { continue } repeatContacts[repeatKey] = true list = append(list, thisPhone) } if thisAddPerson { break } } } logx.Info("GetProjectContactCount 单次耗时:", time.Since(start)) return int64(len(list)) } func GetNewBiddingCount(buyer string) int64 { start := time.Now() if buyer == "" { return 0 } var mustQuery []string st, et := getTimeRange() mustQuery = append(mustQuery, fmt.Sprintf(`{"range":{"publishtime":{"gte":%d,"lte":%d}}}`, st.Unix(), et.Unix())) mustQuery = append(mustQuery, fmt.Sprintf(`{"term": {"buyer": "%s"}}`, buyer)) aa := fmt.Sprintf(`{"query":{"bool":{"must":[%s]}}}`, strings.Join(mustQuery, ",")) count := elastic.Count(biddingIndex, biddingType, aa) logx.Info("GetNewBiddingCount 单次耗时:", buyer, time.Since(start)) return count } // 聚合查询 func GetAggs(index, itype, query string) (aggs map[string]json.RawMessage) { aggs, _, _ = elastic.GetAggs(index, itype, query) return } type buyerInfo struct { Province string City string } // 潜在客户 获取省份和城市 func GetBuyerInfo(buyerNames []string) (infoMap map[string]buyerInfo) { var buyerInfoQuery = `{"query": {"bool": {"must": [{"terms": {"%s": [%s]}}],"must_not": [],"should": []}},"from": 0,"size": 50,"sort": []}` query := fmt.Sprintf(buyerInfoQuery, "buyer_name", `"`+strings.Join(buyerNames, `","`)+`"`) list := *elastic.Get("buyer", "buyer", query) if list != nil { if len(list) > 0 { infoMap = map[string]buyerInfo{} for _, v := range list { infoMap[v["name"].(string)] = buyerInfo{ Province: MC.If(v["province"] != nil, MC.ObjToString(v["province"]), "").(string), City: MC.If(v["city"] != nil, MC.ObjToString(v["city"]), "").(string), } } } } else { logx.Info("采购单位获取地区信息异常") } return } var fc = "follow_customer" //关注客户表 // 采购单位是否作为客户已被关注 func IsFollowd(buyerNames []string, userId string) (isFws map[string]bool) { queryMap := map[string]interface{}{ "userId": userId, "name": map[string]interface{}{ "$in": buyerNames, }, } log.Println("IsFollowd query:", fc, queryMap) list, ok := IC.Mgo.Find(fc, queryMap, `{"_id":1}`, nil, false, -1, -1) if ok && len(*list) > 0 { isFws = map[string]bool{} for _, lv := range *list { if MC.ObjToString(lv["name"]) != "" { isFws[MC.ObjToString(lv["name"])] = true } } } else { logx.Info("采购单位是否已关注信息异常 or 未查到数据", ok) } return } var ( Entniche_customer = "entniche_customer" Entniche_user_customer = "entniche_user_customer" ) // 领取状态 func IsReceived(buyerNames []string, entUserId string) (isRws map[string]string) { //新加领取的客户id----保证领取的唯一性 aa := fmt.Sprintf("SELECT ecn.id, ecn.name FROM %s ecn,%s euu WHERE ecn.id = euu.customer_id AND euu.user_id =? AND ecn.`name` IN ('%s') AND (euu.source_type =1 or euu.source_type=4)", Entniche_customer, Entniche_user_customer, strings.Join(buyerNames, "','")) log.Println(aa) receInfos := IC.MainMysql.SelectBySql(fmt.Sprintf("SELECT ecn.id, ecn.name FROM %s ecn,%s euu WHERE ecn.id = euu.customer_id AND euu.user_id =? AND ecn.`name` IN ('%s') AND (euu.source_type =1 or euu.source_type=4)", Entniche_customer, Entniche_user_customer, strings.Join(buyerNames, "','")), entUserId) if receInfos != nil { if len(*receInfos) > 0 { isRws = map[string]string{} for _, rv := range *receInfos { if MC.ObjToString(rv["name"]) != "" && strconv.Itoa(MC.IntAll(rv["id"])) != "" { isRws[MC.ObjToString(rv["name"])] = encrypt.SE.Encode2HexByCheck(strconv.Itoa(MC.IntAll(rv["id"]))) } } } } else { logx.Info("采购单位是否已领取信息异常") } return } // 是否为空请求 func CheckEmpty(in *bxbuyer.BuyerListReq) bool { if in.BuyerName == "" && len(in.BuyerClass) == 0 && len(in.Province) == 0 && len(in.City) == 0 && in.IsContact == 0 { return true } return false } //缓存数据查询 // 获取采购单位查询query func BuyerListRedisCacheQuery() (qstr string) { qstr = `{"size":%d,"query":{"bool":{"must":[],"must_not":[{"term":{"buyer_name":""}}]}},"sort":[{"updatetime":"desc"}]}` return fmt.Sprintf(qstr, IC.C.BuyerSearchLimit) }