wangkaiyue 4 年之前
父节点
当前提交
1d288c12d2
共有 1 个文件被更改,包括 606 次插入0 次删除
  1. 606 0
      src/jfw/modules/common/src/qfw/util/dataexport/dataexport.go

+ 606 - 0
src/jfw/modules/common/src/qfw/util/dataexport/dataexport.go

@@ -0,0 +1,606 @@
+package dataexport
+
+import (
+	//"config"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"math"
+	qutil "qfw/util"
+	"qfw/util/elastic"
+	"qfw/util/jy"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+	"util"
+
+	"go.mongodb.org/mongo-driver/bson"
+)
+
+/*筛选条件--关键词*/
+type KeyWord struct {
+	Keyword  string   `json:"keyword"`  //关键词
+	Appended []string `json:"appended"` //附加词
+	Exclude  []string `json:"exclude"`  //排除词
+}
+
+/*筛选条件*/
+type SieveCondition struct {
+	Id          string    `json:"id"`
+	PublishTime string    `json:"publishtime"` //发布时间
+	Area        []string  `json:"area"`        //地区-省份
+	City        []string  `json:"city"`        //地区-城市
+	Region      []string  `json:"region"`      //地区-省份+城市
+	Industry    []string  `json:"industry"`    //行业
+	Keyword     []KeyWord `json:"keywords"`    //关键词
+	Buyer       []string  `json:"buyer"`       //招标单位(采购单位)
+	Buyerclass  []string  `json:"buyerclass"`  //采购单位类型
+	Winner      []string  `json:"winner"`      //中标单位
+	ComeInTime  int64     `json:"comeintime"`  //入库时间(秒)
+	OpenId      string    `json:"openid"`      //用户openid
+	MinPrice    string    `json:"minprice"`    //金额——最少
+	MaxPrice    string    `json:"maxprice"`    //金额——最多
+	SelectType  string    `json:"selectType"`  //筛选(正文 or 标题)
+	Subtype     string    `json:"subtype"`     //信息类型
+	Comeinfrom  string    `json:"comeinfrom"`  //查询来源
+	DisWord     string    `json:"disWord"`     //分销系统 口令
+}
+
+//VIP订单
+type VipFilter struct {
+	Area               map[string]interface{} `json:"area"`     //地区
+	Industry           []string               `json:"industry"` //
+	Cyclecount         int                    `json:"cyclecount"`
+	Cycleunit          int                    `json:"cycleunit"`
+	Ordertype          int                    `json:"ordertype"`
+	Addarea            map[string]interface{} `json:"addarea"`            //新增地区
+	Addindustry        []string               `json:"addindustry"`        //新增行业
+	Addareacount       map[string]interface{} `json:"addareacount"`       //新增地区数量
+	Addbuyerclasscount int                    `json:"addbuyerclasscount"` //新增地区数量
+	Buyset             map[string]interface{} `json:buyset`
+	NewBuyset          map[string]interface{} `json:newBuyset` //逻辑重写后的判断条件
+}
+
+const (
+	INDEX          = "bidding"
+	TYPE           = "bidding"
+	bidSearch_sort = `{"publishtime":-1}`
+)
+
+var onceSearchCount = 500
+var ExportTable string = "export_search"
+var searchPool = make(chan bool, 8)
+
+//获取数据导出查询语句
+func getDataExportSql(scd *SieveCondition) string {
+	multi_match := `{"multi_match": {"query": %s,"type": "phrase", "fields": [%s]}}`
+	query := `{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}}}`
+	query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
+	query_price := `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
+	query_bool_must := `{"terms":{"%s":[%s]}}`
+	query_bool_must_and := `{"bool":{"must":[%s]%s}}`
+	gte := `"gte": %s`
+	lte := `"lte": %s`
+
+	bools := []string{}
+	musts := []string{fmt.Sprintf(`{"range":{"comeintime":{"lt":%d}}}`, scd.ComeInTime)}
+	//省份
+	areaCity := []string{}
+	if len(scd.Area) > 0 {
+		areaquery := `{"terms":{"area":[`
+		for k, v := range scd.Area {
+			if k > 0 {
+				areaquery += `,`
+			}
+			areaquery += `"` + v + `"`
+		}
+		areaquery += `]}}`
+		areaCity = append(areaCity, areaquery)
+	}
+	//城市
+	if len(scd.City) > 0 {
+		areaquery := `{"terms":{"city":[`
+		for k, v := range scd.City {
+			if k > 0 {
+				areaquery += `,`
+			}
+			areaquery += `"` + v + `"`
+		}
+		areaquery += `]}}`
+		areaCity = append(areaCity, areaquery)
+	}
+	if len(areaCity) > 0 {
+		musts = append(musts, fmt.Sprintf(query_bool_should, strings.Join(areaCity, ",")))
+	}
+	//检索日期
+
+	starttime := ""
+	now := time.Unix(scd.ComeInTime, 0)
+	endtime := fmt.Sprintf("%d", now.Unix())
+	if scd.PublishTime == "lately-7" { //最近7天
+		starttime = fmt.Sprint(time.Date(now.Year(), now.Month(), now.Day()-7, 0, 0, 0, 0, time.Local).Unix())
+	} else if scd.PublishTime == "lately-30" { //最近30天
+		starttime = fmt.Sprint(time.Date(now.Year(), now.Month(), now.Day()-30, 0, 0, 0, 0, time.Local).Unix())
+	} else if scd.PublishTime == "thisyear" { //去年
+		starttime = fmt.Sprint(time.Date(now.Year()-1, 1, 1, 0, 0, 0, 0, time.Local).Unix())
+		endtime = fmt.Sprint(time.Date(now.Year()-1, 12, 31, 23, 59, 59, 0, time.Local).Unix())
+	} else if strings.Contains(scd.PublishTime, "_") { //设置检索日期
+		starttime = strings.Split(scd.PublishTime, "_")[0]
+		endTime_tmp := now
+		if etime := strings.Split(scd.PublishTime, "_")[1]; etime != "" {
+			etTime := time.Unix(qutil.Int64All(etime), 0)
+			endTime_tmp = time.Date(etTime.Year(), etTime.Month(), etTime.Day()+1, 0, 0, 0, 0, time.Local)
+		}
+		//结束时间必须小于筛选时间
+		if endTime_tmp.After(now) {
+			endTime_tmp = now
+		}
+		endtime = fmt.Sprintf("%d", endTime_tmp.Unix())
+	}
+	timequery := `{"range":{"publishtime":{`
+	if starttime != "" {
+		timequery += `"gte":` + starttime
+	}
+	if starttime != "" && endtime != "" {
+		timequery += `,`
+	}
+	if endtime != "" {
+		timequery += `"lt":` + endtime
+	}
+	timequery += `}}}`
+	musts = append(musts, timequery)
+
+	if scd.Subtype != "" {
+		subquery := `{"terms":{"subtype":[`
+		for k, v := range strings.Split(scd.Subtype, ",") {
+			if k > 0 {
+				subquery += `,`
+			}
+			subquery += `"` + v + `"`
+		}
+		subquery += `]}}`
+		musts = append(musts, subquery)
+	}
+	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, `","`)+`"`))
+	}
+	if len(scd.Winner) > 0 {
+		musts = append(musts, fmt.Sprintf(query_bool_must, "s_winner", `"`+strings.Join(scd.Winner, `","`)+`"`))
+	}
+	_minPrice := ""
+	_maxPrice := ""
+	if scd.MinPrice != "" || scd.MaxPrice != "" {
+		sq := ``
+		if scd.MinPrice != "" {
+			min, _ := strconv.ParseFloat(scd.MinPrice, 64)
+			_minPrice = fmt.Sprintf("%.0f", min*10000)
+			if _minPrice == "0" {
+				_minPrice = ""
+			}
+		}
+		if scd.MaxPrice != "" {
+			max, _ := strconv.ParseFloat(scd.MaxPrice, 64)
+			_maxPrice = fmt.Sprintf("%.0f", max*10000)
+			if _maxPrice == "0" {
+				_maxPrice = ""
+			}
+		}
+		if _minPrice != "" {
+			sq += fmt.Sprintf(gte, _minPrice)
+		}
+		if _minPrice != "" && _maxPrice != "" {
+			sq += `,`
+		}
+		if _maxPrice != "" {
+			sq += fmt.Sprintf(lte, _maxPrice)
+		}
+		if _minPrice != "" || _maxPrice != "" {
+			query_price := fmt.Sprintf(query_bool_should, fmt.Sprintf(query_price, sq, sq))
+			musts = append(musts, query_price)
+		}
+	}
+	boolsNum := 0
+	//should
+	if len(scd.Keyword) > 0 {
+		boolsNum = 1
+		if scd.SelectType == "" || scd.SelectType == "all" {
+			scd.SelectType = "detail\", \"title"
+		}
+		multi_match = fmt.Sprintf(multi_match, "%s", "\""+scd.SelectType+"\"")
+
+		if scd.Comeinfrom == "supersearchPage" {
+			var keywordArr []string
+			if strings.Contains(scd.Keyword[0].Keyword, "+") {
+				keywordArr = strings.Split(scd.Keyword[0].Keyword, "+")
+			} else if strings.Contains(scd.Keyword[0].Keyword, " ") {
+				keywordArr = strings.Split(scd.Keyword[0].Keyword, " ")
+			}
+			if len(keywordArr) > 1 {
+				KeyWordSearch := KeyWord{}
+				for _, v := range keywordArr {
+					KeyWordSearch.Appended = append(KeyWordSearch.Appended, v)
+				}
+				scd.Keyword = []KeyWord{KeyWordSearch}
+			}
+		}
+
+		for _, v := range scd.Keyword {
+			shoulds := []string{}
+			must_not := []string{}
+			//附加词
+			if v.Keyword != "" {
+				shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+v.Keyword+"\""))
+			}
+
+			for _, vv := range v.Appended {
+				shoulds = append(shoulds, fmt.Sprintf(multi_match, "\""+vv+"\""))
+			}
+
+			//排除词
+			for _, vv := range v.Exclude {
+				must_not = append(must_not, fmt.Sprintf(multi_match, "\""+vv+"\""))
+			}
+
+			//添加
+			if len(shoulds) > 0 {
+				notStr := ""
+				if len(must_not) > 0 {
+					notStr = fmt.Sprintf(`,"must_not":[%s]`, strings.Join(must_not, ","))
+				}
+				bools = append(bools, fmt.Sprintf(query_bool_must_and, strings.Join(shoulds, ","), notStr))
+			}
+		}
+	}
+	qstr := fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(bools, ","), boolsNum)
+	return qstr
+}
+
+func GetSqlObjFromId(_id string) *SieveCondition {
+	var (
+		query *map[string]interface{}
+		ok    bool
+	)
+	if query, ok = util.MQFW.FindById(ExportTable, _id, nil); !ok {
+		return nil
+	}
+	return &SieveCondition{
+		Id:          _id,
+		Keyword:     getKeyWordArrFromDbResult((*query)["keywords"]),
+		Industry:    getStringArrFromDbResult((*query)["industry"]),
+		MinPrice:    qutil.ObjToString((*query)["minprice"]),
+		MaxPrice:    qutil.ObjToString((*query)["maxprice"]),
+		Subtype:     qutil.ObjToString((*query)["subtype"]),
+		Area:        getStringArrFromDbResult((*query)["area"]),
+		City:        getStringArrFromDbResult((*query)["city"]),
+		SelectType:  qutil.ObjToString((*query)["selectType"]),
+		PublishTime: qutil.ObjToString((*query)["publishtime"]),
+		Buyer:       getStringArrFromDbResult((*query)["buyer"]),
+		Buyerclass:  getStringArrFromDbResult((*query)["buyerclass"]),
+		Winner:      getStringArrFromDbResult((*query)["winner"]),
+		ComeInTime:  qutil.Int64All((*query)["comeintime"]),
+		Comeinfrom:  qutil.ObjToString((*query)["comeinfrom"]),
+	}
+}
+
+//数据导出-查询结果数量
+func GetDataExportSearchCountUseId(id, elasticAddress string) (count int) {
+	scd := GetSqlObjFromId(id) //用户筛选条件
+	qstr := getDataExportSql(scd)
+	if isNullSearch(scd) {
+		return -1 //程序端返回最大值
+	}
+	log.Printf("GetDataExportSearchCountUseId-%s-sql:%s\n", scd.Id, qstr)
+	count = int(elastic.Count(INDEX, TYPE, qstr))
+	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) {
+		if len(scd.Keyword) != 0 {
+			searchTextSize := 0
+			if len(scd.Keyword) > 0 {
+				searchTextSize = len([]rune(scd.Keyword[0].Keyword))
+			}
+			if searchTextSize > 3 && count < 50 {
+				var res *[]map[string]interface{}
+				if count > 0 {
+					res = doSearch(qstr, 0, count, "")
+				}
+				secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress)
+				scd.Keyword[0].Keyword = secondKWS
+				scd.SelectType = "title"
+				qstr = getDataExportSql(scd)
+				res2 := doSearch(qstr, 0, 100, "")
+				result := len(*delRepeatMapArr(res, res2))
+				if result > 100 {
+					result = 100
+				}
+				log.Printf("GetDataExportSearchCountUseId-%s-count:%d-分词-sql:%s\n", scd.Id, result, qstr)
+				return result
+			}
+			return
+		}
+	}
+	log.Printf("GetDataExportSearchCountUseId-%s-count:%d\n", scd.Id, count)
+	return
+}
+
+//合并map数据,去重
+func delRepeatMapArr(res *[]map[string]interface{}, res2 *[]map[string]interface{}) *[]map[string]interface{} {
+	if res != nil {
+		for _, v := range *res {
+			for n, m := range *res2 {
+				if qutil.ObjToString(v["_id"]) == qutil.ObjToString(m["_id"]) {
+					*res2 = append((*res2)[0:n], (*res2)[n+1:]...)
+					break
+				}
+			}
+		}
+		*res = append(*res, *res2...)
+	} else {
+		res = res2
+	}
+	return res
+}
+
+//查询条件是否为空
+func isNullSearch(scd *SieveCondition) (isNull bool) {
+	if scd.PublishTime == "" && len(scd.Area) == 0 && len(scd.Industry) == 0 && len(scd.Keyword) == 0 && len(scd.Buyer) == 0 && len(scd.Winner) == 0 && scd.MinPrice == "" && scd.MaxPrice == "" && scd.Subtype == "" && len(scd.City) == 0 {
+		isNull = true
+	}
+	return isNull
+}
+
+/*
+ * 数据导出 查询结果
+ * _id 数据库查询条件记录id
+ * dataType 1-普通字段 2-高级字段
+ * webdomain 三级页域名
+ * count 返回数量 (-1:预览数据查询)
+ */
+var EntTable = "winner_enterprise"
+
+func GetDataExportSearchResult(id, dataType string, checkCount int, elasticAddress, webdomain string) (*[]map[string]interface{}, error) {
+	defer qutil.Catch()
+	var res []map[string]interface{}
+	//获取查询语句
+	scd := GetSqlObjFromId(id)
+	if scd == nil {
+		return nil, errors.New("GetDataExportSearchResult-获取查询条件")
+	}
+	qstr := getDataExportSql(scd)
+	log.Printf("GetDataExportSearchResult-%s-sql:%s\n", scd.Id, qstr)
+	//数据导出数据查询
+	if checkCount > onceSearchCount { //分批次查询
+		batchNum := qutil.IntAll(math.Ceil(float64(checkCount) / float64(onceSearchCount)))
+		var searchWaitGroup = &sync.WaitGroup{}
+		var lock sync.Mutex
+		for n := 0; n < batchNum; n++ {
+			searchWaitGroup.Add(1)
+			searchPool <- true
+			go func(start int) {
+				defer func() {
+					searchWaitGroup.Done()
+					<-searchPool
+				}()
+				checkNum, checkOk := onceSearchCount, false
+				if start == (batchNum - 1) {
+					if checkCount%onceSearchCount != 0 {
+						checkNum = checkCount % onceSearchCount
+					}
+				}
+
+				var tmp *[]map[string]interface{}
+				for i := 0; i < 3; i++ {
+					tmp = doSearch(qstr, start*onceSearchCount, onceSearchCount, dataType)
+					if tmp != nil && (len(*tmp) == checkNum) { //校验数据量是否够
+						checkOk = true
+						break
+					}
+				}
+				if tmp == nil {
+					log.Printf("GetDataExportSearchResult-%s-第%d页数据查询结果为空\n", scd.Id, start+1)
+					return
+				}
+				if checkOk {
+					log.Printf("GetDataExportSearchResult-%s-第%d页数据加载完成,共%d条\n", scd.Id, start+1, len(*tmp))
+				} else {
+					log.Printf("GetDataExportSearchResult-%s-第%d页数据加载异常,共%d条,预期%d条\n", scd.Id, start+1, len(*tmp), checkNum)
+				}
+				lock.Lock()
+				res = append(res, *tmp...)
+				lock.Unlock()
+			}(n)
+		}
+		searchWaitGroup.Wait()
+		log.Printf("GetDataExportSearchResult-%s-分批次加载数据总量为%d\n", scd.Id, len(res))
+	} else {
+		tmp := doSearch(qstr, 0, checkCount, dataType)
+		if tmp == nil || len(*tmp) == 0 {
+			log.Printf("GetDataExportSearchResult-%s-一次性加载数据异常\n", scd.Id)
+		} else {
+			res = *tmp
+			log.Printf("GetDataExportSearchResult-%s-一次性加载数据总量为%d\n", scd.Id, len(res))
+		}
+	}
+	//超级搜索一致的检索(防止数据导出和超级搜索数据量不一致)
+	if scd.Comeinfrom == "supersearchPage" && (len(scd.Keyword) != 0 || len(scd.Industry) != 0) {
+		if len(scd.Keyword) != 0 {
+			num := len(res)
+			searchTextSize := 0
+			if len(scd.Keyword) > 0 {
+				searchTextSize = len([]rune(scd.Keyword[0].Keyword))
+			}
+			if searchTextSize > 3 && num < 50 {
+				secondKWS := jy.HttpEs(scd.Keyword[0].Keyword, "ik_smart", elasticAddress)
+				scd.Keyword[0].Keyword = secondKWS
+				scd.SelectType = "title"
+				qstr = getDataExportSql(scd)
+				log.Printf("GetDataExportSearchResult-%s-分词查询-sql:%s\n", scd.Id, qstr)
+				res2 := doSearch(qstr, 0, 100, "")
+				res = *delRepeatMapArr(&res, res2)
+				if len(res) > 100 {
+					res = res[:100]
+				}
+			}
+		}
+	}
+	//校验数量
+	if checkCount != len(res) {
+		return nil, fmt.Errorf("GetDataExportSearchResult-%s-数据总量校验异常,期望:%d,实际:%d", scd.Id, checkCount, len(res))
+		//发邮件
+	}
+
+	var EntArr = []string{}
+	for _, v := range res {
+		//高级字段查询且winner不为空
+		if v["s_winner"] != nil && v["s_winner"] != "" && dataType == "2" {
+			EntArr = append(EntArr, v["s_winner"].(string))
+		}
+	}
+	res = *FormatExportData(&res, webdomain, dataType, EntArr)
+	return &res, nil
+}
+
+func FormatExportData(data *[]map[string]interface{}, webdomain string, dataType string, EntArr []string) *[]map[string]interface{} {
+	//格式化输出
+	for _, v := range *data {
+		//有中标企业 且 高级字段查询
+		if len(EntArr) > 0 && dataType == "2" {
+			//查询企业公示 法人 公司电话 公司邮箱地址
+			query := bson.M{"company_name": bson.M{"$in": EntArr}} //
+			if entData, ok := util.MQFWENT.Find(EntTable, query, nil, `{"company_name":1,"company_email":1,"legal_person":1,"company_phone":1}`, false, -1, -1); ok {
+				if entData != nil && *entData != nil && len(*entData) > 0 {
+					for _, ev := range *entData {
+						if v["s_winner"] == ev["company_name"] {
+							legal_person := ""
+							if ev["legal_person"] != nil {
+								legal_person = ev["legal_person"].(string)
+							}
+							company_phone := ""
+							if ev["company_phone"] != nil {
+								company_phone = ev["company_phone"].(string)
+							}
+							company_email := ""
+							if ev["company_email"] != nil && ev["company_email"] != "无" {
+								company_email = ev["company_email"].(string)
+							}
+							v["legal_person"] = legal_person
+							v["company_phone"] = company_phone
+							v["company_email"] = company_email
+						}
+					}
+				}
+			}
+		}
+		//====================字段补漏=========================
+		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 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
+						}
+					}
+				}
+			}
+		}
+		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"] = qutil.FormatDateWithObj(&date, qutil.Date_Short_Layout)
+		}
+		if v["bidopentime"] != nil {
+			date := v["bidopentime"]
+			v["bidopentime"] = qutil.FormatDateWithObj(&date, qutil.Date_Short_Layout)
+		}
+		if v["_id"] != nil {
+			v["url"] = webdomain + "/article/content/" + qutil.CommonEncodeArticle("content", v["_id"].(string)) + ".html"
+		}
+		if v["currency"] == "" || v["currency"] == nil {
+			v["currency"] = "人民币"
+		}
+		if v["subtype"] == nil && v["toptype"] != nil {
+			v["subtype"] = v["toptype"]
+		}
+	}
+	return data
+}
+
+//保留到0.01分
+func formatFloat(value float64) string {
+	str := strings.TrimRight(fmt.Sprintf("%.7f", value*10000/100000000), "0")
+	if str[len(str)-1:] == "." {
+		return str[:len(str)-1]
+	}
+	return str
+}
+
+func doSearch(sql string, start, count int, dataType string) *[]map[string]interface{} {
+	if sql != "" {
+		//筛选字段
+		if dataType != "" {
+			dataexport_field := `"_id","title","detail","area","city","publishtime","projectname","buyer","s_winner","bidamount","subtype","toptype"`
+			if dataType == "2" {
+				dataexport_field += `,"href","projectcode","buyerperson","buyertel","budget","bidopentime","agency","projectscope","winnerperson","winnertel"`
+			}
+			sql = sql[:len(sql)-1] + `,"_source":[` + dataexport_field + "]}"
+		}
+		//分页排序
+		sql = sql[:len(sql)-1] + `,"sort": {"publishtime":"desc"},"from":` + strconv.Itoa(start) + `,"size":` + strconv.Itoa(count) + "}"
+	}
+	return elastic.Get(INDEX, TYPE, sql)
+}
+
+func getKeyWordArrFromDbResult(k interface{}) (arr []KeyWord) {
+	if k == nil {
+		return
+	}
+	kArr := k.([]interface{})
+	for _, v := range kArr {
+		kw := KeyWord{}
+		b, e := json.Marshal(v)
+		if e != nil {
+			log.Println(e.Error())
+		}
+		json.Unmarshal(b, &kw)
+		arr = append(arr, kw)
+	}
+	return
+}
+
+func getStringArrFromDbResult(c interface{}) (arr []string) {
+	if c != nil {
+		cArr := c.([]interface{})
+		arr = qutil.ObjArrToStringArr(cArr)
+	}
+	return
+}