|
@@ -5,7 +5,6 @@ import (
|
|
|
"encoding/json"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
- "github.com/gogf/gf/v2/util/gconv"
|
|
|
"log"
|
|
|
"math"
|
|
|
"regexp"
|
|
@@ -15,24 +14,33 @@ import (
|
|
|
"sync"
|
|
|
"time"
|
|
|
|
|
|
- qutil "app.yhyue.com/moapp/jybase/common"
|
|
|
. "app.yhyue.com/moapp/jybase/date"
|
|
|
. "app.yhyue.com/moapp/jybase/encrypt"
|
|
|
+
|
|
|
+ "github.com/gogf/gf/v2/util/gconv"
|
|
|
+
|
|
|
+ qutil "app.yhyue.com/moapp/jybase/common"
|
|
|
elastic "app.yhyue.com/moapp/jybase/es"
|
|
|
mg "app.yhyue.com/moapp/jybase/mongodb"
|
|
|
"app.yhyue.com/moapp/jypkg/common/src/qfw/util/jy"
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
- SearchModeAccurate = 0 // 搜索模式:0:精准搜索;
|
|
|
- SearchModeFuzzy = 1 // 搜索模式:1:模糊搜索
|
|
|
- WordsModeAnd = 0 // 搜索关键词模式;默认0:包含所有
|
|
|
- WordsModeOr = 1 // 搜索关键词模式;1:包含任意
|
|
|
- SearchGroupAll = 0 // 搜索分组:默认0:全部;
|
|
|
- SearchGroupBidding = 1 // 搜索分组:1:招标采购公告;2:超前项目
|
|
|
- SearchGroupLeadingProject = 2 // 搜索分组:1:招标采购公告;2:超前项目
|
|
|
- TopTypesBidding = "招标预告,招标公告,招标结果,招标信用信息"
|
|
|
- TopTypesLeadingProject = "拟建项目,采购意向"
|
|
|
+ SearchModeAccurate = 0 // 搜索模式:0:精准搜索;
|
|
|
+ SearchModeFuzzy = 1 // 搜索模式:1:模糊搜索
|
|
|
+ WordsModeAnd = 0 // 搜索关键词模式;默认0:包含所有
|
|
|
+ WordsModeOr = 1 // 搜索关键词模式;1:包含任意
|
|
|
+ SearchGroupAll = 0 // 搜索分组:默认0:全部;
|
|
|
+ SearchGroupBidding = 1 // 搜索分组:1:招标采购公告;2:超前项目
|
|
|
+ SearchGroupLeadingProject = 2 // 搜索分组:1:招标采购公告;2:超前项目
|
|
|
+ SearchGroupAnnouncementProject = 3 // 搜索分组:1:招标采购公告;2:超前项目 移动3:公告 4 预告 5结果
|
|
|
+ SearchGroupPreviewsProject = 4 // 搜索分组:1:招标采购公告;2:超前项目移动3:公告 4 预告 5结果
|
|
|
+ SearchGroupResultsProject = 5 // 搜索分组:1:招标采购公告;2:超前项目移动3:公告 4 预告 5结果
|
|
|
+ TopTypesBidding = "招标预告,招标公告,招标结果,招标信用信息"
|
|
|
+ TopTypesLeadingProject = "拟建项目,采购意向"
|
|
|
+ TopTypesAnnouncementProject = "招标公告"
|
|
|
+ TopTypesPreviewsProject = "招标预告"
|
|
|
+ TopTypesResultsProject = "招标结果"
|
|
|
)
|
|
|
|
|
|
/*筛选条件--关键词*/
|
|
@@ -52,6 +60,7 @@ type SieveCondition struct {
|
|
|
Industry []string `json:"industry"` //行业
|
|
|
Keyword []KeyWord `json:"keywords"` //关键词
|
|
|
Buyer []string `json:"buyer"` //招标单位(采购单位)
|
|
|
+ Agency []string `json:"agency"` //招标代理机构(采购单位)
|
|
|
Buyerclass []string `json:"buyerclass"` //采购单位类型
|
|
|
HasBuyerTel string `json:"hasBuyertel"` //是否有采购单位电话
|
|
|
Winner []string `json:"winner"` //中标单位
|
|
@@ -71,7 +80,9 @@ type SieveCondition struct {
|
|
|
SearchGroup int `json:"searchGroup"` // 搜索分组:默认0:全部;1:招标采购公告;2:超前项目
|
|
|
SearchMode int `json:"searchMode"` // 搜索模式:0:精准搜索;1:模糊搜索
|
|
|
WordsMode int `json:"wordsMode"` // 搜索关键词模式;默认0:包含所有,1:包含任意
|
|
|
- District []string `json:"district"`
|
|
|
+ District []string `json:"district"` //
|
|
|
+ UserId string `json:"s_userid"` //用户id 或 职位id
|
|
|
+ MgoUserId string `json:"mgoUserId"` //mgoUserId
|
|
|
}
|
|
|
|
|
|
const (
|
|
@@ -110,6 +121,23 @@ func DetailANDTitle(findfields string) bool {
|
|
|
return strings.Contains(findfields, "detail") && strings.Contains(findfields, "title")
|
|
|
}
|
|
|
|
|
|
+var getMatchPhraseSql = func(field string, val ...string) (sql string) {
|
|
|
+ if len(val) == 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var arr []string
|
|
|
+ for _, s := range val {
|
|
|
+ if s == "" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ arr = append(arr, fmt.Sprintf(`{"match_phrase": {"%s": "%s"}}`, field, s))
|
|
|
+ }
|
|
|
+ if len(arr) == 0 {
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+ return fmt.Sprintf(`{"bool": {"should": [%s],"minimum_should_match": 1}}`, strings.Join(arr, ","))
|
|
|
+}
|
|
|
+
|
|
|
// 获取数据导出查询语句
|
|
|
func getDataExportSql(scd *SieveCondition) string {
|
|
|
if len(scd.SelectIds) > 0 {
|
|
@@ -211,10 +239,24 @@ func getDataExportSql(scd *SieveCondition) string {
|
|
|
timequery += `}}}`
|
|
|
musts = append(musts, timequery)
|
|
|
if scd.Subtype == "" {
|
|
|
- if scd.SearchGroup == SearchGroupBidding { // 搜索分组处理 招标采购公告 超前项目
|
|
|
+ switch scd.SearchGroup {
|
|
|
+ case SearchGroupBidding:
|
|
|
scd.Subtype = TopTypesBidding
|
|
|
- } else if scd.SearchGroup == SearchGroupLeadingProject {
|
|
|
+ case SearchGroupLeadingProject:
|
|
|
scd.Subtype = TopTypesLeadingProject
|
|
|
+ case SearchGroupAnnouncementProject:
|
|
|
+ scd.Subtype = TopTypesAnnouncementProject
|
|
|
+ case SearchGroupPreviewsProject:
|
|
|
+ scd.Subtype = TopTypesPreviewsProject
|
|
|
+ case SearchGroupResultsProject:
|
|
|
+ scd.Subtype = TopTypesResultsProject
|
|
|
+
|
|
|
+ }
|
|
|
+ if scd.SearchGroup == SearchGroupBidding { // 搜索分组处理 招标采购公告 超前项目
|
|
|
+
|
|
|
+ } else if scd.SearchGroup == SearchGroupLeadingProject {
|
|
|
+
|
|
|
+ } else {
|
|
|
}
|
|
|
}
|
|
|
if scd.Subtype != "" {
|
|
@@ -241,14 +283,25 @@ func getDataExportSql(scd *SieveCondition) string {
|
|
|
if len(scd.Industry) > 0 {
|
|
|
musts = append(musts, fmt.Sprintf(query_bool_must, "s_subscopeclass", `"`+strings.Join(scd.Industry, `","`)+`"`))
|
|
|
}
|
|
|
- if len(scd.Buyer) > 0 {
|
|
|
- musts = append(musts, fmt.Sprintf(query_bool_must, "buyer", `"`+strings.Join(scd.Buyer, `","`)+`"`))
|
|
|
- }
|
|
|
if len(scd.Buyerclass) > 0 {
|
|
|
musts = append(musts, fmt.Sprintf(query_bool_must, "buyerclass", `"`+strings.Join(scd.Buyerclass, `","`)+`"`))
|
|
|
}
|
|
|
+ //P492招标采购搜索匹配采购单位等优化 新增buyer、agency、winner模糊搜索,数据导出同步改为模糊
|
|
|
+ //query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
|
|
|
+ if len(scd.Buyer) > 0 {
|
|
|
+ if sql := getMatchPhraseSql("buyer.mbuyer", scd.Buyer...); sql != "" {
|
|
|
+ musts = append(musts, sql)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if len(scd.Agency) > 0 {
|
|
|
+ if sql := getMatchPhraseSql("agency.magency", scd.Agency...); sql != "" {
|
|
|
+ musts = append(musts, sql)
|
|
|
+ }
|
|
|
+ }
|
|
|
if len(scd.Winner) > 0 {
|
|
|
- musts = append(musts, fmt.Sprintf(query_bool_must, "s_winner", `"`+strings.Join(scd.Winner, `","`)+`"`))
|
|
|
+ if sql := getMatchPhraseSql("s_winner.mwinner", scd.Winner...); sql != "" {
|
|
|
+ musts = append(musts, sql)
|
|
|
+ }
|
|
|
}
|
|
|
_minPrice := ""
|
|
|
_maxPrice := ""
|
|
@@ -495,6 +548,7 @@ func GetSqlObjFromId(mongo mg.MongodbSim, _id string) *SieveCondition {
|
|
|
SelectType: qutil.ObjToString((*query)["selectType"]),
|
|
|
PublishTime: qutil.ObjToString((*query)["publishtime"]),
|
|
|
Buyer: getStringArrFromDbResult((*query)["buyer"]),
|
|
|
+ Agency: getStringArrFromDbResult((*query)["agency"]),
|
|
|
Buyerclass: getStringArrFromDbResult((*query)["buyerclass"]),
|
|
|
HasBuyerTel: qutil.ObjToString((*query)["hasBuyertel"]),
|
|
|
Winner: getStringArrFromDbResult((*query)["winner"]),
|
|
@@ -505,11 +559,13 @@ func GetSqlObjFromId(mongo mg.MongodbSim, _id string) *SieveCondition {
|
|
|
PushKeyWords: getStringArrFromDbResult((*query)["pushKeyWords"]),
|
|
|
FileExists: qutil.ObjToString((*query)["fileExists"]),
|
|
|
SearchTypeSwitch: searchTypeSwitch,
|
|
|
- BidField: qutil.ObjToString((*query)["bid_field"]), // 领域化数据
|
|
|
- SearchGroup: qutil.IntAll((*query)["searchGroup"]), //搜索分组:默认0:全部;1:招标采购公告;2:超前项目
|
|
|
- SearchMode: qutil.IntAll((*query)["searchMode"]), // 搜索模式:0:精准搜索;1:模糊搜索
|
|
|
- WordsMode: qutil.IntAll((*query)["wordsMode"]), // 搜索关键词模式;默认0:包含所有,1:包含任意
|
|
|
- District: gconv.Strings((*query)["district"]),
|
|
|
+ BidField: qutil.ObjToString((*query)["bid_field"]), // 领域化数据
|
|
|
+ SearchGroup: qutil.IntAll((*query)["searchGroup"]), //搜索分组:默认0:全部;1:招标采购公告;2:超前项目
|
|
|
+ SearchMode: qutil.IntAll((*query)["searchMode"]), // 搜索模式:0:精准搜索;1:模糊搜索
|
|
|
+ WordsMode: qutil.IntAll((*query)["wordsMode"]), // 搜索关键词模式;默认0:包含所有,1:包含任意
|
|
|
+ District: gconv.Strings((*query)["district"]), //
|
|
|
+ UserId: qutil.InterfaceToStr((*query)["s_userid"]), //
|
|
|
+ MgoUserId: qutil.InterfaceToStr((*query)["mgoUserId"]), //
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -535,7 +591,7 @@ func GetDataExportSearchCountBySieveCondition(scd *SieveCondition, elasticAddres
|
|
|
}
|
|
|
// 依据用户选择的搜索模式和搜索范围进行匹配,即不限制只能匹配标题,且不限制最多展示100条、针对输入的单个关键词分词后需要都包含
|
|
|
//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
|
|
|
- if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && scd.SearchMode == SearchModeFuzzy {
|
|
|
+ if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0 || IsOnTheWhitelist(scd.UserId, scd.MgoUserId)) && scd.SearchMode == SearchModeFuzzy {
|
|
|
if len(scd.Keyword) != 0 {
|
|
|
// 关键词分词
|
|
|
searchTextSize := 0
|
|
@@ -628,23 +684,30 @@ func GetDataExportSelectReallyCountFromEs(ids []string) int64 {
|
|
|
wait := &sync.WaitGroup{}
|
|
|
var total int64
|
|
|
var lock sync.Mutex
|
|
|
- for _, v := range SplitArray(ids, 200) {
|
|
|
- pool <- true
|
|
|
- wait.Add(1)
|
|
|
- go func(arr []string) {
|
|
|
- defer func() {
|
|
|
- wait.Done()
|
|
|
- <-pool
|
|
|
- }()
|
|
|
- query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}}}`, strings.Join(arr, "\",\""))
|
|
|
- tCount := elastic.Count(INDEX, TYPE, query)
|
|
|
- if tCount > 0 {
|
|
|
- lock.Lock()
|
|
|
- total += tCount
|
|
|
- lock.Unlock()
|
|
|
- }
|
|
|
- return
|
|
|
- }(v)
|
|
|
+ var idArr []string
|
|
|
+ for i, id := range ids {
|
|
|
+ idArr = append(idArr, id)
|
|
|
+ if len(idArr) == 200 || i+1 == len(ids) {
|
|
|
+ pool <- true
|
|
|
+ wait.Add(1)
|
|
|
+ go func(arr []string) {
|
|
|
+ defer func() {
|
|
|
+ wait.Done()
|
|
|
+ <-pool
|
|
|
+ }()
|
|
|
+ log.Println("GetDataExportSelectReallyCountFromEs===", arr[0])
|
|
|
+ query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}}}`, strings.Join(arr, "\",\""))
|
|
|
+ tCount := elastic.Count(INDEX, TYPE, query)
|
|
|
+ if tCount > 0 {
|
|
|
+ lock.Lock()
|
|
|
+ total += tCount
|
|
|
+ lock.Unlock()
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }(idArr)
|
|
|
+ idArr = []string{}
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
wait.Wait()
|
|
|
log.Printf("GetDataExportSelectReallyCount 选择数据共%d条记录,实际查询%d条\n", len(ids), total)
|
|
@@ -665,47 +728,53 @@ func GetDataExportSelectReallyCountFromMongo(bid mg.MongodbSim, biddingName stri
|
|
|
)
|
|
|
pool := make(chan bool, 10)
|
|
|
wait := &sync.WaitGroup{}
|
|
|
-
|
|
|
- for _, i2 := range SplitArray(ids, 200) {
|
|
|
- pool <- true
|
|
|
- wait.Add(1)
|
|
|
- go func(arr []string) {
|
|
|
- defer func() {
|
|
|
- wait.Done()
|
|
|
- <-pool
|
|
|
- }()
|
|
|
- lenNum := int64(len(arr))
|
|
|
- var (
|
|
|
- queryIds []interface{}
|
|
|
- num1, num2 int64
|
|
|
- err error
|
|
|
- )
|
|
|
- for _, idStr := range arr {
|
|
|
- queryIds = append(queryIds, mg.StringTOBsonId(idStr))
|
|
|
- }
|
|
|
- num1, err = sess.DB(biddingName).C("bidding").Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
|
- "$in": queryIds,
|
|
|
- }}).Count()
|
|
|
- if err == nil {
|
|
|
- if num1 == lenNum {
|
|
|
- lock.Lock()
|
|
|
- count += num1
|
|
|
- lock.Unlock()
|
|
|
- return
|
|
|
+ var idArr []string
|
|
|
+ for i, id := range ids {
|
|
|
+ idArr = append(idArr, id)
|
|
|
+ if len(idArr) == 200 || i+1 == len(ids) {
|
|
|
+ pool <- true
|
|
|
+ wait.Add(1)
|
|
|
+ go func(arr []string) {
|
|
|
+ defer func() {
|
|
|
+ wait.Done()
|
|
|
+ <-pool
|
|
|
+ }()
|
|
|
+ log.Println("GetDataExportSelectReallyCountFromMongo===", arr[0])
|
|
|
+ lenNum := int64(len(arr))
|
|
|
+ var (
|
|
|
+ queryIds []interface{}
|
|
|
+ num1, num2 int64
|
|
|
+ err error
|
|
|
+ )
|
|
|
+ for _, idStr := range arr {
|
|
|
+ queryIds = append(queryIds, mg.StringTOBsonId(idStr))
|
|
|
}
|
|
|
- num2, err = sess.DB(biddingName).C("bidding_back").Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
|
+ num1, err = sess.DB(biddingName).C("bidding").Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
|
"$in": queryIds,
|
|
|
}}).Count()
|
|
|
if err == nil {
|
|
|
- lock.Lock()
|
|
|
- count += qutil.If(num2+num1 >= lenNum, lenNum, num2+num1).(int64)
|
|
|
- lock.Unlock()
|
|
|
+ if num1 == lenNum {
|
|
|
+ lock.Lock()
|
|
|
+ count += num1
|
|
|
+ lock.Unlock()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ num2, err = sess.DB(biddingName).C("bidding_back").Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
|
+ "$in": queryIds,
|
|
|
+ }}).Count()
|
|
|
+ if err == nil {
|
|
|
+ lock.Lock()
|
|
|
+ count += qutil.If(num2+num1 >= lenNum, lenNum, num2+num1).(int64)
|
|
|
+ lock.Unlock()
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- }(i2)
|
|
|
+ }(idArr)
|
|
|
+ idArr = []string{}
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
wait.Wait()
|
|
|
- return qutil.If(count > 0, count, -2).(int64)
|
|
|
+ return qutil.If(count > 0, count, ResCount).(int64)
|
|
|
}
|
|
|
|
|
|
func GetDataExportSelectResultFromEs(bidding mg.MongodbSim, biddingName string, scd *SieveCondition, dataType string, checkCount int) (*[]map[string]interface{}, error) {
|
|
@@ -716,19 +785,15 @@ func GetDataExportSelectResultFromEs(bidding mg.MongodbSim, biddingName string,
|
|
|
if checkCount == -1 && len(scd.SelectIds) > 500 {
|
|
|
scd.SelectIds = scd.SelectIds[:500]
|
|
|
}
|
|
|
- pool := make(chan bool, 10)
|
|
|
- wait := &sync.WaitGroup{}
|
|
|
- var lock sync.Mutex
|
|
|
+
|
|
|
returnLsit := make([]map[string]interface{}, 0, len(scd.SelectIds))
|
|
|
- for _, v := range SplitArray(scd.SelectIds, 200) {
|
|
|
- pool <- true
|
|
|
- wait.Add(1)
|
|
|
- go func(arr []string) error {
|
|
|
- defer func() {
|
|
|
- wait.Done()
|
|
|
- <-pool
|
|
|
- }()
|
|
|
- query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}},"_source": [%s],"size":%d}`, strings.Join(arr, "\",\""), bidField, len(arr))
|
|
|
+ var idArr []string
|
|
|
+ for i, id := range scd.SelectIds {
|
|
|
+ idArr = append(idArr, id)
|
|
|
+ if len(idArr) == 200 || i+1 == len(scd.SelectIds) {
|
|
|
+
|
|
|
+ log.Println(scd.Id, "GetDataExportSelectResultFromEs===", idArr[0])
|
|
|
+ query := fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"id":["%s"]}}]}},"_source": [%s],"size":%d}`, strings.Join(idArr, "\",\""), bidField, len(idArr))
|
|
|
log.Println("GetDataExportSelectResultFromEs 数据流量包 es count 信息查询:", query)
|
|
|
data := *elastic.Get(INDEX, TYPE, query)
|
|
|
if data != nil && len(data) > 0 {
|
|
@@ -738,16 +803,13 @@ func GetDataExportSelectResultFromEs(bidding mg.MongodbSim, biddingName string,
|
|
|
if detail != "" {
|
|
|
bv["detail"] = contentfilterReg.ReplaceAllString(detail, "")
|
|
|
}
|
|
|
- lock.Lock()
|
|
|
returnLsit = append(returnLsit, bv)
|
|
|
- lock.Unlock()
|
|
|
}
|
|
|
}
|
|
|
- return nil
|
|
|
- }(v)
|
|
|
+ idArr = []string{}
|
|
|
+ }
|
|
|
}
|
|
|
- wait.Wait()
|
|
|
- if len(returnLsit) == checkCount || checkCount == -1 {
|
|
|
+ if len(returnLsit) == checkCount || checkCount == -1 || checkCount == -2 {
|
|
|
return &returnLsit, nil
|
|
|
} else {
|
|
|
return nil, fmt.Errorf("GetDataExportSelectResultFromEs 选择数据导出异常 数据量期望%d条,实际查询%d条", checkCount, len(returnLsit))
|
|
@@ -768,20 +830,18 @@ func GetDataExportSelectResultFromMongoDb(bidding mg.MongodbSim, biddingName str
|
|
|
if checkCount == -1 && len(scd.SelectIds) > 500 {
|
|
|
scd.SelectIds = scd.SelectIds[:500]
|
|
|
}
|
|
|
- pool := make(chan bool, 10)
|
|
|
- wait := &sync.WaitGroup{}
|
|
|
- var lock sync.Mutex
|
|
|
returnLsit := make([]map[string]interface{}, 0, len(scd.SelectIds))
|
|
|
- for _, v := range SplitArray(scd.SelectIds, 200) {
|
|
|
- pool <- true
|
|
|
- wait.Add(1)
|
|
|
- go func(arr []string) error {
|
|
|
- defer func() {
|
|
|
- wait.Done()
|
|
|
- <-pool
|
|
|
- }()
|
|
|
- var queryIds []interface{}
|
|
|
- for _, idStr := range arr {
|
|
|
+ var idArr []string
|
|
|
+ for i, id := range scd.SelectIds {
|
|
|
+ idArr = append(idArr, id)
|
|
|
+ if len(idArr) == 200 || i+1 == len(scd.SelectIds) {
|
|
|
+
|
|
|
+ log.Println(scd.Id, "GetDataExportSelectResultFromMongoDb===", idArr[0])
|
|
|
+ var (
|
|
|
+ queryIds []interface{}
|
|
|
+ count int
|
|
|
+ )
|
|
|
+ for _, idStr := range idArr {
|
|
|
queryIds = append(queryIds, mg.StringTOBsonId(idStr))
|
|
|
}
|
|
|
iter := sess.DB(biddingName).C("bidding").Select(selectMap).Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
@@ -793,66 +853,35 @@ func GetDataExportSelectResultFromMongoDb(bidding mg.MongodbSim, biddingName str
|
|
|
if detail != "" {
|
|
|
m["detail"] = contentfilterReg.ReplaceAllString(detail, "")
|
|
|
}
|
|
|
- lock.Lock()
|
|
|
+ count++
|
|
|
returnLsit = append(returnLsit, m)
|
|
|
- lock.Unlock()
|
|
|
m = make(map[string]interface{})
|
|
|
}
|
|
|
- iter_back := sess.DB(biddingName).C("bidding_back").Select(selectMap).Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
|
- "$in": queryIds,
|
|
|
- }}).Iter()
|
|
|
- for m := make(map[string]interface{}); iter_back.Next(&m); {
|
|
|
- m["_id"] = mg.BsonIdToSId(m["_id"])
|
|
|
- detail, _ := m["detail"].(string)
|
|
|
- if detail != "" {
|
|
|
- m["detail"] = contentfilterReg.ReplaceAllString(detail, "")
|
|
|
+ if count != len(idArr) {
|
|
|
+ iter_back := sess.DB(biddingName).C("bidding_back").Select(selectMap).Find(map[string]interface{}{"_id": map[string]interface{}{
|
|
|
+ "$in": queryIds,
|
|
|
+ }}).Iter()
|
|
|
+ for m := make(map[string]interface{}); iter_back.Next(&m); {
|
|
|
+ m["_id"] = mg.BsonIdToSId(m["_id"])
|
|
|
+ detail, _ := m["detail"].(string)
|
|
|
+ if detail != "" {
|
|
|
+ m["detail"] = contentfilterReg.ReplaceAllString(detail, "")
|
|
|
+ }
|
|
|
+ returnLsit = append(returnLsit, m)
|
|
|
+ m = make(map[string]interface{})
|
|
|
}
|
|
|
- lock.Lock()
|
|
|
- returnLsit = append(returnLsit, m)
|
|
|
- lock.Unlock()
|
|
|
- m = make(map[string]interface{})
|
|
|
}
|
|
|
- return nil
|
|
|
- }(v)
|
|
|
+
|
|
|
+ idArr = []string{}
|
|
|
+ }
|
|
|
}
|
|
|
- wait.Wait()
|
|
|
- if len(returnLsit) == checkCount || checkCount == -1 {
|
|
|
+ if len(returnLsit) == checkCount || checkCount == -1 || checkCount == -2 {
|
|
|
return &returnLsit, nil
|
|
|
} else {
|
|
|
return nil, fmt.Errorf("GetDataExportSelectResultFromMongoDb 选择数据导出异常 数据量期望%d条,实际查询%d条", checkCount, len(returnLsit))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// SplitArray 分割数组
|
|
|
-func SplitArray(arr []string, num int64) [][]string {
|
|
|
- max := int64(len(arr))
|
|
|
- //判断数组大小是否小于等于指定分割大小的值,是则把原数组放入二维数组返回
|
|
|
- if max <= num {
|
|
|
- return [][]string{arr}
|
|
|
- }
|
|
|
- //获取应该数组分割为多少份
|
|
|
- var quantity int64
|
|
|
- if max%num == 0 {
|
|
|
- quantity = max / num
|
|
|
- } else {
|
|
|
- quantity = (max / num) + 1
|
|
|
- }
|
|
|
- //声明分割好的二维数组
|
|
|
- var segments = make([][]string, 0)
|
|
|
- //声明分割数组的截止下标
|
|
|
- var start, end, i int64
|
|
|
- for i = 1; i <= quantity; i++ {
|
|
|
- end = i * num
|
|
|
- if i != quantity {
|
|
|
- segments = append(segments, arr[start:end])
|
|
|
- } else {
|
|
|
- segments = append(segments, arr[start:])
|
|
|
- }
|
|
|
- start = i * num
|
|
|
- }
|
|
|
- return segments
|
|
|
-}
|
|
|
-
|
|
|
func GetDataExportIds(elasticAddress string, scd *SieveCondition, checkCount int) ([]string, error) {
|
|
|
defer qutil.Catch()
|
|
|
if scd == nil {
|
|
@@ -869,7 +898,7 @@ func GetDataExportIds(elasticAddress string, scd *SieveCondition, checkCount int
|
|
|
}
|
|
|
//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
|
|
|
// 依据用户选择的搜索模式和搜索范围进行匹配,即不限制只能匹配标题,且不限制最多展示100条、针对输入的单个关键词分词后需要都包含
|
|
|
- if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
|
|
|
+ if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0 || IsOnTheWhitelist(scd.UserId, scd.MgoUserId)) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
|
|
|
if len(scd.Keyword) != 0 {
|
|
|
searchTextSize := 0
|
|
|
// 关键词分词
|
|
@@ -939,7 +968,7 @@ func GetDataExportSearchResult(bid mg.MongodbSim, bidMgoDBName, elasticAddress s
|
|
|
res = doSearchByBatch(qstr, dataType, checkCount, fmt.Sprintf("%s-%s", "GetDataExportSearchResult", scd.Id))
|
|
|
}
|
|
|
//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
|
|
|
- if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
|
|
|
+ if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0 || IsOnTheWhitelist(scd.UserId, scd.MgoUserId)) && len(scd.SelectIds) == 0 && scd.SearchMode == SearchModeFuzzy {
|
|
|
if len(scd.Keyword) != 0 {
|
|
|
searchTextSize := 0
|
|
|
// 关键词分词
|
|
@@ -1045,176 +1074,198 @@ func FormatExportData(entmg mg.MongodbSim, data *[]map[string]interface{}, webdo
|
|
|
if len(encry) > 0 {
|
|
|
isEncry = true
|
|
|
}
|
|
|
+ sort.Slice(*data, func(i, j int) bool {
|
|
|
+ time1 := qutil.Int64All((*data)[i]["publishtime"])
|
|
|
+ time2 := qutil.Int64All((*data)[j]["publishtime"])
|
|
|
+ return time1 > time2
|
|
|
+ })
|
|
|
var entCacheMap = map[string]map[string]interface{}{}
|
|
|
+ pool := make(chan bool, 5)
|
|
|
+ wait := &sync.WaitGroup{}
|
|
|
+ lock := &sync.Mutex{}
|
|
|
for index := 0; index < len(*data); index++ {
|
|
|
- v := (*data)[index]
|
|
|
- //有中标企业 且 高级字段查询
|
|
|
- if dataType == "2" {
|
|
|
- //查询企业公示 法人 公司电话 公司邮箱地址
|
|
|
- entidlist, ok := v["entidlist"].([]interface{})
|
|
|
- if ok && len(entidlist) > 0 {
|
|
|
- var winnerMaps []map[string]interface{}
|
|
|
- for _, entIdObj := range entidlist {
|
|
|
- entId := qutil.ObjToString(entIdObj)
|
|
|
- if entId == "" {
|
|
|
- continue
|
|
|
- }
|
|
|
- if entCacheMap[entId] != nil {
|
|
|
- winnerMaps = append(winnerMaps, entCacheMap[entId])
|
|
|
- } else if entDetail := elastic.Get("qyxy", "qyxy", fmt.Sprintf(`{"query":{"bool":{"must":[{"term":{"id":"%s"}}]}},"size":1,"_source":["company_name","company_email","company_phone","legal_person"]}`, entId)); entDetail != nil && len(*entDetail) > 0 {
|
|
|
- thisEntMap := map[string]interface{}{}
|
|
|
- legal_person := ""
|
|
|
- if (*entDetail)[0]["legal_person"] != nil {
|
|
|
- legal_person = (*entDetail)[0]["legal_person"].(string)
|
|
|
- if isEncry {
|
|
|
- var xx = "*"
|
|
|
- switch len([]rune(legal_person)) {
|
|
|
- case 3:
|
|
|
- xx = "**"
|
|
|
- case 4:
|
|
|
- xx = "***"
|
|
|
+ pool <- true
|
|
|
+ wait.Add(1)
|
|
|
+ go func(v map[string]interface{}) {
|
|
|
+ defer qutil.Catch()
|
|
|
+ defer func() {
|
|
|
+ <-pool
|
|
|
+ wait.Done()
|
|
|
+ }()
|
|
|
+ //有中标企业 且 高级字段查询
|
|
|
+ if dataType == "2" {
|
|
|
+ //查询企业公示 法人 公司电话 公司邮箱地址
|
|
|
+ entidlist, ok := v["entidlist"].([]interface{})
|
|
|
+ if ok && len(entidlist) > 0 {
|
|
|
+ var winnerMaps []map[string]interface{}
|
|
|
+ for _, entIdObj := range entidlist {
|
|
|
+ entId := qutil.ObjToString(entIdObj)
|
|
|
+ if entId == "" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ lock.Lock()
|
|
|
+ ecm := entCacheMap[entId]
|
|
|
+ lock.Unlock()
|
|
|
+ if ecm != nil {
|
|
|
+ winnerMaps = append(winnerMaps, ecm)
|
|
|
+ } else if entDetail := elastic.Get("qyxy", "qyxy", fmt.Sprintf(`{"query":{"bool":{"must":[{"term":{"id":"%s"}}]}},"size":1,"_source":["company_name","company_email","company_phone","legal_person"]}`, entId)); entDetail != nil && len(*entDetail) > 0 {
|
|
|
+ thisEntMap := map[string]interface{}{}
|
|
|
+ legal_person := ""
|
|
|
+ if (*entDetail)[0]["legal_person"] != nil {
|
|
|
+ legal_person = (*entDetail)[0]["legal_person"].(string)
|
|
|
+ if isEncry {
|
|
|
+ var xx = "*"
|
|
|
+ switch len([]rune(legal_person)) {
|
|
|
+ case 3:
|
|
|
+ xx = "**"
|
|
|
+ case 4:
|
|
|
+ xx = "***"
|
|
|
+ }
|
|
|
+ legal_person = string([]rune(legal_person)[:1]) + xx
|
|
|
}
|
|
|
- legal_person = string([]rune(legal_person)[:1]) + xx
|
|
|
}
|
|
|
- }
|
|
|
- company_phone := ""
|
|
|
- if (*entDetail)[0]["company_phone"] != nil {
|
|
|
- company_phone = (*entDetail)[0]["company_phone"].(string)
|
|
|
- if isEncry {
|
|
|
- if len([]rune(company_phone)) > 7 {
|
|
|
- company_phone = company_phone[:7] + "****"
|
|
|
- } else {
|
|
|
- company_phone = "****"
|
|
|
+ company_phone := ""
|
|
|
+ if (*entDetail)[0]["company_phone"] != nil {
|
|
|
+ company_phone = (*entDetail)[0]["company_phone"].(string)
|
|
|
+ if isEncry {
|
|
|
+ if len([]rune(company_phone)) > 7 {
|
|
|
+ company_phone = company_phone[:7] + "****"
|
|
|
+ } else {
|
|
|
+ company_phone = "****"
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- company_email := ""
|
|
|
- if (*entDetail)[0]["company_email"] != nil && (*entDetail)[0]["company_email"] != "无" {
|
|
|
- company_email = (*entDetail)[0]["company_email"].(string)
|
|
|
- if isEncry {
|
|
|
- if len(strings.Split(company_email, "@")) > 1 {
|
|
|
- company_email = "******" + "@" + strings.Split(company_email, "@")[1]
|
|
|
+ company_email := ""
|
|
|
+ if (*entDetail)[0]["company_email"] != nil && (*entDetail)[0]["company_email"] != "无" {
|
|
|
+ company_email = (*entDetail)[0]["company_email"].(string)
|
|
|
+ if isEncry {
|
|
|
+ if len(strings.Split(company_email, "@")) > 1 {
|
|
|
+ company_email = "******" + "@" + strings.Split(company_email, "@")[1]
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ company_name := ""
|
|
|
+ if (*entDetail)[0]["company_name"] != nil {
|
|
|
+ company_name = (*entDetail)[0]["company_name"].(string)
|
|
|
+ }
|
|
|
+ thisEntMap["legal_person"] = legal_person
|
|
|
+ thisEntMap["company_phone"] = company_phone
|
|
|
+ thisEntMap["company_email"] = company_email
|
|
|
+ thisEntMap["company_name"] = company_name
|
|
|
+ lock.Lock()
|
|
|
+ entCacheMap[entId] = thisEntMap
|
|
|
+ lock.Unlock()
|
|
|
+ winnerMaps = append(winnerMaps, thisEntMap)
|
|
|
}
|
|
|
- company_name := ""
|
|
|
- if (*entDetail)[0]["company_name"] != nil {
|
|
|
- company_name = (*entDetail)[0]["company_name"].(string)
|
|
|
- }
|
|
|
- thisEntMap["legal_person"] = legal_person
|
|
|
- thisEntMap["company_phone"] = company_phone
|
|
|
- thisEntMap["company_email"] = company_email
|
|
|
- thisEntMap["company_name"] = company_name
|
|
|
- entCacheMap[entId] = thisEntMap
|
|
|
- winnerMaps = append(winnerMaps, thisEntMap)
|
|
|
+ }
|
|
|
+ if len(winnerMaps) > 0 {
|
|
|
+ v["winnerMaps"] = winnerMaps
|
|
|
}
|
|
|
}
|
|
|
- if len(winnerMaps) > 0 {
|
|
|
- v["winnerMaps"] = winnerMaps
|
|
|
- }
|
|
|
+ delete(v, "entidlist")
|
|
|
}
|
|
|
- delete(v, "entidlist")
|
|
|
- }
|
|
|
- //====================字段补漏=========================
|
|
|
- if v["toptype"] == "结果" && dataType == "2" && !(v["agency"] != nil && v["budget"] != nil && v["buyerperson"] != nil && v["buyertel"] != nil) {
|
|
|
- r := elastic.Get("projectset", "projectset", fmt.Sprintf(`{"query":{"term":{"list.infoid":"%s"}},"_source": ["list"]}`, v["_id"]))
|
|
|
- if r != nil && len(*r) > 0 {
|
|
|
- MsgList := (*r)[0]["list"]
|
|
|
- if MsgList != nil {
|
|
|
- list := qutil.ObjArrToMapArr(MsgList.([]interface{}))
|
|
|
- for _, vv := range list {
|
|
|
- if vv["subtype"] == "招标" {
|
|
|
- if v["agency"] == nil && vv["agency"] != nil {
|
|
|
- v["agency"] = vv["agency"]
|
|
|
- }
|
|
|
- if v["budget"] == nil && vv["budget"] != nil {
|
|
|
- v["budget"] = vv["budget"]
|
|
|
- }
|
|
|
- if v["buyerperson"] == nil && vv["buyerperson"] != nil {
|
|
|
- v["buyerperson"] = vv["buyerperson"]
|
|
|
- }
|
|
|
- if v["buyertel"] == nil && vv["buyertel"] != nil {
|
|
|
- v["buyertel"] = vv["buyertel"]
|
|
|
+ //====================字段补漏=========================
|
|
|
+ if v["toptype"] == "结果" && dataType == "2" && !(v["agency"] != nil && v["budget"] != nil && v["buyerperson"] != nil && v["buyertel"] != nil) {
|
|
|
+ r := elastic.Get("projectset", "projectset", fmt.Sprintf(`{"query":{"term":{"list.infoid":"%s"}},"_source": ["list"]}`, v["_id"]))
|
|
|
+ if r != nil && len(*r) > 0 {
|
|
|
+ MsgList := (*r)[0]["list"]
|
|
|
+ if MsgList != nil {
|
|
|
+ list := qutil.ObjArrToMapArr(MsgList.([]interface{}))
|
|
|
+ for _, vv := range list {
|
|
|
+ if vv["subtype"] == "招标" {
|
|
|
+ if v["agency"] == nil && vv["agency"] != nil {
|
|
|
+ v["agency"] = vv["agency"]
|
|
|
+ }
|
|
|
+ if v["budget"] == nil && vv["budget"] != nil {
|
|
|
+ v["budget"] = vv["budget"]
|
|
|
+ }
|
|
|
+ if v["buyerperson"] == nil && vv["buyerperson"] != nil {
|
|
|
+ v["buyerperson"] = vv["buyerperson"]
|
|
|
+ }
|
|
|
+ if v["buyertel"] == nil && vv["buyertel"] != nil {
|
|
|
+ v["buyertel"] = vv["buyertel"]
|
|
|
+ }
|
|
|
+ break
|
|
|
}
|
|
|
- break
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- if v["area"] == "A" {
|
|
|
- v["area"] = "全国"
|
|
|
- }
|
|
|
- if v["bidamount"] != nil {
|
|
|
- v["bidamount"] = formatFloat(qutil.Float64All(v["bidamount"]))
|
|
|
- }
|
|
|
- if v["budget"] != nil {
|
|
|
- v["budget"] = formatFloat(qutil.Float64All(v["budget"]))
|
|
|
- }
|
|
|
- if v["publishtime"] != nil {
|
|
|
- date := v["publishtime"]
|
|
|
- v["publishtime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
- }
|
|
|
- if v["bidopentime"] != nil {
|
|
|
- date := v["bidopentime"]
|
|
|
- v["bidopentime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
- }
|
|
|
- if qutil.IntAll(v["signendtime"]) != 0 {
|
|
|
- date := v["signendtime"]
|
|
|
- v["signendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
- }
|
|
|
- if v["bidendtime"] != nil {
|
|
|
- date := v["bidendtime"]
|
|
|
- v["bidendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
- }
|
|
|
- if v["signaturedate"] != nil {
|
|
|
- date := v["signaturedate"]
|
|
|
- v["signaturedate"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
- }
|
|
|
- if v["_id"] != nil {
|
|
|
- encodeId := CommonEncodeArticle("content", v["_id"].(string))
|
|
|
- v["url"] = webdomain + "/article/content/" + encodeId + ".html"
|
|
|
- v["url_jump"] = webdomain + "/front/reloadTo/article/content/" + encodeId + ".html"
|
|
|
- }
|
|
|
- if v["currency"] == "" || v["currency"] == nil {
|
|
|
- v["currency"] = "人民币"
|
|
|
- }
|
|
|
+ if v["area"] == "A" {
|
|
|
+ v["area"] = "全国"
|
|
|
+ }
|
|
|
+ if v["bidamount"] != nil {
|
|
|
+ v["bidamount"] = formatFloat(qutil.Float64All(v["bidamount"]))
|
|
|
+ }
|
|
|
+ if v["budget"] != nil {
|
|
|
+ v["budget"] = formatFloat(qutil.Float64All(v["budget"]))
|
|
|
+ }
|
|
|
+ if v["publishtime"] != nil {
|
|
|
+ date := v["publishtime"]
|
|
|
+ v["publishtime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
+ }
|
|
|
+ if v["bidopentime"] != nil {
|
|
|
+ date := v["bidopentime"]
|
|
|
+ v["bidopentime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
+ }
|
|
|
+ if qutil.IntAll(v["signendtime"]) != 0 {
|
|
|
+ date := v["signendtime"]
|
|
|
+ v["signendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
+ }
|
|
|
+ if v["bidendtime"] != nil {
|
|
|
+ date := v["bidendtime"]
|
|
|
+ v["bidendtime"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
+ }
|
|
|
+ if v["signaturedate"] != nil {
|
|
|
+ date := v["signaturedate"]
|
|
|
+ v["signaturedate"] = FormatDateWithObj(&date, Date_Short_Layout)
|
|
|
+ }
|
|
|
+ if v["_id"] != nil {
|
|
|
+ encodeId := CommonEncodeArticle("content", v["_id"].(string))
|
|
|
+ v["url"] = webdomain + "/article/content/" + encodeId + ".html"
|
|
|
+ v["url_jump"] = webdomain + "/front/reloadTo/article/content/" + encodeId + ".html"
|
|
|
+ }
|
|
|
+ if v["currency"] == "" || v["currency"] == nil {
|
|
|
+ v["currency"] = "人民币"
|
|
|
+ }
|
|
|
|
|
|
- if isEncry {
|
|
|
- if v["projectscope"] != "" && v["projectscope"] != nil {
|
|
|
- str := ClearHtml.ReplaceAllString(v["projectscope"].(string), "")
|
|
|
- str = ClearOther.ReplaceAllString(str, "")
|
|
|
- str = strings.Replace(str, " ", "", -1)
|
|
|
- if len([]rune(str)) > 100 {
|
|
|
- str = qutil.SubString(str, 0, 100) + "..."
|
|
|
+ if isEncry {
|
|
|
+ if v["projectscope"] != "" && v["projectscope"] != nil {
|
|
|
+ str := ClearHtml.ReplaceAllString(v["projectscope"].(string), "")
|
|
|
+ str = ClearOther.ReplaceAllString(str, "")
|
|
|
+ str = strings.Replace(str, " ", "", -1)
|
|
|
+ if len([]rune(str)) > 100 {
|
|
|
+ str = qutil.SubString(str, 0, 100) + "..."
|
|
|
+ }
|
|
|
+ v["projectscope"] = str
|
|
|
}
|
|
|
- v["projectscope"] = str
|
|
|
- }
|
|
|
- if v["detail"] != "" && v["detail"] != nil {
|
|
|
- str := ClearHtml.ReplaceAllString(v["detail"].(string), "")
|
|
|
- str = ClearOther.ReplaceAllString(str, "")
|
|
|
- str = strings.Replace(str, " ", "", -1)
|
|
|
- if len([]rune(str)) > 100 {
|
|
|
- str = qutil.SubString(str, 0, 100) + "..."
|
|
|
+ if v["detail"] != "" && v["detail"] != nil {
|
|
|
+ str := ClearHtml.ReplaceAllString(v["detail"].(string), "")
|
|
|
+ str = ClearOther.ReplaceAllString(str, "")
|
|
|
+ str = strings.Replace(str, " ", "", -1)
|
|
|
+ if len([]rune(str)) > 100 {
|
|
|
+ str = qutil.SubString(str, 0, 100) + "..."
|
|
|
+ }
|
|
|
+ v["detail"] = str
|
|
|
}
|
|
|
- v["detail"] = str
|
|
|
- }
|
|
|
- if v["title"] != "" && v["title"] != nil {
|
|
|
- str := ClearHtml.ReplaceAllString(v["title"].(string), "")
|
|
|
- str = ClearOther.ReplaceAllString(str, "")
|
|
|
- str = strings.Replace(str, " ", "", -1)
|
|
|
- if len([]rune(str)) > 100 {
|
|
|
- str = qutil.SubString(str, 0, 100) + "..."
|
|
|
+ if v["title"] != "" && v["title"] != nil {
|
|
|
+ str := ClearHtml.ReplaceAllString(v["title"].(string), "")
|
|
|
+ str = ClearOther.ReplaceAllString(str, "")
|
|
|
+ str = strings.Replace(str, " ", "", -1)
|
|
|
+ if len([]rune(str)) > 100 {
|
|
|
+ str = qutil.SubString(str, 0, 100) + "..."
|
|
|
+ }
|
|
|
+ v["title"] = str
|
|
|
}
|
|
|
- v["title"] = str
|
|
|
- }
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- if v["subtype"] == nil && v["toptype"] != nil {
|
|
|
- v["subtype"] = v["toptype"]
|
|
|
- }
|
|
|
+ if v["subtype"] == nil && v["toptype"] != nil {
|
|
|
+ v["subtype"] = v["toptype"]
|
|
|
+ }
|
|
|
+ }((*data)[index])
|
|
|
}
|
|
|
+ wait.Wait()
|
|
|
return data
|
|
|
}
|
|
|
|