123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- package service
- import (
- MC "app.yhyue.com/moapp/jybase/common"
- "app.yhyue.com/moapp/jybase/encrypt"
- elastic "app.yhyue.com/moapp/jybase/es"
- "app.yhyue.com/moapp/jybase/redis"
- "app.yhyue.com/moapp/jypkg/common/src/qfw/util/jy"
- IC "bp.jydev.jianyu360.cn/BaseService/jyMicroservices/jyBXCore/rpc/init"
- "bp.jydev.jianyu360.cn/BaseService/jyMicroservices/jyBXCore/rpc/model/es"
- "bp.jydev.jianyu360.cn/BaseService/jyMicroservices/jyBXCore/rpc/type/bxcore"
- "bp.jydev.jianyu360.cn/BaseService/jyMicroservices/jyBXCore/rpc/util"
- "encoding/json"
- "fmt"
- "log"
- "strconv"
- "strings"
- "time"
- )
- type Purchase struct {
- AppId string ` json:"appId,omitempty"` //剑鱼默认10000
- UserId string ` json:"userId,omitempty"` //用户id
- Phone string ` json:"phone,omitempty"` //手机号
- BaseUserId int64 ` json:"baseUserId,omitempty"` //base_user_id 新用户id
- EntId int64 ` json:"entId,omitempty"` //企业id 没有企业 企业id=0
- EntUserId int64 ` json:"entUserId,omitempty"` //企业用户id 当前企业下的员工id 没有企业默认0
- AccountId int64 ` json:"accountId,omitempty"` //账户id
- EntAccountId int64 ` json:"entAccountId,omitempty"` //企业账户id
- PositionType int64 ` json:"positionType,omitempty"` //职位类型 0个人 1企业
- PositionId int64 ` json:"positionId,omitempty"` //职位id
- MgoUserId string ` json:"mgoUserId,omitempty"` //原userId
- PageNum int64 ` json:"pageNum,omitempty"` //当前页码
- PageSize int64 ` json:"pageSize,omitempty"` //每页数量
- PublishTime string ` json:"publishTime,omitempty"` //发布时间
- SelectType string ` json:"selectType,omitempty"` //搜索范围:
- DomainFirstType string ` json:"domainFirstType,omitempty"` //领域 一级
- DomainSecondType string ` json:"domainSecondType,omitempty"` //领域 二级
- DomainThirdType string ` json:"domainThirdType,omitempty"` //领域 三级
- DeadlineStatus int64 ` json:"deadlineStatus,omitempty"` //报名截止状态
- DeadlineTime string ` json:"deadlineTime,omitempty"` //报名截止时间
- DeadlineStart int64 ` json:"deadlineStart,omitempty"` //报名截止时间-开始
- DeadlineEnd int64 ` json:"deadlineEnd,omitempty"` //报名截止时间-结束
- DeliveryArea string ` json:"deliveryArea,omitempty"` //交付地点-省份
- DeliveryCity string ` json:"deliveryCity,omitempty"` //交付地点-城市
- DeliveryDistrict string ` json:"deliveryDistrict,omitempty"` //交付地点-县区
- ProjectArea string ` json:"projectArea,omitempty"` //项目地区-省份
- ProjectCity string ` json:"projectCity,omitempty"` //项目地区-城市
- ProjectDistrict string ` json:"projectDistrict,omitempty"` //项目地区-县区
- Industry string ` json:"industry,omitempty"` //行业
- FileExists int64 ` json:"fileExists,omitempty"` //是否有附件
- Publisher int64 ` json:"publisher,omitempty"` //发布者:可选:全部、用户发布:1、平台发布:2。
- KeyWords string ` json:"keyWords,omitempty"` //关键词:多个空格隔开(主)
- AdditionalWords string ` json:"additionalWords,omitempty"` //关键词:附加关键词(副:五组,每组最多15个字符)
- SearchMode int64 ` json:"searchMode,omitempty"` //搜索模式:0:精准搜索;1:模糊搜索
- WordsMode int64 ` json:"wordsMode,omitempty"` //搜索关键词模式;默认0:包含所有,1:包含任意
- UserAgent string ` json:"userAgent,omitempty"` //请求头信息
- Platform string ` json:"platform,omitempty"` //请求平台
- TipMsg string `json:"tipMsg"` //关键词提示信息
- HighlightWords string `json:"highlightWords"` //需要高亮的词,多个,号分割
- Total int64 `json:"total"` //数据总量
- }
- func NewPurchase(in *bxcore.PurchaseReq) *Purchase {
- baseUserId, _ := strconv.ParseInt(in.NewUserId, 10, 64)
- accountId, _ := strconv.ParseInt(in.AccountId, 10, 64)
- positionType, _ := strconv.ParseInt(in.PositionType, 10, 64)
- positionId, _ := strconv.ParseInt(in.PositionId, 10, 64)
- return &Purchase{
- AppId: in.AppId,
- UserId: in.UserId,
- Phone: in.Phone,
- BaseUserId: baseUserId,
- EntId: in.EntId,
- EntUserId: in.EntUserId,
- AccountId: accountId,
- EntAccountId: in.EntAccountId,
- PositionType: positionType,
- PositionId: positionId,
- MgoUserId: in.MgoUserId,
- PageNum: in.PageNum,
- PageSize: in.PageSize,
- PublishTime: in.PublishTime,
- SelectType: in.SelectType,
- DomainFirstType: in.DomainFirstType,
- DomainSecondType: in.DomainSecondType,
- DomainThirdType: in.DomainThirdType,
- DeadlineStatus: in.DeadlineStatus,
- DeadlineTime: in.DeadlineTime,
- DeliveryArea: in.DeliveryArea,
- DeliveryCity: in.DeliveryCity,
- DeliveryDistrict: in.DeliveryDistrict,
- ProjectArea: in.ProjectArea,
- ProjectCity: in.ProjectCity,
- ProjectDistrict: in.ProjectDistrict,
- Industry: in.Industry,
- FileExists: in.FileExists,
- Publisher: in.Publisher,
- KeyWords: in.KeyWords,
- AdditionalWords: in.AdditionalWords,
- SearchMode: in.SearchMode,
- WordsMode: in.WordsMode,
- UserAgent: in.UserAgent,
- Platform: in.Platform,
- }
- }
- // 格式化
- func (p *Purchase) PurchaseListFormat(res *[]map[string]interface{}) (list []*bxcore.PurchaseList) {
- for _, rv := range *res {
- id := MC.InterfaceToStr(rv["id"])
- list = append(list, &bxcore.PurchaseList{
- Id: encrypt.EncodeArticleId2ByCheck(id),
- Area: "",
- City: "",
- District: "",
- RegionUrl: "",
- BuyerClass: "",
- PublishTime: 0,
- FileExists: false,
- Title: "",
- Price: 0,
- Buyer: "",
- BuyerTel: "",
- DeadlineTime: "",
- DeliveryLoc: "",
- Industry: "",
- })
- }
- return
- }
- func (p *Purchase) PurchaseQuery() (query string) {
- var (
- wordsMusts, wordsShould, must, mustNot []string
- selectTypeArr = strings.Split(p.SelectType, ",")
- selectType = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
- )
- //发布时间
- if len(strings.Split(p.PublishTime, "-")) > 1 {
- var (
- timeQuery string
- startTime, endTime = strings.Split(p.PublishTime, "-")[0], strings.Split(p.PublishTime, "-")[1]
- )
- if startTime != "" || endTime != "" {
- timeQuery += `{"range":{"publishtime":{`
- if startTime != "" {
- timeQuery += `"gte":` + startTime
- }
- if startTime != "" && endTime != "" {
- timeQuery += `,`
- }
- if endTime != "" {
- timeQuery += `"lt":` + endTime
- }
- timeQuery += `}}}`
- }
- if timeQuery != "" {
- must = append(must, timeQuery)
- }
- }
- // 关键词
- if p.KeyWords != "" {
- var (
- keyWordsMusts []string
- )
- for _, v := range strings.Split(p.KeyWords, IC.C.JYKeyMark) {
- if elastic.ReplaceYH(v) == "" {
- continue
- }
- keyWordsMusts = append(keyWordsMusts, fmt.Sprintf(fmt.Sprintf(es.MultiMatch, "%s", selectType), elastic.ReplaceYH(v)))
- }
- //搜索关键词模式;默认0:包含所有,1:包含任意
- if p.WordsMode == 1 {
- wordsShould = append(wordsShould, fmt.Sprintf(elastic.NgramMust, strings.Join(keyWordsMusts, ",")))
- } else {
- wordsMusts = append(wordsMusts, keyWordsMusts...)
- }
- }
- //附加词
- if p.AdditionalWords != "" {
- for _, aws := range strings.Split(p.AdditionalWords, ",") {
- //多组附加词,每组间,号隔开。每组内如果关键词中间有空格,自动分词
- var (
- addWordsMusts []string
- )
- for _, v := range strings.Split(aws, IC.C.JYKeyMark) {
- if elastic.ReplaceYH(v) == "" {
- continue
- }
- addWordsStr := fmt.Sprintf(fmt.Sprintf(es.MultiMatch, "%s", selectType), elastic.ReplaceYH(v))
- if p.WordsMode == 0 {
- wordsMusts = append(wordsMusts, addWordsStr)
- } else {
- addWordsMusts = append(addWordsMusts, addWordsStr)
- }
- }
- //搜索关键词模式;默认0:包含所有,1:包含任意
- if len(addWordsMusts) > 0 {
- wordsShould = append(wordsShould, fmt.Sprintf(elastic.NgramMust, strings.Join(addWordsMusts, ",")))
- }
- }
- }
- //搜索关键词模式;默认0:包含所有,1:包含任意
- //包含任意一组
- if len(wordsShould) > 0 {
- must = append(must, fmt.Sprintf(es.QueryBoolShould, strings.Join(wordsShould, ",")))
- } else if len(wordsMusts) > 0 {
- must = append(must, fmt.Sprintf(elastic.NgramMust, strings.Join(wordsMusts, ",")))
- }
- //行业
- if p.Industry != "" {
- must = append(must, fmt.Sprintf(es.QueryBoolMustA, "s_subscopeclass", `"`+strings.ReplaceAll(p.Industry, ",", `","`)+`"`))
- }
- //附件
- if p.FileExists != 0 {
- switch p.FileExists {
- case 1: //有附件
- must = append(must, fmt.Sprintf(es.QueryBoolMustTermBool, "isValidFile", true))
- case -1: //无附件
- mustNot = append(mustNot, fmt.Sprintf(es.QueryBoolMustTermBool, "isValidFile", true))
- }
- }
- //项目地区
- var (
- areaQuery []string
- areaTerms = `{"terms":{"%s":["%s"]}}`
- )
- if p.ProjectArea != "" {
- areaQuery = append(areaQuery, fmt.Sprintf(areaTerms, "area", strings.ReplaceAll(p.ProjectArea, ",", "\",\"")))
- }
- if p.ProjectCity != "" {
- areaQuery = append(areaQuery, fmt.Sprintf(areaTerms, "city", strings.ReplaceAll(p.ProjectArea, ",", "\",\"")))
- }
- if p.ProjectDistrict != "" {
- for _, v := range strings.Split(p.ProjectDistrict, ",") {
- if len(strings.Split(v, "_")) > 1 {
- cityName := strings.Split(v, "_")[0]
- districtName := strings.Split(v, "_")[1]
- queryBoolMustAndDistrict := `{"bool":{"must":[{"terms":{"city":["%s"]}},{"terms":{"district":["%s"]}}]}}`
- areaQuery = append(areaQuery, fmt.Sprintf(queryBoolMustAndDistrict, cityName, districtName))
- }
- }
- }
- if len(areaQuery) > 0 {
- must = append(must, fmt.Sprintf(es.QueryBoolShould, strings.Join(areaQuery, ",")))
- }
- //交付地点
- areaQuery = []string{}
- if p.DeliveryArea != "" {
- areaQuery = append(areaQuery, fmt.Sprintf(areaTerms, "deliver_area", strings.ReplaceAll(p.DeliveryArea, ",", "\",\"")))
- }
- if p.DeliveryCity != "" {
- areaQuery = append(areaQuery, fmt.Sprintf(areaTerms, "deliver_city", strings.ReplaceAll(p.DeliveryCity, ",", "\",\"")))
- }
- if p.DeliveryDistrict != "" {
- for _, v := range strings.Split(p.DeliveryDistrict, ",") {
- if len(strings.Split(v, "_")) > 1 {
- cityName := strings.Split(v, "_")[0]
- districtName := strings.Split(v, "_")[1]
- queryBoolMustAndDistrict := `{"bool":{"must":[{"terms":{"deliver_city":["%s"]}},{"terms":{"deliver_district":["%s"]}}]}}`
- areaQuery = append(areaQuery, fmt.Sprintf(queryBoolMustAndDistrict, cityName, districtName))
- }
- }
- }
- if len(areaQuery) > 0 {
- must = append(must, fmt.Sprintf(es.QueryBoolShould, strings.Join(areaQuery, ",")))
- }
- //发布方式
- if p.Publisher > 0 {
- must = append(must, fmt.Sprintf(es.QueryBoolMustTerm, "public_type", fmt.Sprintf("%d", p.Publisher)))
- }
- //截止时间
- if p.DeadlineStart > 0 || p.DeadlineEnd > 0 {
- var timeQuery string
- timeQuery += `{"range":{"signendtime":{`
- if p.DeadlineStart > 0 {
- timeQuery += fmt.Sprintf(`"gte":%d`, p.DeadlineStart)
- }
- if p.DeadlineStart > 0 && p.DeadlineEnd > 0 {
- timeQuery += `,`
- }
- if p.DeadlineEnd > 0 {
- timeQuery += fmt.Sprintf(`"lt":%d`, p.DeadlineEnd)
- }
- timeQuery += `}}}`
- }
- //领域
- areaQuery = []string{}
- if p.DomainSecondType != "" {
- areaQuery = append(areaQuery, fmt.Sprintf(areaTerms, "domain_secondtype", strings.ReplaceAll(p.DomainSecondType, ",", "\",\"")))
- }
- if p.DomainThirdType != "" {
- areaQuery = append(areaQuery, fmt.Sprintf(areaTerms, "domain_thirdtype", strings.ReplaceAll(p.DomainThirdType, ",", "\",\"")))
- }
- if len(areaQuery) > 0 {
- must = append(must, fmt.Sprintf(es.QueryBoolShould, strings.Join(areaQuery, ",")))
- }
- //直采 采购信息 搜索
- query = fmt.Sprintf(query, strings.Join(must, ","), strings.Join(mustNot, ","))
- log.Println("zc-query:", query)
- return
- }
- func (p *Purchase) FindDataFromES() (total int64, list *[]map[string]interface{}, err error) {
- var (
- start = int((p.PageNum - 1) * p.PageSize)
- )
- biddingSearch := es.SearchByES{
- Index: es.PurchaseIndex,
- IType: es.PurchaseType,
- Query: p.PurchaseQuery(),
- FindFields: p.SelectType,
- Order: es.PurchaseSearchSort,
- Fields: es.PurchaseBaseField,
- Start: start,
- Limit: int(p.PageSize),
- Count: 0, //高亮正文数量
- HighLight: false, //是否高亮正文
- }
- total, list = biddingSearch.GetAllByNgramWithCount(es.LoginTypePay)
- fmt.Println(total, "-------------------", *list)
- p.Total = total
- total = int64(util.SearchPageSize * util.SearchMaxPageNum)
- if p.Total > total {
- p.Total = total
- }
- return
- }
- var (
- redisCode = "newother"
- purchaseCacheKey = "purchase_cache_data"
- purchaseCacheExpire = 4 * 60 * 60
- )
- func (p *Purchase) GetPurchaseData() (list []*bxcore.PurchaseList, err error) {
- var (
- res *[]map[string]interface{}
- )
- if p.IsEmptySearch() {
- //查缓存
- cacheBytes, err := redis.GetBytes(redisCode, purchaseCacheKey)
- start := int((p.PageNum - 1) * p.PageSize)
- pageSize := p.PageSize
- if err == nil && len(*cacheBytes) > start {
- end := int(p.PageNum * p.PageSize)
- if end > len(*cacheBytes) {
- end = len(*cacheBytes)
- }
- err = json.Unmarshal((*cacheBytes)[start:end], res)
- }
- if len(*res) == 0 {
- p.PageNum = 1
- p.PageSize = int64(util.SearchPageSize * util.SearchMaxPageNum)
- _, res, err = p.FindDataFromES()
- *cacheBytes, err = json.Marshal(res)
- if err == nil && len(*cacheBytes) > 0 {
- err = redis.PutBytes(redisCode, purchaseCacheKey, cacheBytes, purchaseCacheExpire)
- }
- }
- *res = (*res)[start:pageSize]
- } else {
- //实时查询
- //未登录查询 限制并发数
- _, res, err = p.FindDataFromES()
- }
- if len(*res) > 0 {
- p.PurchaseListFormat(res)
- }
- return
- }
- // 关键词 附加词 行业
- func (p *Purchase) IsEmptySearch() bool {
- if p.KeyWords != "" || p.AdditionalWords != "" || p.Industry != "" {
- return false
- }
- return true
- }
- var (
- purchaseSelectTypeMap = map[string]bool{
- "title": true,
- "purchasing": true,
- }
- tipMsg = "“%s“及其后面的字词均被忽略,因为剑鱼标讯的查询限制在%d个汉字以内。"
- )
- // 筛选条件格式化
- func (p *Purchase) FilterCriteriaFormat() {
- //搜索范围
- if p.SelectType != "" {
- var selectTypes []string
- for _, sv := range strings.Split(p.SelectType, ",") {
- if purchaseSelectTypeMap[sv] {
- selectTypes = append(selectTypes, sv)
- }
- }
- if len(selectTypes) > 0 {
- p.SelectType = strings.Join(selectTypes, ",")
- }
- }
- if p.SelectType == "" {
- p.SelectType = "title"
- }
- // p.SearchMode 搜索模式:0:精准搜索;1:模糊搜索
- // 精准搜索:不分词,完全匹配;(中间带空格的关键词组自动分词)
- // 模糊搜索:对用户输入的单个关键词进行分词处理,但必须都存在;
- if p.SearchMode < 0 || p.SearchMode > 1 {
- p.SearchMode = 0
- }
- // p.WordsMode 搜索关键词模式;默认0:包含所有,1:包含任意
- if p.WordsMode < 0 || p.WordsMode > 1 {
- p.WordsMode = 0
- }
- //发布时间--默认最近一年
- if p.PublishTime == "" {
- p.PublishTime = fmt.Sprintf("%d-%d", time.Now().AddDate(-1, 0, 0).Unix(), time.Now().Unix())
- }
- //默认每页数据量
- if p.PageSize <= 0 || p.PageSize > 100 {
- p.PageSize = 50
- }
- //第一页
- if p.PageNum <= 0 || p.PageNum > int64(IC.C.DefaultBidInfo.Count)/p.PageSize {
- p.PageNum = 1
- }
- //行业
- if p.Industry != "" {
- p.Industry = strings.TrimSpace(p.Industry)
- //P510 行业:其它
- if qt := jy.IndustryHandle(p.Industry); len(qt) > 0 {
- p.Industry = fmt.Sprintf("%s,%s", p.Industry, strings.Join(qt, ","))
- }
- }
- var (
- searchWords []string
- )
- //关键词
- if p.KeyWords != "" {
- p.KeyWords = strings.TrimSpace(p.KeyWords)
- _, p.TipMsg, p.KeyWords = util.InterceptSearchKW(p.KeyWords, MC.IntAllDef(IC.C.KeywordsLimit, 35), true)
- if p.TipMsg != "" {
- p.TipMsg = fmt.Sprintf(tipMsg, p.TipMsg, MC.IntAllDef(IC.C.KeywordsLimit, 35))
- }
- // in.SearchMode 搜索模式:0:精准搜索;1:模糊搜索
- // 精准搜索:不分词,完全匹配;(中间带空格的关键词组自动分词)
- // 模糊搜索:对用户输入的单个关键词进行分词处理,但必须都存在;
- //主关键词词组
- if p.SearchMode == 1 {
- if ikWords := util.HttpEs(p.KeyWords, "ik_smart", IC.DB.Es.Addr); ikWords != "" {
- p.KeyWords = jy.KeywordsProcessing(ikWords, IC.C.JYKeyMark)
- }
- }
- searchWords = append(searchWords, p.KeyWords)
- }
- //附加词 每组附加词不能超过15个字符
- if p.AdditionalWords != "" {
- var additionalWords []string
- for _, ak := range strings.Split(p.AdditionalWords, ",") {
- if len([]rune(ak)) > 15 {
- additionalWords = append(additionalWords, string([]rune(ak)[:15]))
- } else {
- additionalWords = append(additionalWords, ak)
- }
- }
- p.AdditionalWords = strings.Join(additionalWords, ",") //分组不变
- //多组附加词,每组间,号隔开。每组内如果关键词中间有空格,自动分词
- if p.SearchMode == 1 {
- var (
- addWords []string
- )
- for _, awv := range strings.Split(p.AdditionalWords, ",") {
- if strings.TrimSpace(awv) != "" {
- if ikWords := util.HttpEs(awv, "ik_smart", IC.DB.Es.Addr); ikWords != "" {
- addWords = append(addWords, jy.KeywordsProcessing(ikWords, IC.C.JYKeyMark))
- }
- }
- }
- if len(addWords) > 0 {
- p.AdditionalWords = strings.Join(addWords, ",")
- }
- }
- searchWords = append(searchWords, strings.Split(p.AdditionalWords, ",")...)
- }
- p.HighlightWords = strings.Join(searchWords, ",")
- //报名截止
- if p.DeadlineStatus < 0 || p.DeadlineStatus > 2 {
- p.DeadlineStatus = 0
- }
- if len(strings.Split(p.DeadlineTime, "-")) > 1 {
- p.DeadlineStart, _ = strconv.ParseInt(strings.Split(p.DeadlineTime, "-")[0], 10, 64)
- p.DeadlineEnd, _ = strconv.ParseInt(strings.Split(p.DeadlineTime, "-")[1], 10, 64)
- if p.DeadlineEnd > p.DeadlineStart {
- var deadline = p.DeadlineStart
- p.DeadlineStart = p.DeadlineEnd
- p.DeadlineEnd = deadline
- }
- }
- switch p.DeadlineStatus {
- case 1: //未截止
- if p.DeadlineEnd < time.Now().Unix() {
- p.DeadlineStart = time.Now().Unix()
- p.DeadlineEnd = 0
- }
- case 2: //已截止
- if p.DeadlineEnd > time.Now().Unix() {
- p.DeadlineStart = 0
- p.DeadlineEnd = time.Now().Unix()
- }
- }
- //空搜索 其它筛选条件 无效
- if p.IsEmptySearch() {
- //
- p.DomainFirstType = ""
- p.DomainSecondType = ""
- p.DomainThirdType = ""
- p.DeadlineStatus = 0
- p.DeadlineStart = 0
- p.DeadlineEnd = 0
- p.DeliveryArea = ""
- p.DeliveryCity = ""
- p.DeliveryDistrict = ""
- p.ProjectArea = ""
- p.ProjectCity = ""
- p.ProjectDistrict = ""
- p.FileExists = 0
- p.Publisher = 0
- }
- }
|