123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632 |
- package marketanalysis
- import (
- "app.yhyue.com/moapp/jybase/common"
- "app.yhyue.com/moapp/jybase/encrypt"
- elastic "app.yhyue.com/moapp/jybase/es"
- "app.yhyue.com/moapp/jybase/mongodb"
- "app.yhyue.com/moapp/jybase/mysql"
- "app.yhyue.com/moapp/jybase/redis"
- "app.yhyue.com/moapp/jypkg/common/src/qfw/util/jy"
- "encoding/json"
- "errors"
- "fmt"
- "log"
- "strings"
- "sync"
- "time"
- )
- var (
- MAPool chan bool
- MATimeout int
- MAProjectNumLimit int
- MAKeyWordsCount int
- MinKeyWordsCount int //关键词数量最低值 小于此数量,默认走线上
- MaxPCount int //项目最大限制数量
- ProjectCount int
- PtIndex = "projectset"
- PtType = "projectset"
- FieldsDetail = `"purchasing","projectname.pname"`
- Fields = `"projectname.pname"`
- BWCount = Top1000
- BWDCount = BWDistribution
- )
- func MAInit(limit, timeOut, projectNumLimit, keyWordsCount, pCount, minKCount, maxPCount, bwc, bwdc int, ptIndex, ptType string, fields []string) {
- if limit == 0 {
- limit = 5
- }
- MAPool = make(chan bool, limit)
- for i := 0; i < limit; i++ {
- MAPool <- true
- }
- if timeOut <= 0 {
- timeOut = 20
- }
- MATimeout = timeOut
- if projectNumLimit <= 0 {
- projectNumLimit = 600000
- }
- MAProjectNumLimit = projectNumLimit
- if keyWordsCount <= 0 {
- keyWordsCount = 300
- }
- MAKeyWordsCount = keyWordsCount
- if minKCount <= 0 {
- minKCount = 100
- }
- MinKeyWordsCount = minKCount
- if maxPCount <= 0 {
- maxPCount = 5000000
- }
- MaxPCount = maxPCount
- //项目数量
- ProjectCount = pCount
- //es 索引
- if ptIndex != "" {
- PtIndex = ptIndex
- PtType = ptType
- }
- //
- if len(fields) > 1 {
- Fields = fmt.Sprintf(`"%s"`, fields[0])
- FieldsDetail = fmt.Sprintf(`"%s"`, strings.Join(fields, `","`))
- }
- //
- if bwc > 0 {
- BWCount = bwc
- }
- if bwdc > 0 {
- BWDCount = bwdc
- }
- }
- // AnalysisRequestParam 接口原请求参数
- type AnalysisRequestParam struct {
- KeysItemsStr string //分析内容【字符串】结构和o_member_jy.a_items保持一致
- RangeTime string //时间【字符串】 时间戳开始-结束时间戳
- RangeTimeExtra string //时间【字符串】前段回显使用
- Area string //省份【对象字符串】
- Industry string //行业【对象字符串】
- BuyerClass string //采购单位类型【字符串】多个采购单位类型用逗号拼接
- Buyer string //采购单位
- Winner string //中标单位
- Sort int //排序:默认0:成交时间倒序;1:项目金额倒序
- PageSize int //默认每页10条
- PageNum int //默认当前第一页
- IsDetail bool //是否是项目明细请求
- MatchingMode string //匹配方式 title:标题 content:项目名称/标的物
- }
- type viewKeyWord struct {
- Keyword []string `json:"key"` //关键词
- Appended []string `json:"appendkey"` //附加词
- Exclude []string `json:"notkey"` //排除词
- MatchWay int `json:"matchway"` //匹配模式
- }
- // keyWordGroup 订阅词结构体
- type keyWordGroup struct {
- A_Key []viewKeyWord `json:"a_key"`
- ItemName string `json:"s_item"`
- UpdateTime int64 `json:"updatetime"`
- }
- // AnalysisRequestFormat 格式化后参数
- type AnalysisRequestFormat struct {
- KeysItems []keyWordGroup
- Area, City []string //省份城市
- STime, ETime int64 //开始结束时间
- Industry []string //行业
- BuyerClass []string //采购单位类型
- Buyer string //采购单位
- Winner string //中标单位
- Sort int //排序:默认0:成交时间倒序;1:项目金额倒序
- PageSize int //默认每页10条
- PageNum int //默认当前第一页
- }
- type AnalysisEntity struct {
- MgoRecordId string
- BaseParam AnalysisRequestParam
- FormatParam AnalysisRequestFormat
- UId, Pid string
- ProjectInfo projectInfo
- Offline int // 1-离线 2-实时
- State int // 状态:默认0:生成中;1:已生成;2:已取消;-1:生成失败
- MgoUserId string
- Phone string // 手机号
- PositionId int64
- OriginalTotal int64 // 数据总数
- KeysTotal int64 //关键词数量
- PositionType int
- EntId int
- EntUserId int
- Source string
- Mgo *mongodb.MongodbSim
- MySql *mysql.Mysql
- Rs int //分析来源
- }
- type projectInfo struct {
- Count int64
- List []ProjectList
- }
- type ProjectList struct {
- Name string `json:"name"` //项目名称
- Id string `json:"id"` //项目id
- Area string `json:"area"` //地区
- DealTime int64 `json:"dealTime"` //成交时间
- BidStatus string `json:"bidStatus"` //项目类型
- BuyerClass string `json:"buyerClass"` //采购单位类型
- Winner []string `json:"winner"` //中标单位
- WinnerId []string `json:"winnerId"` //中标单位id
- Buyer string `json:"buyer"` //采购单位
- BidAmount float64 `json:"bidAmount"` //中标金额
- Budget float64 `json:"budget"` //预算
- }
- // ForMatData 获取格式化请求参数
- func (a *AnalysisEntity) ForMatData() error {
- //格式化订阅词
- if err := json.Unmarshal([]byte(a.BaseParam.KeysItemsStr), &a.FormatParam.KeysItems); err != nil {
- return fmt.Errorf("关键词组格式异常")
- }
- if a.FormatParam.KeysItems == nil || len(a.FormatParam.KeysItems) == 0 {
- return fmt.Errorf("请选择关键词组")
- }
- var flag bool
- if a.Rs == 0 { //普通分析(非pdf)
- // 判断关键词是不是为空
- for i := 0; i < len(a.FormatParam.KeysItems); i++ {
- items := a.FormatParam.KeysItems[i]
- for j := 0; j < len(items.A_Key); j++ {
- AKey := items.A_Key[j]
- if len(AKey.Keyword) > 0 {
- var keys []string
- for _, kv := range AKey.Keyword {
- if strings.TrimSpace(kv) != "" {
- keys = append(keys, kv)
- }
- }
- AKey.Keyword = []string{}
- if len(keys) > 0 {
- AKey.Keyword = keys
- flag = true
- break
- }
- }
- if len(AKey.Keyword) == 0 {
- items.A_Key = append(items.A_Key[:j], items.A_Key[j+1:]...)
- }
- }
- if flag {
- break
- }
- a.FormatParam.KeysItems = append(a.FormatParam.KeysItems[:i], a.FormatParam.KeysItems[i+1:]...)
- }
- if !flag {
- return fmt.Errorf("请选择关键词组")
- }
- }
- //格式化时间段
- if timeArr := strings.Split(a.BaseParam.RangeTime, "-"); len(timeArr) == 2 {
- a.FormatParam.STime = common.Int64All(timeArr[0])
- a.FormatParam.ETime = common.Int64All(timeArr[1])
- if a.FormatParam.STime == 0 || a.FormatParam.ETime == 0 {
- return fmt.Errorf("开始时间和结束时间不能为空")
- }
- } else {
- return fmt.Errorf("时间戳格式异常")
- }
- //格式化省份、城市
- if areaStr := strings.TrimSpace(a.BaseParam.Area); areaStr != "" {
- imap := map[string][]string{}
- if err := json.Unmarshal([]byte(a.BaseParam.Area), &imap); err != nil {
- return fmt.Errorf("非法地区信息")
- }
- var city, area []string
- for name, v := range imap {
- if len(v) == 0 {
- area = append(area, name)
- } else {
- for _, vv := range v {
- city = append(city, vv)
- }
- }
- }
- a.FormatParam.Area = area
- a.FormatParam.City = city
- }
- //格式化行业
- if industryStr := strings.TrimSpace(a.BaseParam.Industry); industryStr != "" {
- imap := map[string][]string{}
- if err := json.Unmarshal([]byte(industryStr), &imap); err != nil {
- return fmt.Errorf("非法行业信息")
- }
- var farr []string
- for name, v := range imap {
- for _, vv := range v {
- farr = append(farr, fmt.Sprintf("%s_%s", name, vv))
- }
- }
- if len(farr) > 0 {
- //P510 行业:其它
- if qt := jy.IndustryHandle(strings.Join(farr, ",")); len(qt) > 0 {
- farr = append(farr, qt...)
- }
- }
- a.FormatParam.Industry = farr
- }
- //格式化类型
- if buyerClassStr := strings.TrimSpace(a.BaseParam.BuyerClass); buyerClassStr != "" {
- a.FormatParam.BuyerClass = strings.Split(buyerClassStr, ",")
- }
- //中标企业
- a.FormatParam.Winner = a.BaseParam.Winner
- //采购单位
- a.FormatParam.Buyer = a.BaseParam.Buyer
- //排序
- a.FormatParam.Sort = common.If(a.BaseParam.Sort != 0 && a.BaseParam.Sort != 1, 0, a.BaseParam.Sort).(int)
- if a.BaseParam.PageNum*a.BaseParam.PageSize > ProjectCount {
- a.BaseParam.PageNum = ProjectCount / a.BaseParam.PageSize
- }
- //当前页码
- a.FormatParam.PageNum = common.If(a.BaseParam.PageNum < 1 || a.BaseParam.PageNum > 1000, 1, a.BaseParam.PageNum).(int)
- //默认每页10条
- a.FormatParam.PageSize = common.If(a.BaseParam.PageSize < 1 || a.BaseParam.PageSize > 100, 50, a.BaseParam.PageSize).(int)
- return nil
- }
- // ForMatData 获取格式化请求参数
- func (a *AnalysisEntity) ForMatDataPdf() (string, error) {
- //格式化订阅词
- if err := json.Unmarshal([]byte(a.BaseParam.KeysItemsStr), &a.FormatParam.KeysItems); err != nil {
- return "", fmt.Errorf("关键词组格式异常")
- }
- //格式化时间段
- if timeArr := strings.Split(a.BaseParam.RangeTime, "-"); len(timeArr) == 2 {
- a.FormatParam.STime = common.Int64All(timeArr[0])
- a.FormatParam.ETime = common.Int64All(timeArr[1])
- if a.FormatParam.STime == 0 || a.FormatParam.ETime == 0 {
- return "", fmt.Errorf("开始时间和结束时间不能为空")
- }
- } else {
- return "", fmt.Errorf("时间戳格式异常")
- }
- //格式化省份、城市
- if areaStr := strings.TrimSpace(a.BaseParam.Area); areaStr != "" {
- imap := map[string][]string{}
- if err := json.Unmarshal([]byte(a.BaseParam.Area), &imap); err != nil {
- return "", fmt.Errorf("非法地区信息")
- }
- var city, area []string
- for name, v := range imap {
- if len(v) == 0 {
- area = append(area, name)
- } else {
- for _, vv := range v {
- city = append(city, vv)
- }
- }
- }
- a.FormatParam.Area = area
- a.FormatParam.City = city
- }
- //格式化行业
- if industryStr := strings.TrimSpace(a.BaseParam.Industry); industryStr != "" {
- imap := map[string][]string{}
- if err := json.Unmarshal([]byte(industryStr), &imap); err != nil {
- return "", fmt.Errorf("非法行业信息")
- }
- var farr []string
- for name, v := range imap {
- for _, vv := range v {
- farr = append(farr, fmt.Sprintf("%s_%s", name, vv))
- }
- }
- a.FormatParam.Industry = farr
- }
- //格式化类型
- if buyerClassStr := strings.TrimSpace(a.BaseParam.BuyerClass); buyerClassStr != "" {
- a.FormatParam.BuyerClass = strings.Split(buyerClassStr, ",")
- }
- //中标企业
- a.FormatParam.Winner = a.BaseParam.Winner
- //采购单位
- a.FormatParam.Buyer = a.BaseParam.Buyer
- //排序
- a.FormatParam.Sort = common.If(a.BaseParam.Sort != 0 && a.BaseParam.Sort != 1, 0, a.BaseParam.Sort).(int)
- if a.BaseParam.PageNum*a.BaseParam.PageSize > ProjectCount {
- a.BaseParam.PageNum = ProjectCount / a.BaseParam.PageSize
- }
- //当前页码
- a.FormatParam.PageNum = common.If(a.BaseParam.PageNum < 1 || a.BaseParam.PageNum > 1000, 1, a.BaseParam.PageNum).(int)
- //默认每页10条
- a.FormatParam.PageSize = common.If(a.BaseParam.PageSize < 1 || a.BaseParam.PageSize > 100, 50, a.BaseParam.PageSize).(int)
- data := map[string]interface{}{
- "s_keysItems": a.BaseParam.KeysItemsStr,
- "s_rangeTime": a.BaseParam.RangeTime,
- "s_rangeTimeExtra": a.BaseParam.RangeTimeExtra,
- "s_area": a.BaseParam.Area,
- "s_industry": a.BaseParam.Industry,
- "s_buyerClass": a.BaseParam.BuyerClass,
- "s_matchingMode": a.BaseParam.MatchingMode,
- "s_userId": a.UId,
- "s_parentId": a.Pid,
- "s_mgoUserId": a.MgoUserId,
- "i_positionId": a.PositionId,
- "s_phone": a.Phone,
- "audit": 1,
- }
- if a.OriginalTotal > 0 {
- data["l_originalTotal"] = a.OriginalTotal
- }
- if a.Source != "" {
- data["source"] = a.Source
- }
- rs, b := a.Mgo.FindOne(ReportHistoryTable, data)
- if b && rs != nil && len(*rs) > 0 {
- return common.InterfaceToStr((*rs)["_id"]), errors.New("当期分析已存在")
- }
- return "", nil
- }
- // GetProjectInfoList 项目明细
- func (a *AnalysisEntity) GetProjectInfoList() error {
- var (
- queryDefault = `,"sort": [{%s}],"from": %d,"size": %d`
- start = (a.FormatParam.PageNum - 1) * a.FormatParam.PageSize
- sort = `"jgtime": "desc"`
- )
- if a.FormatParam.Sort > 0 {
- sort = `"bidamount": "desc","budget": "desc"`
- }
- countSql := fmt.Sprintf(a.GetCommonQuerySql(), "")
- queryDefault = fmt.Sprintf(queryDefault, sort, start, a.FormatParam.PageSize)
- finalSql := fmt.Sprintf(a.GetCommonQuerySql(), queryDefault)
- log.Println("finalSql:", finalSql)
- count, hits := elastic.GetWithCount(PtIndex, PtType, countSql, finalSql)
- //hits, count := elastic.GetOA(PtIndex, PtType, finalSql)
- if count > 0 {
- a.ProjectInfo.Count = count
- source := *hits
- for _, v := range source {
- var winnerIdArr []string
- if common.ObjToString(v["s_winner"]) != "" && v["entidlist"] != nil {
- idObjs, _ := v["entidlist"].([]interface{})
- for _, v := range common.ObjArrToStringArr(idObjs) {
- if v != "" && v != "-" {
- v = encrypt.EncodeArticleId2ByCheck(v)
- }
- winnerIdArr = append(winnerIdArr, v)
- }
- }
- a.ProjectInfo.List = append(a.ProjectInfo.List, ProjectList{
- Name: common.ObjToString(v["projectname"]),
- Id: encrypt.EncodeArticleId2ByCheck(common.ObjToString(v["id"])),
- Area: common.ObjToString(v["area"]),
- DealTime: common.Int64All(v["jgtime"]), //截止时间
- BidStatus: common.ObjToString(v["bidstatus"]),
- BuyerClass: common.ObjToString(v["buyerclass"]),
- Winner: strings.Split(common.ObjToString(v["s_winner"]), ","),
- WinnerId: winnerIdArr,
- Buyer: common.ObjToString(v["buyer"]),
- BidAmount: common.Float64All(v["bidamount"]), //中标金额
- Budget: common.Float64All(v["budget"]), //预算
- })
- }
- }
- return nil
- }
- // SaveAnalysisRecord 保存分析记录
- func (a *AnalysisEntity) SaveAnalysisRecord() error {
- if a.Offline == ValueRealTime {
- a.State = ReportStateGenerated
- } else {
- a.State = ReportStateGenerating
- }
- data := map[string]interface{}{
- "s_keysItems": a.BaseParam.KeysItemsStr,
- "s_rangeTime": a.BaseParam.RangeTime,
- "s_rangeTimeExtra": a.BaseParam.RangeTimeExtra,
- "s_area": a.BaseParam.Area,
- "s_industry": a.BaseParam.Industry,
- "s_buyerClass": a.BaseParam.BuyerClass,
- "s_matchingMode": a.BaseParam.MatchingMode,
- "s_userId": a.UId,
- "s_parentId": a.Pid,
- "i_state": common.If(a.Source == "analysisPDF", 1, a.State), //状态:默认0:生成中;1:已生成;2:已取消;-1:生成失败
- "l_updateTime": time.Now().Unix(), //生成时间 or 取消时间
- "l_createTime": time.Now().Unix(),
- "i_offline": common.If(a.Source == "analysisPDF", 2, a.Offline),
- "s_mgoUserId": a.MgoUserId,
- "i_positionId": a.PositionId,
- "s_phone": a.Phone,
- }
- if a.OriginalTotal > 0 {
- data["l_originalTotal"] = a.OriginalTotal
- }
- if a.KeysTotal > 0 {
- data["l_keysTotal"] = a.KeysTotal
- }
- if a.Source != "" {
- data["source"] = a.Source
- }
- a.MgoRecordId = a.Mgo.Save(ReportHistoryTable, data)
- if a.MgoRecordId == "" {
- return fmt.Errorf("分析创建异常")
- }
- return nil
- }
- // GetAnalysisFromMgoDb 从数据库中获取分析记录
- func (a *AnalysisEntity) GetAnalysisFromMgoDb() error {
- if a.MgoRecordId == "" {
- return fmt.Errorf("缺少参数")
- }
- queryMap := map[string]interface{}{
- "_id": mongodb.StringTOBsonId(a.MgoRecordId),
- "i_del": map[string]interface{}{"$ne": 1},
- }
- if a.UId == a.Pid { //主账号
- queryMap["s_parentId"] = a.Pid
- } else {
- queryMap["s_userId"] = a.UId
- }
- res, _ := a.Mgo.FindOne(ReportHistoryTable, queryMap)
- if res == nil || len(*res) == 0 {
- return fmt.Errorf("未查询到相关数据")
- }
- a.Offline = common.IntAll((*res)["i_offline"])
- a.State = common.IntAll((*res)["i_state"])
- a.BaseParam.KeysItemsStr, _ = (*res)["s_keysItems"].(string)
- a.BaseParam.RangeTime, _ = (*res)["s_rangeTime"].(string)
- a.BaseParam.RangeTimeExtra, _ = (*res)["s_rangeTimeExtra"].(string)
- a.BaseParam.Area, _ = (*res)["s_area"].(string)
- a.BaseParam.Industry, _ = (*res)["s_industry"].(string)
- a.BaseParam.BuyerClass, _ = (*res)["s_buyerClass"].(string)
- a.BaseParam.MatchingMode, _ = (*res)["s_matchingMode"].(string)
- return nil
- }
- // removeEmptyRecord 删除空报告记录
- func (a *AnalysisEntity) removeEmptyRecord() {
- queryMap := map[string]interface{}{
- "_id": mongodb.StringTOBsonId(a.MgoRecordId),
- }
- if a.UId == a.Pid { //主账号
- queryMap["s_parentId"] = a.Pid
- } else {
- queryMap["s_userId"] = a.UId
- }
- a.Mgo.Update(ReportHistoryTable, queryMap, map[string]interface{}{
- "$set": map[string]interface{}{"i_del": 1},
- }, false, false)
- //log.Println("删除空报告", queryMap)
- }
- // GetRecordList 获取分析记录
- func (a *AnalysisEntity) GetRecordList(pageNum, PageSize int, positionType int, entId, entUserId int) (total int, list []map[string]interface{}) {
- queryMap := map[string]interface{}{
- "i_del": map[string]interface{}{"$ne": 1},
- }
- if a.UId == a.Pid { //主账号
- queryMap["s_parentId"] = a.Pid
- } else {
- queryMap["s_userId"] = a.UId
- }
- if pageNum == 1 {
- total = a.Mgo.Count(ReportHistoryTable, queryMap)
- if total == 0 {
- return
- }
- } else {
- total = -1
- }
- res, _ := a.Mgo.Find(ReportHistoryTable, queryMap, `{"l_createTime":-1}`, nil, false, (pageNum-1)*PageSize, PageSize)
- if res == nil || len(*res) == 0 {
- return
- }
- var ids []string
- for _, m := range *res {
- ids = append(ids, common.InterfaceToStr(m["_id"]))
- }
- idMap := make(map[string]map[string]interface{})
- tName, _ := GetMongoColl(MarketScaleMain)
- mids, _ := a.Mgo.Find(tName, map[string]interface{}{
- "s_m_id": map[string]interface{}{
- "$in": ids,
- },
- }, "", `{"market_profile":1,"s_m_id":1}`, false, -1, -1)
- if mids != nil && len(*mids) > 0 {
- for _, m := range *mids {
- marketProfile, _ := m["market_profile"].(map[string]interface{})
- if common.IntAll(marketProfile["project_count"]) > 0 {
- idMap[common.InterfaceToStr(m["s_m_id"])] = marketProfile
- }
- }
- }
- //用户消息开关
- open := GetMsgOpen(a.Mgo, a.MgoUserId, positionType, entId, entUserId)
- for _, row := range *res {
- var status int
- if row["i_state"] != nil {
- status = common.IntAll(row["i_state"])
- if status == ReportStateFailed {
- status = ReportStateGenerating // 生成失败对外还是展示为生成中
- }
- }
- var (
- isDownload bool
- )
- marketProfile := make(map[string]interface{})
- if marketProfile = idMap[mongodb.BsonIdToSId(row["_id"])]; marketProfile != nil && common.IntAll(marketProfile["project_count"]) > 0 && status == 1 {
- isDownload = true
- }
- //P510 回显 移除 其它
- industry := common.ObjToString(row["s_industry"])
- if industry != "" {
- industry = strings.ReplaceAll(industry, "\"其它\"", "")
- }
- data := map[string]interface{}{
- "id": encodeId(mongodb.BsonIdToSId(row["_id"])),
- "keysItems": common.ObjToString(row["s_keysItems"]),
- "area": common.ObjToString(row["s_area"]),
- "industry": industry,
- "buyerclass": common.ObjToString(row["s_buyerClass"]),
- "rangeTime": common.ObjToString(row["s_rangeTime"]),
- "s_rangeTimeExtra": common.ObjToString(row["s_rangeTimeExtra"]),
- "createTime": common.Int64All(row["l_createTime"]),
- "matchingMode": common.ObjToString(row["s_matchingMode"]), //项目匹配方式
- "state": common.If(row["i_state"] == nil, nil, status),
- "updateTime": common.Int64All(row["l_updateTime"]),
- "msgOpen": open,
- "isDownload": isDownload,
- "marketProfile": marketProfile,
- }
- list = append(list, data)
- }
- return
- }
- func (a *AnalysisEntity) GetRecordPdfList(pageNum, PageSize int) (total int, list []map[string]interface{}) {
- queryMap := map[string]interface{}{
- "i_del": map[string]interface{}{"$ne": 1},
- "source": "analysisPDF",
- }
- if a.UId == a.Pid { //主账号
- queryMap["s_parentId"] = a.Pid
- } else {
- queryMap["s_userId"] = a.UId
- }
- if pageNum == 1 {
- total = a.Mgo.Count(ReportHistoryTable, queryMap)
- if total == 0 {
- return
- }
- } else {
- total = -1
- }
- res, _ := a.Mgo.Find(ReportHistoryTable, queryMap, `{"l_createTime":-1}`, nil, false, (pageNum-1)*PageSize, PageSize)
- if res == nil || len(*res) == 0 {
- return
- }
- for _, row := range *res {
- data := map[string]interface{}{
- "id": encodeId(mongodb.BsonIdToSId(row["_id"])),
- "keysItems": common.ObjToString(row["s_keysItems"]),
- "area": common.ObjToString(row["s_area"]),
- "industry": common.ObjToString(row["s_industry"]),
- "buyerclass": common.ObjToString(row["s_buyerClass"]),
- "rangeTime": common.ObjToString(row["s_rangeTime"]),
- "s_rangeTimeExtra": common.ObjToString(row["s_rangeTimeExtra"]),
- "createTime": common.Int64All(row["l_createTime"]),
- "matchingMode": common.ObjToString(row["s_matchingMode"]), //项目匹配方式
- "updateTime": common.Int64All(row["l_updateTime"]),
- "audit": common.Int64All(row["audit"]),
- }
- list = append(list, data)
- }
- return
- }
- // GetQueryItem 获取查询条件,前端回显使用
- func (a *AnalysisEntity) getQueryItem() (map[string]interface{}, error) {
- return map[string]interface{}{
- "keysItems": a.BaseParam.KeysItemsStr,
- "area": a.BaseParam.Area,
- "industry": a.BaseParam.Industry,
- "buyerclass": a.BaseParam.BuyerClass,
- "rangeTime": a.BaseParam.RangeTime,
- "s_rangeTimeExtra": a.BaseParam.RangeTimeExtra,
- "matchingMode": a.BaseParam.MatchingMode,
- }, nil
- }
- // GetPartResult 分块儿获取报告内容
- func (a *AnalysisEntity) GetPartResult(flag int) (map[string]interface{}, error) {
- defer common.Catch()
- if flag == MarketQueryItem { //返回查询内容
- return a.getQueryItem()
- }
- thisCacheKey := fmt.Sprintf(ReportCacheKey, a.MgoRecordId, flag)
- if cacheData := redis.Get(ReportCacheDB, thisCacheKey); cacheData != nil {
- if cacheMap, ok := cacheData.(map[string]interface{}); ok && len(cacheMap) > 0 {
- return cacheMap, nil
- }
- }
- rData, err := func() (map[string]interface{}, error) {
- //控制并发&&超时返回超时异常
- select {
- case <-time.After(time.Duration(MATimeout) * time.Second * 20):
- return nil, fmt.Errorf("查询超时,请稍后重试")
- case <-MAPool:
- }
- start := time.Now()
- defer func() {
- MAPool <- true
- log.Printf("report %s[%d] speed %d ms\n", a.MgoRecordId, flag, time.Now().Sub(start).Milliseconds())
- }()
- //校验报告是否合法
- //if flag != MarketScaleMain {
- // if exists, _ := redis.Exists(ReportCacheDB, fmt.Sprintf(ReportCacheKey, a.MgoRecordId, 1)); !exists {
- // return nil, fmt.Errorf("报告异常请求,请刷新重试")
- // }
- //}
- // 1. 查mongo
- var rData map[string]interface{}
- var err error
- rData, err = a.GetMongoData(flag)
- // 查到数据则直接返回
- if err == nil && rData != nil {
- return rData, nil
- }
- // 2.没有查询到数据 判断是不是离线的
- // 正常情况下正在离线生的不会走到这里
- // 离线的应该生成完报告之后才会调用获取结果接口 这里处理是防止直接调接口传正在离线生的报告
- if a.Offline == ValueOffline || a.Offline == 0 {
- return nil, err
- }
- // 3. 实时则查es
- rData, err = a.RealTimeQuery(flag)
- if err == nil && len(rData) > 0 {
- // 4.存库
- a.SaveMongoReport(rData, flag)
- return rData, err
- }
- return nil, err
- }()
- if err == nil && rData != nil && len(rData) > 0 {
- delete(rData, "s_m_id")
- delete(rData, "_id")
- redis.Put(ReportCacheDB, thisCacheKey, rData, ReportCacheTime)
- }
- return rData, err
- }
- // 离线 获取采购单位和中部单位数据
- func (a *AnalysisEntity) BWData() (buyers []string, winners []string) {
- sql := `"buyer_terms": {"terms": {"field": "buyer","size": 50000}},"winner_terms": {"terms": {"field": "s_winner","size": 50000}}`
- finalSql := fmt.Sprintf(a.GetCommonQuerySqlWithAggs(), sql)
- res := GetAggs(PtIndex, PtType, finalSql)
- if res == nil || len(res) == 0 {
- return
- }
- var bw = BWBuckets{}
- for name, object := range res {
- bArr, err := object.MarshalJSON()
- if len(bArr) == 0 || err != nil {
- continue
- }
- if name == "buyer_terms" {
- if json.Unmarshal(bArr, &bw.Buyerterms) != nil {
- continue
- }
- } else if name == "winner_terms" {
- if json.Unmarshal(bArr, &bw.Winnerterms) != nil {
- continue
- }
- }
- }
- for _, bv := range bw.Buyerterms.Buckets {
- buyers = append(buyers, bv.Key)
- }
- for _, wv := range bw.Winnerterms.Buckets {
- winners = append(winners, wv.Key)
- }
- return
- }
- // 实时查询
- func (a *AnalysisEntity) RealTimeQuery(flag int) (map[string]interface{}, error) {
- switch flag {
- case MarketScaleMain:
- rData, err := a.MarketTime()
- //非离线
- if a.Offline != ValueOffline && err != nil { //若无报告内容,删除报告记录
- go a.removeEmptyRecord()
- }
- if rData != nil && a.Offline == ValueOffline {
- //采购单位和中部单位 数据
- rData["buyers"], rData["winners"] = a.BWData()
- }
- return rData, err
- case MarketTopProject:
- return a.ProjectTop10()
- case MarketProjectAllData:
- return a.AllData()
- case MarketScaleRefine:
- return a.MarketScaleRefineQuery()
- case MarketBuyerAndWinner:
- return a.BuyerWinnerAnalysis(), nil
- }
- return nil, fmt.Errorf("未知请求")
- }
- // GetMongoData 从mongo库查询数据
- func (a *AnalysisEntity) GetMongoData(flag int) (map[string]interface{}, error) {
- collName, err := GetMongoColl(flag)
- if err != nil || collName == "" {
- return nil, fmt.Errorf("未知请求")
- }
- // 查询
- query := map[string]interface{}{
- "s_m_id": a.MgoRecordId,
- }
- data, b := a.Mgo.FindOne(collName, query)
- if !b || data == nil || len(*data) == 0 {
- log.Println("没有查询到数据", b, query, collName)
- return nil, nil
- }
- delete(*data, "s_m_id")
- delete(*data, "_id")
- return *data, nil
- }
- // GetMongoColl 获取mgo库对应的Coll
- func GetMongoColl(flag int) (string, error) {
- switch flag {
- case MarketScaleMain:
- return CollMarketScaleMain, nil
- case MarketTopProject:
- return CollMarketTopProject, nil
- case MarketProjectAllData:
- return CollMarketProjectAllData, nil
- case MarketScaleRefine:
- return CollMarketScaleRefine, nil
- case MarketBuyerAndWinner:
- return CollMarketBuyerAndWinner, nil
- }
- return "", fmt.Errorf("未知类型")
- }
- // SaveMongoReport 数据存mongo库
- func (a *AnalysisEntity) SaveMongoReport(rData map[string]interface{}, flag int) {
- collName, _ := GetMongoColl(flag)
- rData["s_m_id"] = a.MgoRecordId
- b, err := json.Marshal(rData)
- if err != nil {
- log.Println("JSON marshal error:", err)
- } else {
- var saveMap map[string]interface{}
- err = json.Unmarshal(b, &saveMap)
- if err != nil {
- log.Println("JSON Unmarshal error:", err)
- a.Mgo.Save(collName, rData)
- } else {
- a.Mgo.Save(collName, saveMap)
- }
- }
- }
- // GetAnalyzingReport 是否有正在分析的离线报告
- func (a *AnalysisEntity) GetAnalyzingReport() string {
- query := map[string]interface{}{
- "s_userId": a.UId,
- "i_state": map[string]interface{}{"$in": []int{ReportStateGenerating, ReportStateFailed}}, //状态:默认0:生成中;1:已生成;2:已取消;-1:生成失败
- "i_del": map[string]interface{}{"$ne": 1},
- }
- //log.Println("query:", query)
- rs, b := a.Mgo.FindOne(ReportHistoryTable, query)
- //log.Println("rs,b:", rs, b)
- if b && rs != nil {
- return mongodb.BsonIdToSId((*rs)["_id"])
- }
- return ""
- }
- // IsOffline 判断是否符合在线分析的条件
- func (a *AnalysisEntity) IsOffline() {
- //离线生成:订阅词(关键词+排除词)超过300个(数量支持配置),或单次分析数据超过60万条,则离线生成;
- // 查询数据量
- countSql := fmt.Sprintf(a.GetCommonQuerySql(), "")
- log.Println(a.Phone, "IsOffline count SQL:", countSql)
- now := time.Now()
- dataCount := elastic.Count(PtIndex, PtType, countSql)
- log.Println(a.Phone, "--IsOffline 数据量:", dataCount, "---", MaxPCount)
- if dataCount > int64(MaxPCount) { //提示用户 数据量过大,修改生成报告条件
- a.Offline = ValueError
- return
- }
- a.OriginalTotal = dataCount
- keyCount := 0
- for i := 0; i < len(a.FormatParam.KeysItems); i++ {
- items := a.FormatParam.KeysItems[i]
- for j := 0; j < len(items.A_Key); j++ {
- AKey := items.A_Key[j]
- for k := 0; k < len(AKey.Keyword); k++ {
- keyCount++
- }
- for k := 0; k < len(AKey.Appended); k++ {
- keyCount++
- }
- for k := 0; k < len(AKey.Exclude); k++ {
- keyCount++
- }
- }
- }
- a.KeysTotal = int64(keyCount)
- //关键词数量 < 100 ,默认走线上
- if keyCount < MinKeyWordsCount {
- a.Offline = ValueRealTime
- return
- }
- if keyCount > MAKeyWordsCount {
- // 查询配置
- if mac := a.getMarUserAccount(); mac != nil {
- if keyCount >= mac.Threshold {
- a.Offline = ValueOffline
- return
- }
- } else {
- a.Offline = ValueOffline
- return
- }
- }
- log.Println("IsOffline 统计数据量耗时:", time.Since(now))
- if int(dataCount) > MAProjectNumLimit {
- a.Offline = ValueOffline
- return
- }
- a.Offline = ValueRealTime
- return
- }
- type MarUserAccount struct {
- Threshold int // 关键词离线标准量
- }
- // 获取离线市场报告分析关键词标准信息
- func (a *AnalysisEntity) getMarUserAccount() *MarUserAccount {
- rs := a.MySql.SelectBySql(fmt.Sprintf("SELECT threshold FROM %s where position_id=? and state = 0;", TablejianyuMarUserAccount), a.PositionId)
- if rs != nil && len(*rs) > 0 {
- return &MarUserAccount{Threshold: common.IntAll((*rs)[0]["threshold"])}
- }
- return nil
- }
- func (a *AnalysisEntity) GetReportState() (generated bool, needUpdate bool, err error) {
- // 查库
- err = a.GetAnalysisFromMgoDb()
- if err != nil {
- return
- }
- // 已经生成的可以直接返回
- if a.State == ReportStateGenerated {
- generated = true
- return
- }
- // 该字段没有值 说明是还没有被更新的历史数据 需要更新
- // 且判断之后后续需要更新i_state和i_offline字段
- if a.Offline == 0 {
- needUpdate = true
- }
- // 如果没有值的话 说明这是历史数据 需要接着走下面的流程进行判断
- // 格式化数据 用于后面校验个数
- if err = a.ForMatData(); err != nil {
- return
- }
- return
- }
- // Cancel 取消正在分析中的报告
- func (a *AnalysisEntity) Cancel() (bool, error) {
- // 取消报告
- queryMap := map[string]interface{}{
- "_id": a.MgoRecordId,
- "i_state": map[string]interface{}{"$in": []int{ReportStateGenerating, ReportStateFailed}}, //状态:默认0:生成中;1:已生成;2:已取消;-1:生成失败
- "i_del": map[string]interface{}{"$ne": 1},
- }
- if a.UId == a.Pid { //主账号
- queryMap["s_parentId"] = a.Pid
- } else {
- queryMap["s_userId"] = a.UId
- }
- //验证
- rs, b := a.Mgo.FindOne(ReportHistoryTable, queryMap)
- //
- if !b || rs == nil {
- return false, fmt.Errorf("未查询到该记录")
- }
- update := a.Mgo.UpdateById(ReportHistoryTable, a.MgoRecordId, map[string]interface{}{"$set": map[string]interface{}{
- "l_updateTime": time.Now().Unix(),
- "i_state": ReportStateCanceled,
- }})
- if !update {
- log.Println("分析报告取消失败:", a.MgoRecordId)
- return false, fmt.Errorf("取消失败")
- }
- // redis里面放取消标识
- redis.Put(ReportCacheDB, fmt.Sprintf(ReportCanceledKey, a.MgoRecordId), 1, ReportCanceledTime)
- return update, nil
- }
- // UpdateOffline 更新报告是否是离线报告
- func (a *AnalysisEntity) UpdateOffline(offline bool) bool {
- set := map[string]interface{}{
- "i_state": common.If(offline, ReportStateGenerating, ReportStateGenerated),
- "i_offline": common.If(offline, ValueOffline, ValueRealTime),
- "l_updateTime": time.Now().Unix(),
- "s_mgoUserId": a.MgoUserId, // 这里更新这些字段是因为这几个字段是p437 版本新加上的 历史数据没有这些字段
- "s_positionId": a.PositionId,
- "s_phone": a.Phone,
- }
- if a.OriginalTotal > 0 {
- set["l_originalTotal"] = a.OriginalTotal
- }
- data := map[string]interface{}{
- "$set": set,
- }
- update := a.Mgo.UpdateById(ReportHistoryTable, a.MgoRecordId, data)
- if !update {
- log.Println("UpdateOffline 更新报告状态失败:", data, a.MgoRecordId)
- }
- return update
- }
- // UpdateState 更新报告生成状态
- func (a *AnalysisEntity) UpdateState(state int) bool {
- setMap := map[string]interface{}{
- "i_state": state,
- "l_updateTime": time.Now().Unix(),
- }
- if state == ReportStateGenerated {
- setMap["l_finishTime"] = time.Now().Unix()
- }
- data := map[string]interface{}{
- "$set": setMap,
- }
- update := a.Mgo.UpdateById(ReportHistoryTable, a.MgoRecordId, data)
- if !update {
- log.Println("UpdateState 更新报告生成状态失败:", data, a.MgoRecordId)
- }
- return update
- }
- // Delete 删除正在分析中的报告
- func (a *AnalysisEntity) Delete() (bool, error) {
- // 删除报告
- queryMap := map[string]interface{}{
- "_id": a.MgoRecordId,
- "i_del": map[string]interface{}{"$ne": 1},
- }
- if a.UId == a.Pid { //主账号
- queryMap["s_parentId"] = a.Pid
- } else {
- queryMap["s_userId"] = a.UId
- }
- //验证
- rs, b := a.Mgo.FindOne(ReportHistoryTable, queryMap)
- //
- if !b || rs == nil {
- return false, fmt.Errorf("未查询到该记录")
- }
- update := a.Mgo.UpdateById(ReportHistoryTable, a.MgoRecordId, map[string]interface{}{"$set": map[string]interface{}{
- "l_updateTime": time.Now().Unix(),
- "i_del": 1,
- }})
- if !update {
- log.Println("分析报告删除失败:", a.MgoRecordId)
- return false, fmt.Errorf("删除失败")
- }
- // redis里面放取消标识
- redis.Put(ReportCacheDB, fmt.Sprintf(ReportCanceledKey, a.MgoRecordId), 1, ReportCanceledTime)
- return update, nil
- }
- // GetCommonQuerySql 公共筛选
- func (a *AnalysisEntity) GetCommonQuerySql() string {
- var musts, bools []string
- //时间
- musts = append(musts, fmt.Sprintf(`{"range":{"jgtime":{"gte":%d,"lte":%d}}}`, a.FormatParam.STime, a.FormatParam.ETime))
- //地区
- if len(a.FormatParam.Area) > 0 || len(a.FormatParam.City) > 0 {
- var areaCity []string
- if len(a.FormatParam.Area) > 0 {
- areaCity = append(areaCity, fmt.Sprintf(`{"terms":{"area":["%s"]}}`, strings.Join(a.FormatParam.Area, `","`)))
- }
- if len(a.FormatParam.City) > 0 {
- areaCity = append(areaCity, fmt.Sprintf(`{"terms":{"city":["%s"]}}`, strings.Join(a.FormatParam.City, `","`)))
- }
- musts = append(musts, fmt.Sprintf(`{"bool":{"should":[%s],"minimum_should_match": 1}}`, strings.Join(areaCity, ",")))
- }
- //行业
- if len(a.FormatParam.Industry) > 0 {
- musts = append(musts, fmt.Sprintf(`{"terms":{"subscopeclass":["%s"]}}`, strings.Join(a.FormatParam.Industry, `","`)))
- }
- //类型
- if len(a.FormatParam.BuyerClass) > 0 {
- musts = append(musts, fmt.Sprintf(`{"terms":{"buyerclass":["%s"]}}`, strings.Join(a.FormatParam.BuyerClass, `","`)))
- }
- //分析报告中标状态限制
- musts = append(musts, fmt.Sprintf(queryBoolMust, pSearchDecMust))
- //订阅词
- for _, v := range getAllKeywordArr(a.FormatParam.KeysItems) {
- if sql := getKeyWordSql(v, a.BaseParam.MatchingMode); sql != "" {
- bools = append(bools, sql)
- }
- }
- //中标企业
- if a.FormatParam.Winner != "" {
- var winnerId string
- if mongodb.IsObjectIdHex(a.FormatParam.Winner) {
- winnerId = a.FormatParam.Winner
- } else {
- rData := elastic.Get("qyxy", "qyxy", fmt.Sprintf(`{"query": {"bool": {"must": [{"term": {"company_name": "%s"}}]}},"_source":["_id"],"size": 1}`, a.FormatParam.Winner))
- if rData != nil && len(*rData) > 0 {
- winnerId = common.InterfaceToStr((*rData)[0]["_id"])
- }
- }
- if winnerId != "" {
- musts = append(musts, fmt.Sprintf(`{"term":{"entidlist":"%s"}}`, winnerId))
- } else {
- musts = append(musts, fmt.Sprintf(`{"term":{"s_winner":"%s"}}`, a.FormatParam.Winner))
- }
- }
- //采购单位
- if a.FormatParam.Buyer != "" {
- musts = append(musts, fmt.Sprintf(`{"term":{"buyer":"%s"}}`, a.FormatParam.Buyer))
- }
- return fmt.Sprintf(`{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}}%s}`, strings.Join(musts, ","), strings.Join(bools, ","), common.If(len(bools) > 0, 1, 0).(int), "%s")
- }
- // GetCommonQuerySqlWithAggs 此方法用于聚合查询
- func (a *AnalysisEntity) GetCommonQuerySqlWithAggs() string {
- return fmt.Sprintf(a.GetCommonQuerySql(), `,"aggs":{%s},"size":0`)
- }
- // 市场概况+时间分布
- func (a *AnalysisEntity) MarketTime() (map[string]interface{}, error) {
- var (
- sql []string
- monthB, yearB bool
- MonthRange, YearRange string
- isOffline = a.Offline == 1
- )
- sql = append(sql, fmt.Sprintf(aggsMarketAnalysis, "thismarket", fmt.Sprintf(`{"key":"%s","from":%d,"to":%d}`, "market", a.FormatParam.STime, a.FormatParam.ETime)))
- n_stime := a.FormatParam.STime
- var n_mae AnalysisEntity
- n_mae.FormatParam = a.FormatParam
- n_mae.BaseParam = a.BaseParam
- n_mae.MgoRecordId = a.MgoRecordId
- n_mae.FormatParam.ETime = a.FormatParam.ETime
- if time.Unix(a.FormatParam.STime, 0).AddDate(1, 0, 0).Unix() >= time.Unix(a.FormatParam.ETime, 0).Unix() {
- n_stime = getPreviousMarket(time.Unix(a.FormatParam.STime, 0), time.Unix(a.FormatParam.ETime, 0))
- sql = append(sql, fmt.Sprintf(aggsMarketAnalysis, "oldmarket", fmt.Sprintf(`{"key":"%s","from":%d,"to":%d}`, "market", n_stime, a.FormatParam.STime)))
- }
- if isOffline || time.Unix(a.FormatParam.STime, 0).AddDate(0, 1, 0).Unix() < time.Unix(a.FormatParam.ETime, 0).Unix() {
- var mon_time, year_time int64
- stime, etime := time.Unix(a.FormatParam.STime, 0), time.Unix(a.FormatParam.ETime, 0)
- monthB, MonthRange = GetMonthData(isOffline, stime, etime)
- sql = append(sql, fmt.Sprintf(projectTimeDistribution, "monthtime", MonthRange))
- if monthB {
- mon_time = stime.AddDate(0, -1, 0).Unix()
- } else {
- mon_time = a.FormatParam.STime
- }
- //年度数据
- yearB, YearRange = GetYearData(isOffline, stime, etime)
- sql = append(sql, fmt.Sprintf(projectTimeDistribution, "yeartime", YearRange))
- if yearB {
- year_time = stime.AddDate(-1, 0, 0).Unix()
- } else {
- year_time = a.FormatParam.STime
- }
- if n_stime > mon_time {
- n_stime = mon_time
- }
- if n_stime > year_time {
- n_stime = year_time
- }
- }
- //非离线
- if !isOffline {
- n_mae.FormatParam.STime = n_stime
- }
- finalSql := fmt.Sprintf(n_mae.GetCommonQuerySqlWithAggs(), strings.Join(sql, ","))
- log.Printf("final MarketScaleRefineQuery sql: %s", finalSql)
- rMap := make(map[string]interface{})
- rMapData := make(map[string]interface{})
- thisRow := marketTime{}
- res := GetAggs(PtIndex, PtType, finalSql)
- if res == nil || len(res) == 0 {
- return nil, fmt.Errorf("未查询到项目")
- }
- Rest(res, &thisRow)
- if thisRow.Thismarket.Buckets != nil && len(thisRow.Thismarket.Buckets) != 0 {
- Projectmarket := thisRow.Thismarket.Buckets[0]
- if !isOffline && Projectmarket.ProjectCount.DocCount == 0 {
- return nil, fmt.Errorf("未查询到项目数据")
- }
- // 实时分析数据量 如果关键词少于100,项目数据量可能大于MAProjectNumLimit(600000)
- //if Projectmarket.ProjectCount.DocCount > MAProjectNumLimit {
- // return nil, fmt.Errorf("项目数量超出上限")
- //}
- rMapData["project_count"] = Projectmarket.ProjectCount.DocCount
- rMapData["projctamout"] = Projectmarket.ProjectAmount.Value
- rMapData["projectavgmoney"] = Projectmarket.ProjectAvgMoney.Value
- rMapData["buyercount"] = Projectmarket.BuyerCount.Value
- rMapData["winnercount"] = Projectmarket.WinnerCount.Value
- if thisRow.Oldmarket.Buckets != nil && len(thisRow.Oldmarket.Buckets) != 0 {
- oldProjectmarket := thisRow.Oldmarket.Buckets[0]
- //环比数据
- rMapData["projctamount_ratio"] = sequential(Projectmarket.ProjectAmount.Value, oldProjectmarket.ProjectAmount.Value)
- rMapData["project_count_ratio"] = sequential(float64(Projectmarket.ProjectCount.DocCount), float64(oldProjectmarket.ProjectCount.DocCount))
- rMapData["projectavgmoney_ratio"] = sequential(Projectmarket.ProjectAvgMoney.Value, oldProjectmarket.ProjectAvgMoney.Value)
- rMapData["buyercount_ratio"] = sequential(float64(Projectmarket.BuyerCount.Value), float64(oldProjectmarket.BuyerCount.Value))
- rMapData["winnercount_ratio"] = sequential(float64(Projectmarket.WinnerCount.Value), float64(oldProjectmarket.WinnerCount.Value))
- }
- }
- rMap["market_profile"] = rMapData
- if thisRow.Monthtime.Buckets != nil && len(thisRow.Monthtime.Buckets) != 0 {
- rMap["month_distribution"] = n_mae.TimeData(monthB, thisRow.Monthtime.Buckets)
- }
- if thisRow.Yeartime.Buckets != nil && len(thisRow.Yeartime.Buckets) != 0 {
- rMap["year_distribution"] = n_mae.TimeData(yearB, thisRow.Yeartime.Buckets)
- }
- return rMap, nil
- }
- // 时间分布月,年通用数据处理
- func (a *AnalysisEntity) TimeData(_b bool, thisRow []Buckets) map[string]interface{} {
- var count_ss, amout_ss []map[string]interface{}
- for k, v := range thisRow {
- //环比多取一期数据
- if _b && k == 0 {
- continue
- }
- count := make(map[string]interface{})
- amount := make(map[string]interface{})
- count["minth"] = v.Key
- count["value"] = v.ScaleTotal.DocCount
- amount["minth"] = v.Key
- amount["value"] = v.ScaleAmount.Value
- //整月,年统计环比
- if _b {
- doccount := thisRow[k-1].ScaleTotal.DocCount
- amountvalue := thisRow[k-1].ScaleAmount.Value
- count["ratio"] = sequential(float64(v.ScaleTotal.DocCount), float64(doccount))
- amount["ratio"] = sequential(v.ScaleAmount.Value, amountvalue)
- }
- count_ss = append(count_ss, count)
- amout_ss = append(amout_ss, amount)
- }
- rMapData := make(map[string]interface{})
- rMapData["project_count"] = count_ss
- rMapData["project_amount"] = amout_ss
- return rMapData
- }
- // top10
- func (a *AnalysisEntity) ProjectTop10() (rMap map[string]interface{}, err error) {
- finalSql := fmt.Sprintf(a.GetCommonQuerySql(), queryTop10)
- log.Println("ProjectTop10:", finalSql)
- hits := elastic.Get(PtIndex, PtType, finalSql)
- if hits == nil || len(*hits) == 0 {
- return
- }
- rMap = map[string]interface{}{}
- bArr := []map[string]interface{}{}
- source := *hits
- for _, v := range source {
- bA := map[string]interface{}{}
- if v["ids"] != nil && len(InterToSliceString(v["ids"])) > 0 {
- idss := InterToSliceString(v["ids"])
- bA["_id"] = encodeId(idss[len(idss)-1])
- } else {
- bA["_id"] = nil
- }
- if v["area"] == "" {
- bA["city"] = nil
- } else {
- bA["area"] = v["area"]
- }
- if v["city"] == "" {
- bA["city"] = nil
- } else {
- bA["city"] = v["city"]
- }
- bA["jgtime"] = v["jgtime"]
- bA["projectname"] = v["s_projectname"]
- bA["sortprice"] = v["sortprice"]
- ids := v["entidlist"]
- var id_s []string
- var winner_s []string
- for _, i := range InterToSliceString(ids) {
- iid := encodeId(i)
- id_s = append(id_s, iid)
- }
- bA["eidlist"] = id_s
- bA["winner_s"] = nil
- if common.ObjToString(v["s_winner"]) != "" {
- w_s := strings.Split(common.ObjToString(v["s_winner"]), ",")
- for _, vv := range w_s {
- winner_s = append(winner_s, vv)
- }
- bA["winner_s"] = winner_s
- }
- bArr = append(bArr, bA)
- }
- rMap["ProjectTop10"] = bArr
- return
- }
- func (a *AnalysisEntity) AllData() (rMap map[string]interface{}, err error) {
- rMap = map[string]interface{}{}
- var aggs []string
- area := a.FormatParam.Area
- city := a.FormatParam.City
- buyclass := a.FormatParam.BuyerClass
- aggs = append(aggs, aggsAllCM, fmt.Sprintf(queryAggsSortprice, sortpriceStr), aggsArea)
- if (len(area) + len(city)) != 1 {
- aaat3 := fmt.Sprintf(aggsAreaAmounttop3, Top30)
- aact3 := fmt.Sprintf(aggsAreaCounttop3, Top30)
- if a.Offline == ValueOffline {
- aaat3 = fmt.Sprintf(aggsAreaAmounttop3, Top30)
- aact3 = fmt.Sprintf(aggsAreaCounttop3, Top30)
- }
- aggs = append(aggs, aaat3, aact3)
- }
- if len(buyclass) != 1 {
- abat3 := fmt.Sprintf(aggsBuyerclassAmounttop3, Top30)
- abct3 := fmt.Sprintf(aggsBuyerclassCounttop3, Top30)
- if a.Offline == ValueOffline {
- abat3 = fmt.Sprintf(aggsBuyerclassAmounttop3, Top30)
- abct3 = fmt.Sprintf(aggsBuyerclassCounttop3, Top30)
- }
- //aggs = append(aggs, aggs_buyerclass, aggs_buyerclass_other, aggs_buyerclass_amounttop3, aggs_buyerclass_counttop3)
- aggs = append(aggs, aggsBuyerclass, abat3, abct3)
- }
- finalSql := fmt.Sprintf(a.GetCommonQuerySqlWithAggs(), strings.Join(aggs, ","))
- log.Println("allData sql:", finalSql)
- res := GetAggs(PtIndex, PtType, finalSql)
- if res == nil || len(res) == 0 {
- return
- }
- thisRow := AreaCTop{}
- for name, object := range res {
- bArr, err := object.MarshalJSON()
- if len(bArr) == 0 || err != nil {
- continue
- }
- if name == "project_amount" {
- if json.Unmarshal(bArr, &thisRow.Amount) != nil {
- continue
- }
- } else if name == "project_count" {
- if json.Unmarshal(bArr, &thisRow.ProjectCount) != nil {
- continue
- }
- //} else if name == "buyerclass_scale_other" {
- // if json.Unmarshal(bArr, &thisRow.BuyerclassScaleOther) != nil {
- // continue
- // }
- } else if name == "project_count_not0" {
- if json.Unmarshal(bArr, &thisRow.CountNot0) != nil {
- continue
- }
- } else if name == "sortprice_ranges" {
- if json.Unmarshal(bArr, &thisRow.SortpriceRanges) != nil {
- continue
- }
- } else if name == "area_distribution" {
- if json.Unmarshal(bArr, &thisRow.AreaDistribution) != nil {
- continue
- }
- } else if name == "buyerclass_scale" {
- if json.Unmarshal(bArr, &thisRow.BuyerclassScale) != nil {
- continue
- }
- } else if name == "area_amount_top3" {
- if json.Unmarshal(bArr, &thisRow.AreaAmountTop3) != nil {
- continue
- }
- } else if name == "area_count_top3" {
- if json.Unmarshal(bArr, &thisRow.AreaCountTop3) != nil {
- continue
- }
- } else if name == "buyerclass_amount_top3" {
- if json.Unmarshal(bArr, &thisRow.BuyclassAmountTop3) != nil {
- continue
- }
- } else if name == "buyerclass_count_top3" {
- if json.Unmarshal(bArr, &thisRow.BuyclassCountTop3) != nil {
- continue
- }
- }
- }
- thisRow.Total = int64(thisRow.ProjectCount.DocCount)
- data := ProjectScale(thisRow)
- area_data := AreaDistribute(thisRow)
- customerData, customerOther := CustomerDistribute(thisRow)
- //customerOther, customerData := CustomerDistributeDetails(thisRow, customerDetails)
- var ids []string
- for _, v := range thisRow.AreaAmountTop3.Buckets {
- for _, va := range v.WinnerTop.Buckets {
- ids = append(ids, va.Winner)
- }
- }
- for _, v := range thisRow.BuyclassAmountTop3.Buckets {
- for _, va := range v.WinnerTop.Buckets {
- ids = append(ids, va.Winner)
- }
- }
- for _, v := range thisRow.AreaCountTop3.Buckets {
- for _, va := range v.WinnerTop.Buckets {
- ids = append(ids, va.Winner)
- }
- }
- for _, v := range thisRow.BuyclassCountTop3.Buckets {
- for _, va := range v.BidcountTop.Buckets {
- ids = append(ids, va.Winner)
- }
- }
- eid := IDToName(ids)
- rMap["projectScale"] = data
- rMap["area_infos"] = area_data
- rMap["customer_scale"] = customerData
- rMap["customer_scale_other"] = customerOther //客户分布(其它)
- rMap["scaleAreaAmountTop"] = AmountCompute(thisRow, "area", eid, a.Offline == ValueOffline)
- rMap["scaleBuyclassAmountTop"] = AmountCompute(thisRow, "buyclass", eid, a.Offline == ValueOffline)
- rMap["scaleAreaCountTop"] = CountCompute(thisRow, "area", eid, a.Offline == ValueOffline)
- rMap["scaleBuyclassCountTop"] = CountCompute(thisRow, "buyclass", eid, a.Offline == ValueOffline)
- if a.Offline == ValueOffline {
- rMap["count_not_0"] = thisRow.CountNot0.Count
- }
- return
- }
- // MarketScaleRefineQuery 细化聚合
- func (a *AnalysisEntity) MarketScaleRefineQuery() (rMap map[string]interface{}, err error) {
- //关键词分组聚合
- var aggsGroup []string
- //获取总金额及总数
- aggsGroup = append(aggsGroup, `"projectAmount":{"sum":{"field":"sortprice"}}`)
- aggsGroup = append(aggsGroup, `"projectTotal":{"filter":{"match_all":{}}}`)
- itemDataMap := map[string]int64{}
- for _, group := range a.FormatParam.KeysItems {
- var bools []string
- for _, v := range getGroupKeywordArr(group.A_Key) {
- if sql := getKeyWordSql(v, a.BaseParam.MatchingMode); sql != "" {
- bools = append(bools, sql)
- }
- }
- if len(bools) > 0 {
- //临时调整 进行数据验证 Top3
- rwt := Top30
- rwa := Top30
- if a.Offline == ValueOffline { //离线
- rwt = Top30
- rwa = Top30
- }
- aggsGroup = append(aggsGroup, fmt.Sprintf(`"%s":{"filter":{"bool":{"should":[%s],"minimum_should_match": 1}},"aggs":{"project_count":{"filter":{"match_all":{}}},"project_amount":{"sum":{"field":"sortprice"}},"winner_total_top":{"terms":{"field":"entidlist","exclude":["-"],"order":[{"refine_winner_total":"desc"}],"size":%d},"aggs":{"refine_winner_total":{"filter":{"match_all":{}}}}},"winner_amount_top":{"terms":{"field":"entidlist","exclude":["-"],"order":[{"refine_winner_amount":"desc"}],"size":%d},"aggs":{"refine_winner_amount":{"sum":{"field":"sortprice"}}}}}}`, group.ItemName, strings.Join(bools, ","), rwt, rwa))
- }
- itemDataMap[group.ItemName] = group.UpdateTime
- }
- finalSql := fmt.Sprintf(a.GetCommonQuerySqlWithAggs(), strings.Join(aggsGroup, ","))
- fmt.Println("finalSql-----4", finalSql)
- rMap = map[string]interface{}{}
- res := GetAggs(PtIndex, PtType, finalSql)
- if res == nil || len(res) == 0 {
- return
- }
- scale := scaleRefineData{IdSwitch: map[string]string{}, IsOffline: a.Offline == ValueOffline}
- for name, object := range res {
- bArr, err := object.MarshalJSON()
- if len(bArr) == 0 || err != nil {
- continue
- }
- if name == "projectTotal" {
- st := simpleTotal{}
- if err := json.Unmarshal(bArr, &st); err == nil {
- scale.Total = st
- }
- continue
- } else if name == "projectAmount" {
- ss := simpleSum{}
- if err := json.Unmarshal(bArr, &ss); err == nil {
- scale.Amount = ss
- }
- continue
- }
- thisRow := scaleRefineRow{}
- if err := json.Unmarshal(bArr, &thisRow); err != nil {
- continue
- }
- thisRow.ItemName = name
- thisRow.UpdateTime = itemDataMap[name]
- scale.Data = append(scale.Data, &thisRow)
- }
- scale.formatData() //获取所需数据
- scale.doIdSwitch() //补充企业名称
- return map[string]interface{}{
- "scaleRefineAll": scale.ReturnData.Overall,
- "scaleRefineTotalTop": scale.ReturnData.TotalTop,
- "scaleRefineAmountTop": scale.ReturnData.AmountTop,
- }, nil
- }
- // 采购单位分析
- func (a *AnalysisEntity) BuyerWinnerAnalysis() map[string]interface{} {
- var datas []string
- //采购单位-采购规模分布
- //buyer_scalefmt := fmt.Sprintf(buyer_procurement_scale, sortprice_str)
- //采购单位-项目数量 采购单位-项目金额
- bc := fmt.Sprintf(buyerCount, Top50, Top30)
- bs := fmt.Sprintf(buyerSortprice, Top50, Top30)
- if a.Offline == ValueOffline {
- bc = fmt.Sprintf(buyerCount, BWCount, Top30)
- bs = fmt.Sprintf(buyerSortprice, BWCount, Top30)
- }
- bps := fmt.Sprintf(buyerProcurementScale, BWDCount)
- datas = append(datas, bps, bc, bs)
- //中标单位-规模分布
- //winner_scalefmt := fmt.Sprintf(winner_procurement_scale, sortprice_str)
- //中标单位-项目数量 中标单位-项目金额
- wc := fmt.Sprintf(winnerCount, Top50, Top30) //正常需求30-3;目前是50-30,多获取数据 分析后进行数据损失补充,尽量减少 实时分析和离线分析的误差
- ws := fmt.Sprintf(winnerSortprice, Top50, Top30)
- if a.Offline == ValueOffline {
- wc = fmt.Sprintf(winnerCount, BWCount, Top30)
- ws = fmt.Sprintf(winnerSortprice, BWCount, Top30)
- }
- wps := fmt.Sprintf(winnerProcurementScale, BWDCount)
- datas = append(datas, wps, wc, ws)
- finalSql := fmt.Sprintf(a.GetCommonQuerySqlWithAggs(), strings.Join(datas, ","))
- log.Printf("final PurchasingAnalysiseQuery sql: %s", finalSql)
- t := time.Now()
- res := GetAggs(PtIndex, PtType, finalSql)
- if res == nil || len(res) == 0 {
- return nil
- }
- //计算entidlist大于1的中标单位金额
- entArrMap := make(map[string]float64)
- winnerKeyMap := make(map[string]int)
- newSql := strings.ReplaceAll(fmt.Sprintf(a.GetCommonQuerySql(), `,"sort": [{"sortprice": {"order": "desc"}}], "_source": ["entidlist","sortprice"],"size":10000`), `],"should":[`, fmt.Sprintf(`%s],"should":[`, `,{"script": {"script": {"source": "doc['entidlist'].length > 1"}}}`))
- log.Println("winner new sql", newSql)
- multiBid := elastic.Get(PtIndex, PtType, newSql)
- if multiBid != nil && len(*multiBid) > 0 {
- for _, m := range *multiBid {
- entidlist, _ := m["entidlist"].([]interface{})
- entArr := common.ObjArrToStringArr(entidlist)
- sortprice := common.Float64All(m["sortprice"])
- entLen := len(entArr)
- switch entLen {
- case 1:
- entArrMap[entArr[0]] = sortprice
- //winnerKeyMap[entArr[0]]++
- case 0:
- default:
- assessedAmount := sortprice / common.Float64All(entLen)
- for _, m2 := range entArr {
- //winnerKeyMap[m2]++
- entArrMap[m2] = assessedAmount
- }
- }
- }
- }
- log.Println("采购单位-中标单位分析报告es查询耗时===", time.Since(t))
- var thisBuyerWinnerRow BuyerWinnerRow
- for name, object := range res {
- bArr, err := object.MarshalJSON()
- if len(bArr) == 0 || err != nil {
- continue
- }
- if name == "buyer_amount_distribution" {
- if json.Unmarshal(bArr, &thisBuyerWinnerRow.BuyerAmountDistribution) != nil {
- continue
- }
- } else if name == "buyer_count_top3" {
- if json.Unmarshal(bArr, &thisBuyerWinnerRow.BuyerCountTop3) != nil {
- continue
- }
- } else if name == "buyer_amount_top3" {
- if json.Unmarshal(bArr, &thisBuyerWinnerRow.BuyerAmountTop3) != nil {
- continue
- }
- } else if name == "winner_amount_distribution" {
- if json.Unmarshal(bArr, &thisBuyerWinnerRow.WinnerAmountDistribution) != nil {
- continue
- }
- } else if name == "winner_count_top3" {
- if json.Unmarshal(bArr, &thisBuyerWinnerRow.WinnerCountTop3) != nil {
- continue
- }
- } else if name == "winner_amount_top3" {
- if json.Unmarshal(bArr, &thisBuyerWinnerRow.WinnerAmountTop3) != nil {
- continue
- }
- }
- }
- var winnerKeys []string
- for _, v := range thisBuyerWinnerRow.BuyerCountTop3.Buckets {
- for _, v1 := range v.SWinnerTop.Buckets {
- winnerKeyMap[v1.Key]++
- }
- }
- for _, v := range thisBuyerWinnerRow.BuyerAmountTop3.Buckets {
- for _, v1 := range v.SWinnerTop.Buckets {
- winnerKeyMap[v1.Key]++
- }
- }
- for _, v := range thisBuyerWinnerRow.WinnerCountTop3.SWinnerCount {
- winnerKeyMap[v.Key]++
- }
- for _, v := range thisBuyerWinnerRow.WinnerAmountTop3.SWinnerAmount {
- winnerKeyMap[v.Key]++
- }
- for k := range winnerKeyMap {
- winnerKeys = append(winnerKeys, k)
- }
- winnerName := GetEntNameByIds(winnerKeys)
- //rMap := make(map[string]interface{})
- var rMap = sync.Map{}
- sy := sync.WaitGroup{}
- sy.Add(2)
- go BuyerAnalysis(thisBuyerWinnerRow, &rMap, winnerName, &sy, a.Offline == ValueOffline)
- go WinningAnalysis(thisBuyerWinnerRow, &rMap, entArrMap, winnerName, &sy, a.Offline == ValueOffline)
- sy.Wait()
- log.Println("采购单位-中标单位分析报告程序计算耗时===", time.Since(t))
- rMaps := make(map[string]interface{})
- rMap.Range(func(key, value interface{}) bool {
- rMaps[common.InterfaceToStr(key)] = value
- return true
- })
- return rMaps
- }
- func (a *AnalysisEntity) GetPdfPageApi() (finalDate map[string]interface{}, err error) {
- var (
- wg = sync.WaitGroup{}
- lock = &sync.Mutex{}
- )
- finalDate = make(map[string]interface{})
- for i := 1; i <= 5; i++ {
- wg.Add(1)
- go func(flag int) {
- defer wg.Done()
- mgoData, _ := a.GetMongoData(flag)
- lock.Lock()
- for s, i2 := range mgoData {
- finalDate[s] = i2
- }
- lock.Unlock()
- }(i)
- }
- wg.Wait()
- return
- }
|