فهرست منبع

feat:移动端搜索优化

wangshan 2 سال پیش
والد
کامیت
12b9aea650

+ 1 - 1
jyBXCore/rpc/bxcore.go

@@ -22,7 +22,7 @@ func main() {
 	go func() {
 		//正文、附件搜索限制
 		util.LimitSearchInit()
-		err := endless.ListenAndServe(":"+MC.InterfaceToStr(IC.C.Webrpcport), nil, func() {})
+		err := endless.ListenAndServe(":"+MC.InterfaceToStr(IC.C.WebRpcPort), nil, func() {})
 		if err != nil {
 			log.Println("ListenAndServe: ", err)
 		}

+ 1 - 1
jyBXCore/rpc/bxcore.proto

@@ -48,7 +48,7 @@ message SearchData {
   int64  isLimit = 3;//全文检索限制//限制正文、附件查询 //return 1 正常 //return -1 抱歉!由于系统繁忙暂时无法进行搜索,请1分钟后再试! //return -2 抱歉!由于系统繁忙暂时无法进行搜索,请稍后再试!
   repeated string historyKeys = 4;//历史搜索关键词
   repeated SearchList list = 5;//搜索列表
-  string numberMsg = 6;//查询总结果数量
+  int64 total = 6;//查询总结果数量
   string remark = 7;//备注
   int64 interceptLimit = 8;//关键词截取长度
   string interceptOtherWords= 9;//关键词截取剩余关键词

+ 38 - 7
jyBXCore/rpc/entity/search.go

@@ -57,7 +57,7 @@ func (kws *KeyWordsSearch) GetBidSearchListByCache(in *bxcore.SearchReq) (list [
 		//查询缓存数据 参数初始化
 		kws.DefaultSearchParamsAuto(in)
 		//缓存数据
-		count, list = service.SearchCacheData(in)
+		count, list = service.GetBidSearchData(in, true)
 		limitCount := int64(util.SearchPageSize * MC.If(in.IsPay, util.SearchMaxPageNum_PAYED, util.SearchMaxPageNum).(int))
 		if count > limitCount {
 			count = limitCount
@@ -76,7 +76,7 @@ func (kws *KeyWordsSearch) GetBidSearchListByCache(in *bxcore.SearchReq) (list [
 		return
 	}(in)
 	if len(l) > 0 {
-		list = l[in.PageNum : (in.PageNum+1)*in.PageSize]
+		list = l[(in.PageNum-1)*in.PageSize : in.PageNum*in.PageSize]
 		count = c
 		//是否收藏
 		util.MakeCollection(in.UserId, list)
@@ -84,7 +84,7 @@ func (kws *KeyWordsSearch) GetBidSearchListByCache(in *bxcore.SearchReq) (list [
 	return
 }
 
-//缓存查询条件初始化
+// DefaultSearchParamsAuto 缓存查询条件初始化
 func (kws *KeyWordsSearch) DefaultSearchParamsAuto(in *bxcore.SearchReq) {
 	//缓存数据 默认查询分组 searchGroup = 1 ,
 	//不查超前信息--招标信息类型为拟建和采购意向的信息
@@ -125,9 +125,11 @@ func (kws *KeyWordsSearch) SearchParamsHandle(in *bxcore.SearchReq) {
 	}
 	//信息类型参数为空  根据搜索分组 初始化信息类型
 	if in.TopType == "" && in.Subtype == "" {
-		in.Subtype = IC.C.DefaultTopTypes[in.SearchGroup]
+		in.Subtype = MC.If(in.SearchGroup > 0, IC.C.DefaultTopTypes[in.SearchGroup], "").(string)
 	}
 	// in.SearchMode 搜索模式 搜索模式:0:精准搜索;1:模糊搜索
+	// 精准搜索:不分词,完全匹配;(中间带空格的关键词组自动分词)
+	// 模糊搜索:对用户输入的单个关键词进行分词处理,但必须都存在;
 	if in.SearchMode < 0 {
 		in.SearchMode = 0
 	}
@@ -165,8 +167,37 @@ func (kws *KeyWordsSearch) SearchParamsHandle(in *bxcore.SearchReq) {
 		in.KeyWords = strings.TrimSpace(in.KeyWords)
 		//以后可能会出现 关键词 C++ 等带+的关键词
 		in.InterceptKeyWords, in.InterceptOtherWords, in.KeyWords = util.InterceptSearchKW(in.KeyWords, MC.IntAllDef(IC.C.KeywordsLimit, 35), len(in.Industry) == 0)
+		//附加词在关键词的基础上 有效
+		//附加词 每组附加词不能超过15个字符
+		if in.AdditionalWords != "" {
+			var additionalWords []string
+			for _, ak := range strings.Split(in.AdditionalWords, ",") {
+				if len([]rune(ak)) > 15 {
+					additionalWords = append(additionalWords, string([]rune(ak)[:15]))
+				} else {
+					additionalWords = append(additionalWords, ak)
+				}
+			}
+			in.AdditionalWords = strings.Join(additionalWords, IC.C.JYKeyMark) //util.MatchSpace.ReplaceAllString(in.AdditionalWords, IC.C.JYKeyMark)
+		}
 		//更新关键词搜索历史记录
 		go kws.SaveKeyWordsToHistory(in)
+	} else {
+		in.AdditionalWords = ""
+	}
+	//格式化关键词
+	in.KeyWords = util.GetSearchKeyWordsQueryStr(in)
+	//排除词  每组排除词不能超过15个字符
+	if in.ExclusionWords != "" {
+		var exclusionWords []string
+		for _, ak := range strings.Split(in.ExclusionWords, ",") {
+			if len([]rune(ak)) > 15 {
+				exclusionWords = append(exclusionWords, string([]rune(ak)[:15]))
+			} else {
+				exclusionWords = append(exclusionWords, ak)
+			}
+		}
+		in.ExclusionWords = strings.Join(exclusionWords, IC.C.JYKeyMark) //util.MatchSpace.ReplaceAllString(in.ExclusionWords, IC.C.JYKeyMark)
 	}
 	//判断用户身份
 	userInfo := util.GetVipState(IC.MainMysql, IC.Mgo, in.UserId)
@@ -178,11 +209,11 @@ func (kws *KeyWordsSearch) SearchParamsHandle(in *bxcore.SearchReq) {
 }
 
 // GetBidSearchList 非空搜索 查询
-func (kws *KeyWordsSearch) GetBidSearchList(in *bxcore.SearchReq) (count int64, list []*bxcore.SearchList, numberMsg string) {
+func (kws *KeyWordsSearch) GetBidSearchList(in *bxcore.SearchReq) (count, total int64, list []*bxcore.SearchList) {
 	//排除异常in.PageNum参数
-	count, list = service.GetBidSearchData(in)
+	count, list = service.GetBidSearchData(in, false)
 	util.MakeCollection(in.UserId, list)
-	numberMsg = fmt.Sprintf("%d", count) //返回数据总量提示信息
+	total = count //返回数据总量提示信息
 	limitCount := MC.If(in.IsPay, int64(util.SearchPageSize*util.SearchMaxPageNum_PAYED), int64(util.SearchPageSize*util.SearchMaxPageNum)).(int64)
 	if count > limitCount {
 		count = limitCount //付费用户count 最多5000条,100页数据,每页50条;免费用户count 最多500条,10页数据,每页50条。

+ 4 - 3
jyBXCore/rpc/etc/bxcore.yaml

@@ -5,11 +5,11 @@ Etcd:
     - 127.0.0.1:2379
   Key: bxcore.rpc
 Timeout: 12000
-Webrpcport: 8013
+WebRpcPort: 8013
 BidSearchOldUserLimit: 1627920001
 LabelUrl:
   Area: /list/area/%s.html
-  Stype: /list/stype/%s.html
+  SType: /list/stype/%s.html
   Industry: /list/industry/%s.html
 DefaultSearchCacheTime: 24
 LimitSearchText:
@@ -33,7 +33,7 @@ PaySearchLimit:
   PageSize: 20
 KeywordsLimit: 35 #主搜索框 关键词长度限制
 DefaultBidInfo: #默认搜索
-  NumMsg: 超过1.8亿 #数据量提示
+  Total: 1800000000 #数据量提示
   PageNum: 10 #总页数
   Count: 500 #查询数据量
   PayCount: 5000 #付费用户查询数据量
@@ -41,3 +41,4 @@ DefaultTopTypes:
   - 拟建,采购意向,招标预告,招标公告,招标结果,招标信用信息
   - 招标预告,招标公告,招标结果,招标信用信息
   - 拟建,采购意向
+JYKeyMark: +剑鱼+

+ 1 - 1
jyBXCore/rpc/init/label.go

@@ -34,7 +34,7 @@ func LabelInit() {
 			case 2:
 				url = fmt.Sprintf(C.LabelUrl.Industry, MC.ObjToString(v["code"]))
 			case 3:
-				url = fmt.Sprintf(C.LabelUrl.Stype, MC.ObjToString(v["code"]))
+				url = fmt.Sprintf(C.LabelUrl.SType, MC.ObjToString(v["code"]))
 			}
 			for _, nv := range strings.Split(names, ",") {
 				LabelMap[nv] = labelStruct{

+ 10 - 9
jyBXCore/rpc/internal/config/config.go

@@ -7,11 +7,11 @@ import (
 
 type Config struct {
 	zrpc.RpcServerConf
-	Webrpcport            int64
+	WebRpcPort            int64
 	BidSearchOldUserLimit int64
 	LabelUrl              struct {
 		Area     string
-		Stype    string
+		SType    string
 		Industry string
 	}
 	DefaultSearchCacheTime int //清除搜索列表内存缓存 间隔时间
@@ -24,8 +24,8 @@ type Config struct {
 		Msg        string
 		LimitKey   string
 	}
-	SearchTypeSwitch bool
-	FileSignBool     bool
+	SearchTypeSwitch bool //标题和正文 同时查询,关键词>1;是否优化查询只查正文(正文包含标题)
+	FileSignBool     bool //IC.C.FileSignBool列表是否显示附件标识开关
 	PaySearchLimit   struct {
 		Switch   bool
 		Year     int
@@ -33,15 +33,16 @@ type Config struct {
 		WordSize int
 		PageNum  int64
 		PageSize int64
-	}
-	KeywordsLimit  int
+	} //优化付费用户搜索速度
+	KeywordsLimit  int //关键词长度限制
 	DefaultBidInfo struct {
-		NumMsg   string
+		Total    int64
 		PageNum  int
 		Count    int
 		PayCount int
-	}
-	DefaultTopTypes []string
+	} //招标信息初始化
+	DefaultTopTypes []string //信息类型初始值
+	JYKeyMark       string   //关键词分组标识
 }
 
 type Db struct {

+ 10 - 11
jyBXCore/rpc/internal/logic/getsearchlistlogic.go

@@ -29,7 +29,7 @@ func NewGetSearchListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Get
 	}
 }
 
-// 标讯搜索结果列表数据
+// GetSearchList 标讯搜索结果列表数据
 func (l *GetSearchListLogic) GetSearchList(in *bxcore.SearchReq) (*bxcore.SearchResp, error) {
 	defer MC.Catch()
 	//用户身份 是否登录
@@ -43,7 +43,7 @@ func (l *GetSearchListLogic) GetSearchList(in *bxcore.SearchReq) (*bxcore.Search
 		Count:          0,
 		List:           []*bxcore.SearchList{},
 		InterceptLimit: int64(MC.IntAllDef(IC.C.KeywordsLimit, 35)),
-		NumberMsg:      IC.C.DefaultBidInfo.NumMsg,
+		Total:          IC.C.DefaultBidInfo.Total,
 	}
 	//初始化搜索对象
 	ks := entity.NewKeyWordsSearch()
@@ -81,20 +81,19 @@ func (l *GetSearchListLogic) GetSearchList(in *bxcore.SearchReq) (*bxcore.Search
 	if res.IsLimit == 1 {
 		//付费用户搜索优化--默认搜索5年数据,数据量太多,接口反应太慢,前两页数据 时间范围根据配置缩小查询以达到快速查询的目的。
 		publishTime := in.PublishTime
-		t1 := time.Now()
 		if b := util.IsOptimize(IC.C, in); b {
-			res.Count, res.List, res.NumberMsg = ks.GetBidSearchList(in) // util.GetBidSearchData(in)
-			logx.Info("1查询耗时", time.Since(t1))
+			t1 := time.Now()
+			res.Count, res.Total, res.List = ks.GetBidSearchList(in) // util.GetBidSearchData(in)
+			logx.Info("1查询耗时:", time.Since(t1))
 		}
-		t2 := time.Now()
-		//如果优化查询数据量提少,和配置数据量作比较,不够的话走原始查询
+		//如果优化查询数据量太少,和配置数据量作比较,不够的话走原始查询
 		if res.Count < IC.C.PaySearchLimit.PageSize {
+			t2 := time.Now()
 			in.PublishTime = publishTime
-			res.Count, res.List, res.NumberMsg = ks.GetBidSearchList(in) //util.GetBidSearchData(in)
+			res.Count, res.Total, res.List = ks.GetBidSearchList(in) //util.GetBidSearchData(in)
+			logx.Info("2查询耗时:", time.Since(t2))
 		}
-		logx.Info("2查询耗时:", time.Since(t2))
-
-		res.KeyWords = in.KeyWords
+		res.KeyWords = in.InterceptKeyWords
 		res.InterceptOtherWords = in.InterceptOtherWords
 	}
 	logx.Info("关键词 -全部- 查询耗时:", time.Since(t).Seconds())

+ 34 - 15
jyBXCore/rpc/model/es/es.go

@@ -9,22 +9,41 @@ import (
 )
 
 const (
-	highlightStr = `"%s": {"fragment_size": %d,"number_of_fragments": 1}`
-	HL           = `"highlight": {"pre_tags": [""],"post_tags": [""],"fields": {%s}}`
-	INDEX        = "bidding"
-	TYPE         = "bidding"
-
-	BidSearchSort       = `{"dataweight":-1,"publishtime":-1}`
-	BidSearchFieldBase  = `"_id","title","publishtime","dataweight","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass","spidercode","site"`                                                    //搜索列表基础字段
-	BidSearchFieldOfVip = BidSearchFieldBase + `,"buyer","buyertel","buyerperson","agency","agencytel","agencyperson","s_winner","winnertel","winnerperson","signendtime","bidendtime","bidopentime","budget","projectinfo","entidlist"` //付费列表字段
-	BidSearchFieldFile  = `,"isValidFile"`                                                                                                                                                                                               //根据配置开关 选择是否显示 是否有附件提示,IC.C.FileSignBool
-
-	DefaultFields = `"title"` //最新招标信息
+	multiMatch              = `{"multi_match": {"query": "%s","type": "phrase", "fields": [%s]}}`
+	query                   = `{"query":{"bool":{"must":[%s],"must_not":[%s]}}}`
+	queryBoolShould         = `{"bool":{"should":[%s],"minimum_should_match": 1}}`
+	queryBoolMustBoolShould = `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
+	queryBoolMust           = `{"bool":{"must":[{"terms":{"s_subscopeclass":[%s]}}]}}`
+	queryBoolMustTerm       = `{"bool": {"must": [{ "term": {"isValidFile": %d }}]}}`
+	queryMissing            = `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
+	gte                     = `"gte": %s`
+	lte                     = `"lte": %s`
+	HighlightStr            = `"%s": {"fragment_size": %d,"number_of_fragments": 1}`
+	HL                      = `"highlight": {"pre_tags": [""],"post_tags": [""],"fields": {%s}}`
+	INDEX                   = "bidding"
+	TYPE                    = "bidding"
+	QueryBoolShould         = `{"bool":{"should":[%s],"minimum_should_match": 1}}`
+	BidSearchSort           = `{"dataweight":-1,"publishtime":-1}`
+	BidSearchFieldBase      = `"_id","title","publishtime","dataweight","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass","spidercode","site"`                                                    //搜索列表基础字段
+	BidSearchFieldOfVip     = BidSearchFieldBase + `,"buyer","buyertel","buyerperson","agency","agencytel","agencyperson","s_winner","winnertel","winnerperson","signendtime","bidendtime","bidopentime","budget","projectinfo","entidlist"` //付费列表字段
+	BidSearchFieldFile      = `,"isValidFile"`                                                                                                                                                                                               //根据配置开关 选择是否显示 是否有附件提示,IC.C.FileSignBool
+	//DefaultFields       = `"title"`                                                                                                                                                                                                      //最新招标信息
 )
 
-var SR = strings.Replace
+var (
+	SR = strings.Replace
+	//信息类型 一级类型参数和数据类型转换
+	topTypeMap = map[string]string{
+		"招标预告":   "预告",
+		"招标公告":   "招标",
+		"招标结果":   "结果",
+		"招标信用信息": "其它",
+		"拟建项目":   "拟建",
+		"采购意向":   "采购意向",
+	}
+)
 
-type ESSearch struct {
+type SearchByES struct {
 	Index      string
 	IType      string
 	Query      string
@@ -38,13 +57,13 @@ type ESSearch struct {
 }
 
 // GetAllByNgramWithCount  获取es查询结果及总数量
-func (e *ESSearch) GetAllByNgramWithCount() (int64, *[]map[string]interface{}) {
+func (e *SearchByES) GetAllByNgramWithCount() (int64, *[]map[string]interface{}) {
 	if e.Query != "" {
 		queryStr := e.Query
 		if e.HighLight {
 			var ws []string
 			for _, w := range strings.Split(e.FindFields, ",") {
-				ws = append(ws, fmt.Sprintf(highlightStr, w, e.Count))
+				ws = append(ws, fmt.Sprintf(HighlightStr, w, e.Count))
 			}
 			queryStr = queryStr[:len(queryStr)-1] + `,` + fmt.Sprintf(HL, strings.Join(ws, ",")) + `}`
 		}

+ 67 - 80
jyBXCore/rpc/model/es/search.go

@@ -11,100 +11,88 @@ import (
 	"strings"
 )
 
-// GetSearchCacheData  查询es bidding 获取数据
-func GetSearchCacheData(query string) (*[]map[string]interface{}, int64) {
-	return elastic.GetAllByNgramNew(INDEX, TYPE, query, DefaultFields, bidSearch_sort, bidSearch_field, 0, IC.C.DefaultBidInfo.Count, 0, false)
-
-}
-
 // GetSearchQuery  整理关键词等查询条件
-func GetSearchQuery(in *bxcore.SearchReq, mustquery string) (qstr string) {
-	multi_match := `{"multi_match": {"query": "%s","type": "phrase", "fields": [%s]}}`
-	query := `{"query":{"bool":{"must":[%s],"must_not":[%s]}}}`
-	query_bool_should := `{"bool":{"should":[%s],"minimum_should_match": 1}}`
-	query_bools_must := `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
-	query_bool_must := `{"bool":{"must":[{"terms":{"s_subscopeclass":[%s]}}]}}`
-	query_bool_must_term := `{"bool": {"must": [{ "term": {"isValidFile": %d }}]}}`
-	query_missing := `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
-	gte := `"gte": %s`
-	lte := `"lte": %s`
-	musts, must_not := []string{}, []string{}
-	if mustquery != "" {
-		musts = append(musts, mustquery)
+func GetSearchQuery(in *bxcore.SearchReq, mustQuery string) (qstr string) {
+	var (
+		musts, must_not []string
+	)
+	if mustQuery != "" {
+		musts = append(musts, mustQuery)
 	}
 	//搜索范围是否只有附件
 	//搜索范围只选择附件,是否有附件条件无效;
 	var isFileSearch bool = in.SelectType == "filetext"
 	selectTypeArr := strings.Split(in.SelectType, ",")
-	var findfields string
+	var findFields string
 	if selectTypeArr == nil || len(selectTypeArr) == 0 {
-		findfields = `"title"`
+		findFields = `"title"`
 	} else {
-		findfields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
+		findFields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
 	}
 	//此时关键词中间有+进行隔离
 	if in.KeyWords != "" {
-		shoulds := []string{}
-		var switchBool = strings.Contains(findfields, "detail") && strings.Contains(findfields, "title") && IC.C.SearchTypeSwitch
-		keyword_multi_match := fmt.Sprintf(multi_match, "%s", findfields)
-		for _, v := range strings.Split(in.KeyWords, "+") {
+		var (
+			keyMusts   []string
+			switchBool = strings.Contains(findFields, "detail") && strings.Contains(findFields, "title") && IC.C.SearchTypeSwitch
+		)
+		for _, v := range strings.Split(in.KeyWords, IC.C.JYKeyMark) {
 			if elastic.ReplaceYH(v) == "" {
 				continue
 			}
-			if len([]rune(elastic.ReplaceYH(v))) == 1 {
-				//单个字  搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
-				if DetailFileORTitle(findfields) {
-					keyword_multi_match = fmt.Sprintf(multi_match, "%s", findfields+`,"title"`)
-				}
-			} else {
+			//单个字  搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+			if len([]rune(elastic.ReplaceYH(v))) == 1 && DetailFileORTitle(findFields) {
+				findFields += `,"title"`
+			} else if switchBool && len([]rune(elastic.ReplaceYH(v))) > 1 {
 				//标题 全文搜索 搜索类型开关打开 默认搜索全文;(全文包含标题)(单字排除)
-				if switchBool && len([]rune(elastic.ReplaceYH(v))) > 1 {
-					if strings.Contains(findfields, `"title",`) {
-						findfields = strings.Replace(findfields, `"title",`, ``, -1)
-					} else if strings.Contains(findfields, `,"title"`) {
-						findfields = strings.Replace(findfields, `,"title"`, ``, -1)
-					}
-					keyword_multi_match = fmt.Sprintf(multi_match, "%s", findfields)
+				if strings.Contains(findFields, `"title",`) {
+					findFields = strings.Replace(findFields, `"title",`, ``, -1)
+				} else if strings.Contains(findFields, `,"title"`) {
+					findFields = strings.Replace(findFields, `,"title"`, ``, -1)
 				}
 			}
-			shoulds = append(shoulds, fmt.Sprintf(keyword_multi_match, elastic.ReplaceYH(v)))
+			keyMusts = append(keyMusts, fmt.Sprintf(fmt.Sprintf(multiMatch, "%s", findFields), elastic.ReplaceYH(v)))
+		}
+		//搜索关键词模式;默认0:包含所有,1:包含任意
+		if in.WordsMode == 1 {
+			musts = append(musts, fmt.Sprintf(queryBoolShould, strings.Join(keyMusts, ",")))
+		} else {
+			musts = append(musts, fmt.Sprintf(elastic.NgramMust, strings.Join(keyMusts, ",")))
 		}
-		musts = append(musts, fmt.Sprintf(elastic.NgramMust, strings.Join(shoulds, ",")))
 	}
 	if in.Industry != "" {
-		industrys := strings.Split(in.Industry, ",")
-		musts = append(musts, fmt.Sprintf(query_bool_must, `"`+strings.Join(industrys, `","`)+`"`))
+		//industrys := strings.Split(in.Industry, ",")
+		musts = append(musts, fmt.Sprintf(queryBoolMust, `"`+strings.ReplaceAll(in.Industry, ",", `","`)+`"`))
 	}
 	//价格
 	if in.Price != "" && len(strings.Split(in.Price, "-")) > 1 {
-		minprice, maxprice := strings.Split(in.Price, "-")[0], strings.Split(in.Price, "-")[1]
-		if minprice != "" || maxprice != "" {
+		minPrice, maxPrice := strings.Split(in.Price, "-")[0], strings.Split(in.Price, "-")[1]
+		if minPrice != "" || maxPrice != "" {
 			sq := ``
-			if minprice != "" {
-				min, _ := strconv.ParseFloat(minprice, 64)
-				minprice = fmt.Sprintf("%.0f", min*10000)
-				if minprice == "0" {
-					minprice = ""
+			if minPrice != "" {
+				min, _ := strconv.ParseFloat(minPrice, 64)
+				minPrice = fmt.Sprintf("%.0f", min*10000)
+				if minPrice == "0" {
+					minPrice = ""
 				}
 			}
-			if maxprice != "" {
-				max, _ := strconv.ParseFloat(maxprice, 64)
-				maxprice = fmt.Sprintf("%.0f", max*10000)
-				if maxprice == "0" {
-					maxprice = ""
+			if maxPrice != "" {
+				max, _ := strconv.ParseFloat(maxPrice, 64)
+				maxPrice = fmt.Sprintf("%.0f", max*10000)
+				if maxPrice == "0" {
+					maxPrice = ""
 				}
 			}
-			if minprice != "" {
-				sq += fmt.Sprintf(gte, minprice)
+			if minPrice != "" {
+				sq += fmt.Sprintf(gte, minPrice)
 			}
-			if minprice != "" && maxprice != "" {
+			if minPrice != "" && maxPrice != "" {
 				sq += `,`
 			}
-			if maxprice != "" {
-				sq += fmt.Sprintf(lte, maxprice)
+			if maxPrice != "" {
+				sq += fmt.Sprintf(lte, maxPrice)
 			}
-			if minprice != "" || maxprice != "" {
-				query_price := fmt.Sprintf(query_bool_should, fmt.Sprintf(query_bools_must, sq, sq))
+			if minPrice != "" || maxPrice != "" {
+				query_price := fmt.Sprintf(queryBoolShould, fmt.Sprintf(queryBoolMustBoolShould, sq, sq))
 				musts = append(musts, query_price)
 			}
 		}
@@ -112,47 +100,46 @@ func GetSearchQuery(in *bxcore.SearchReq, mustquery string) (qstr string) {
 	hasBuyerTel := in.BuyerTel
 	if hasBuyerTel != "" {
 		if hasBuyerTel == "y" {
-			must_not = append(must_not, fmt.Sprintf(query_missing, "buyertel"))
+			must_not = append(must_not, fmt.Sprintf(queryMissing, "buyertel"))
 		} else {
-			musts = append(musts, fmt.Sprintf(query_missing, "buyertel"))
+			musts = append(musts, fmt.Sprintf(queryMissing, "buyertel"))
 		}
 	}
 	hasWinnerTel := in.WinnerTel
 	if hasWinnerTel != "" {
 		if hasWinnerTel == "y" {
-			must_not = append(must_not, fmt.Sprintf(query_missing, "winnertel"))
+			must_not = append(must_not, fmt.Sprintf(queryMissing, "winnertel"))
 		} else {
-			musts = append(musts, fmt.Sprintf(query_missing, "winnertel"))
+			musts = append(musts, fmt.Sprintf(queryMissing, "winnertel"))
 		}
 	}
 	//排除词
-	notkey := in.ExclusionWords
-	if notkey = strings.TrimSpace(notkey); notkey != "" {
-		notkey_multi_match := fmt.Sprintf(multi_match, "%s", findfields)
-		notkey_must_not := []string{}
-		for _, v := range strings.Split(notkey, " ") {
+	if notKey := strings.TrimSpace(in.ExclusionWords); notKey != "" {
+		notKeyMultiMatch := fmt.Sprintf(multiMatch, "%s", findFields)
+		var notKeyMustNot []string
+		for _, v := range strings.Split(notKey, IC.C.JYKeyMark) {
 			v = strings.TrimSpace(v)
 			if v == "" {
 				continue
 			}
 			if len([]rune(elastic.ReplaceYH(v))) == 1 {
 				//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
-				if DetailFileORTitle(findfields) {
-					notkey_multi_match = fmt.Sprintf(multi_match, "%s", findfields+`,"title"`)
+				if DetailFileORTitle(findFields) {
+					notKeyMultiMatch = fmt.Sprintf(multiMatch, "%s", findFields+`,"title"`)
 				}
 			}
-			notkey_must_not = append(notkey_must_not, fmt.Sprintf(notkey_multi_match, elastic.ReplaceYH(v)))
+			notKeyMustNot = append(notKeyMustNot, fmt.Sprintf(notKeyMultiMatch, elastic.ReplaceYH(v)))
 		}
-		must_not = append(must_not, fmt.Sprintf(query_bool_should, strings.Join(notkey_must_not, ",")))
+		must_not = append(must_not, fmt.Sprintf(queryBoolShould, strings.Join(notKeyMustNot, ",")))
 	}
 	//
 	fileExists := in.FileExists
 	if !isFileSearch && fileExists != "" {
 		if fileExists == "1" { //有附件
-			must_not = append(must_not, fmt.Sprintf(query_missing, "isValidFile"))
-			musts = append(musts, fmt.Sprintf(query_bool_must_term, 1))
+			must_not = append(must_not, fmt.Sprintf(queryMissing, "isValidFile"))
+			musts = append(musts, fmt.Sprintf(queryBoolMustTerm, 1))
 		} else if fileExists == "-1" { //无附件
-			musts = append(musts, fmt.Sprintf(query_missing, "isValidFile"))
+			musts = append(musts, fmt.Sprintf(queryMissing, "isValidFile"))
 		}
 	}
 	qstr = fmt.Sprintf(query, strings.Join(musts, ","), strings.Join(must_not, ","))
@@ -191,7 +178,7 @@ func GetBidSearchQuery(in *bxcore.SearchReq) string {
 		query += `]}}`
 	}
 	if query != "" {
-		query = fmt.Sprintf(query_bool_should, query)
+		query = fmt.Sprintf(QueryBoolShould, query)
 	}
 	//发布时间
 	publishtime := in.PublishTime
@@ -254,7 +241,7 @@ func GetBidSearchQuery(in *bxcore.SearchReq) string {
 		if query != "" {
 			query += ","
 		}
-		query += fmt.Sprintf(query_bool_should, alltype)
+		query += fmt.Sprintf(QueryBoolShould, alltype)
 	}
 	//采购单位类型
 	buyerclass := in.BuyerClass

+ 0 - 31
jyBXCore/rpc/model/es/searchQuery.go

@@ -1,31 +0,0 @@
-package es
-
-const (
-	queryByIds        = `{"query":{"bool":{"must":[{"terms":{"_id":[%s]}}]}}}`
-	multiMatch        = `{"multi_match": {"query": %s,"type": "phrase", "fields": [%s]}}`
-	query             = `{"query":{"bool":{"must":[%s],"must_not":[%s],"should":[%s],"minimum_should_match": %d}}}`
-	queryBoolShould   = `{"bool":{"should":[%s],"minimum_should_match": 1}}`
-	queryPrice        = `{"bool":{"must":[{"range":{"bidamount":{%s}}}]}},{"bool":{"must":[{"range":{"budget":{%s}}}],"must_not":[{"range":{"bidamount":{"gte":-1}}}]}}`
-	queryBoolMust     = `{"terms":{"%s":[%s]}}`
-	queryBoolMustAnd  = `{"bool":{"must":[%s]%s}}`
-	queryMissing      = `{"constant_score":{"filter":{"missing":{"field":"%s"}}}}`
-	queryBoolMustTerm = `{"bool": {"must": [{ "term": {"isValidFile": %d }}]}}`
-	gte               = `"gte": %s`
-	lte               = `"lte": %s`
-	queryPublishTime  = `{"range":{"publishtime":{%s}}}`
-
-	query_bool_should = `{"bool":{"should":[%s],"minimum_should_match": 1}}`
-	bidSearch_sort    = `{"dataweight":-1,"publishtime":-1}`
-	bidSearch_field_1 = `"_id","title","publishtime","dataweight","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass","spidercode","site"` //,"filetext"
-	bidSearch_field   = bidSearch_field_1 + `,"bidopentime","winner","buyer","projectname","projectcode","projectinfo"`
-)
-
-//
-var topTypeMap = map[string]string{
-	"招标预告":   "预告",
-	"招标公告":   "招标",
-	"招标结果":   "结果",
-	"招标信用信息": "其它",
-	"拟建项目":   "拟建",
-	"采购意向":   "采购意向",
-}

+ 11 - 34
jyBXCore/rpc/service/search.go

@@ -11,48 +11,23 @@ import (
 	"time"
 )
 
-// SearchCacheData  默认查询缓存数据 只查标题
+// GetBidSearchData  默认查询缓存数据 只查标题
 // 登录用户默认搜索500条数据,付费用户字段和免费用户字段不同,未登录用户查询5000条。
-func SearchCacheData(in *bxcore.SearchReq) (count int64, list []*bxcore.SearchList) {
-	t := time.Now()
-	query := MC.If(in.IsPay, es.BidSearchFieldOfVip, es.BidSearchFieldBase).(string)
-	biddingSearch := es.ESSearch{
-		Index:      es.INDEX,
-		IType:      es.TYPE,
-		Query:      es.GetSearchQuery(in, es.GetBidSearchQuery(in)),
-		FindFields: "title",
-		Order:      es.BidSearchSort,
-		Fields:     MC.If(IC.C.FileSignBool, query+es.BidSearchFieldFile, query).(string), //IC.C.FileSignBool列表是否显示附件开关
-		Start:      0,
-		Limit:      MC.If(in.IsPay, IC.C.DefaultBidInfo.PayCount, IC.C.DefaultBidInfo.Count).(int), //付费用户5000条,免费用户及未登录500条
-		Count:      MC.If(strings.Contains(in.SelectType, "detail"), 115, 0).(int),                 //高亮正文数量
-		HighLight:  MC.If(strings.Contains(in.SelectType, "detail"), true, false).(bool),           //是否高亮正文
-	}
-	var repl *[]map[string]interface{}
-	count, repl = biddingSearch.GetAllByNgramWithCount()
-	if repl != nil && *repl != nil && len(*repl) > 0 {
-		list = util.SearchListFormat(in.Industry, repl, false)
-	} else {
-		logx.Info("查询缓存异常")
-	}
-	logx.Info("关键词 -cache- 查询耗时:", time.Since(t).Seconds())
-	return
-}
-
-//GetBidSearchData 标信息搜索
-func GetBidSearchData(in *bxcore.SearchReq) (count int64, list []*bxcore.SearchList) {
+// 标信息搜索 isCache:是否是获取缓存信息
+func GetBidSearchData(in *bxcore.SearchReq, isCache bool) (count int64, list []*bxcore.SearchList) {
 	var start = int((in.PageNum - 1) * in.PageSize)
 	if start >= 0 {
 		t := time.Now()
-		biddingSearch := es.ESSearch{
+		fields := MC.If(in.IsPay, es.BidSearchFieldOfVip, es.BidSearchFieldBase).(string)
+		biddingSearch := es.SearchByES{
 			Index:      es.INDEX,
 			IType:      es.TYPE,
 			Query:      es.GetSearchQuery(in, es.GetBidSearchQuery(in)),
-			FindFields: "detail",
+			FindFields: MC.If(isCache, "title", "detail").(string),
 			Order:      es.BidSearchSort,
-			Fields:     MC.If(IC.C.FileSignBool, MC.If(in.IsPay, es.BidSearchFieldOfVip, es.BidSearchFieldBase).(string)+es.BidSearchFieldFile, MC.If(in.IsPay, es.BidSearchFieldOfVip, es.BidSearchFieldBase).(string)).(string), //IC.C.FileSignBool列表是否显示附件开关
-			Start:      start,
-			Limit:      int(in.PageSize),
+			Fields:     MC.If(IC.C.FileSignBool, fields+es.BidSearchFieldFile, fields).(string), //IC.C.FileSignBool列表是否显示附件开关
+			Start:      MC.If(isCache, 0, start).(int),
+			Limit:      MC.If(isCache, MC.If(in.IsPay, IC.C.DefaultBidInfo.PayCount, IC.C.DefaultBidInfo.Count).(int), int(in.PageSize)).(int),
 			Count:      MC.If(strings.Contains(in.SelectType, "detail"), 115, 0).(int),       //高亮正文数量
 			HighLight:  MC.If(strings.Contains(in.SelectType, "detail"), true, false).(bool), //是否高亮正文
 		}
@@ -61,6 +36,8 @@ func GetBidSearchData(in *bxcore.SearchReq) (count int64, list []*bxcore.SearchL
 		if repl != nil && *repl != nil && len(*repl) > 0 {
 			//格式化查询结果
 			list = util.SearchListFormat(in.Industry, repl, true)
+		} else {
+			logx.Info("查询数据异常")
 		}
 		logx.Info("关键词 -1- 查询耗时:", time.Since(t).Seconds())
 	}

+ 125 - 125
jyBXCore/rpc/type/bxcore/bxcore.pb.go

@@ -380,7 +380,7 @@ type SearchData struct {
 	IsLimit             int64         `protobuf:"varint,3,opt,name=isLimit,proto3" json:"isLimit,omitempty"`                        //全文检索限制//限制正文、附件查询 //return 1 正常 //return -1 抱歉!由于系统繁忙暂时无法进行搜索,请1分钟后再试! //return -2 抱歉!由于系统繁忙暂时无法进行搜索,请稍后再试!
 	HistoryKeys         []string      `protobuf:"bytes,4,rep,name=historyKeys,proto3" json:"historyKeys,omitempty"`                 //历史搜索关键词
 	List                []*SearchList `protobuf:"bytes,5,rep,name=list,proto3" json:"list,omitempty"`                               //搜索列表
-	NumberMsg           string        `protobuf:"bytes,6,opt,name=numberMsg,proto3" json:"numberMsg,omitempty"`                     //查询总结果数量
+	Total               int64         `protobuf:"varint,6,opt,name=total,proto3" json:"total,omitempty"`                            //查询总结果数量
 	Remark              string        `protobuf:"bytes,7,opt,name=remark,proto3" json:"remark,omitempty"`                           //备注
 	InterceptLimit      int64         `protobuf:"varint,8,opt,name=interceptLimit,proto3" json:"interceptLimit,omitempty"`          //关键词截取长度
 	InterceptOtherWords string        `protobuf:"bytes,9,opt,name=interceptOtherWords,proto3" json:"interceptOtherWords,omitempty"` //关键词截取剩余关键词
@@ -453,11 +453,11 @@ func (x *SearchData) GetList() []*SearchList {
 	return nil
 }
 
-func (x *SearchData) GetNumberMsg() string {
+func (x *SearchData) GetTotal() int64 {
 	if x != nil {
-		return x.NumberMsg
+		return x.Total
 	}
-	return ""
+	return 0
 }
 
 func (x *SearchData) GetRemark() string {
@@ -1165,7 +1165,7 @@ var file_bxcore_proto_rawDesc = []byte{
 	0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x72, 0x72, 0x4d, 0x73, 0x67,
 	0x12, 0x26, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
 	0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x44, 0x61,
-	0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xb2, 0x02, 0x0a, 0x0a, 0x53, 0x65, 0x61,
+	0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xaa, 0x02, 0x0a, 0x0a, 0x53, 0x65, 0x61,
 	0x72, 0x63, 0x68, 0x44, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a,
 	0x08, 0x6b, 0x65, 0x79, 0x57, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
@@ -1175,127 +1175,127 @@ var file_bxcore_proto_rawDesc = []byte{
 	0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72,
 	0x79, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20,
 	0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x0a,
-	0x09, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x09, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x72,
-	0x65, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d,
-	0x61, 0x72, 0x6b, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
-	0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x69, 0x6e, 0x74,
-	0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x30, 0x0a, 0x13, 0x69,
-	0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72,
-	0x64, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63,
-	0x65, 0x70, 0x74, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x64, 0x73, 0x22, 0xad, 0x07,
-	0x0a, 0x0a, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
-	0x61, 0x72, 0x65, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x65, 0x61,
-	0x12, 0x18, 0x0a, 0x07, 0x61, 0x72, 0x65, 0x61, 0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x07, 0x61, 0x72, 0x65, 0x61, 0x55, 0x72, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x75,
-	0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
-	0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69,
-	0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x16,
-	0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
-	0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74,
-	0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74,
-	0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x55, 0x72,
-	0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72,
-	0x79, 0x55, 0x72, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54,
-	0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69,
-	0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x45, 0x78,
-	0x69, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65,
-	0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70,
-	0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65,
-	0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x18, 0x0c,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c,
-	0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x43, 0x6f, 0x6c, 0x6c,
-	0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x43,
-	0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a,
-	0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70,
-	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72,
-	0x6f, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06,
-	0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x62, 0x75,
-	0x64, 0x67, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e,
-	0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75,
-	0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x79, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x05, 0x62, 0x75, 0x79, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x75, 0x79, 0x65,
-	0x72, 0x54, 0x65, 0x6c, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x79, 0x65,
-	0x72, 0x54, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x75, 0x79, 0x65, 0x72, 0x50, 0x65, 0x72,
-	0x73, 0x6f, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x75, 0x79, 0x65, 0x72,
-	0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79,
-	0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22,
-	0x0a, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x18, 0x17,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x65, 0x72, 0x73,
-	0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x54, 0x65, 0x6c, 0x18,
-	0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x54, 0x65, 0x6c,
-	0x12, 0x32, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x19,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x57, 0x69,
-	0x6e, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72,
-	0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x69, 0x64, 0x4f, 0x70, 0x65, 0x6e, 0x54,
-	0x69, 0x6d, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x69, 0x64, 0x4f, 0x70,
-	0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x45, 0x6e,
-	0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x69, 0x67,
-	0x6e, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x69, 0x64, 0x45,
-	0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x69,
-	0x64, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x74, 0x65,
-	0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a,
-	0x73, 0x70, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0a, 0x73, 0x70, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x0b,
-	0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x1f, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x49, 0x6e, 0x66, 0x6f,
-	0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x82, 0x01,
-	0x0a, 0x0a, 0x57, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06,
-	0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x77, 0x69,
-	0x6e, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x65,
-	0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x54,
-	0x65, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x65, 0x72, 0x73,
-	0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72,
-	0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72,
-	0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72,
-	0x49, 0x64, 0x22, 0x83, 0x02, 0x0a, 0x05, 0x50, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b,
-	0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x26,
-	0x0a, 0x0e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x43,
-	0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76,
-	0x65, 0x44, 0x65, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x70, 0x70,
-	0x72, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x72,
-	0x6f, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20,
-	0x0a, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x54, 0x69, 0x6d, 0x65,
-	0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18,
-	0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79,
-	0x70, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x4e, 0x75, 0x6d,
-	0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f,
-	0x76, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xc2, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x61,
-	0x70, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x69,
-	0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63,
-	0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e,
-	0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
-	0x04, 0x66, 0x6c, 0x61, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74,
-	0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65,
-	0x6e, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18,
-	0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a,
-	0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x22, 0x59, 0x0a,
-	0x0f, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70,
-	0x12, 0x19, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x03, 0x52, 0x07, 0x65, 0x72, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x65,
-	0x72, 0x72, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x72,
-	0x72, 0x4d, 0x73, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x80, 0x01, 0x0a, 0x06, 0x42, 0x78, 0x43,
-	0x6f, 0x72, 0x65, 0x12, 0x36, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x4c, 0x69, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65,
-	0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65,
-	0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x0b, 0x53,
-	0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x2e, 0x62, 0x78, 0x63,
+	0x72, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a,
+	0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f,
+	0x74, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x07, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x26, 0x0a, 0x0e, 0x69,
+	0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20,
+	0x01, 0x28, 0x03, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x4c, 0x69,
+	0x6d, 0x69, 0x74, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
+	0x4f, 0x74, 0x68, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x4f, 0x74, 0x68, 0x65, 0x72,
+	0x57, 0x6f, 0x72, 0x64, 0x73, 0x22, 0xad, 0x07, 0x0a, 0x0a, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
+	0x4c, 0x69, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x65, 0x61, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x65, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x72, 0x65, 0x61,
+	0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x72, 0x65, 0x61, 0x55,
+	0x72, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x75, 0x79, 0x65, 0x72, 0x43, 0x6c, 0x61,
+	0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
+	0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x1a,
+	0x0a, 0x08, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e,
+	0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0b, 0x69, 0x6e, 0x64, 0x75, 0x73, 0x74, 0x72, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x20, 0x0a, 0x0b,
+	0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1e,
+	0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01,
+	0x28, 0x08, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x18,
+	0x0a, 0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x07, 0x73, 0x75, 0x62, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x74,
+	0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75,
+	0x62, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c,
+	0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20,
+	0x0a, 0x0b, 0x69, 0x73, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0e, 0x20,
+	0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64,
+	0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18,
+	0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61,
+	0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x64,
+	0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+	0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x11,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09,
+	0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52,
+	0x09, 0x62, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75,
+	0x79, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x79, 0x65, 0x72,
+	0x12, 0x1a, 0x0a, 0x08, 0x62, 0x75, 0x79, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x18, 0x14, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x79, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0b,
+	0x62, 0x75, 0x79, 0x65, 0x72, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0b, 0x62, 0x75, 0x79, 0x65, 0x72, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x16,
+	0x0a, 0x06, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+	0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79,
+	0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67,
+	0x65, 0x6e, 0x63, 0x79, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x67,
+	0x65, 0x6e, 0x63, 0x79, 0x54, 0x65, 0x6c, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61,
+	0x67, 0x65, 0x6e, 0x63, 0x79, 0x54, 0x65, 0x6c, 0x12, 0x32, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x6e,
+	0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x19, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62,
+	0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x57, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f,
+	0x52, 0x0a, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b,
+	0x62, 0x69, 0x64, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0b, 0x62, 0x69, 0x64, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x20,
+	0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x1b, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65,
+	0x12, 0x1e, 0x0a, 0x0a, 0x62, 0x69, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x1c,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x62, 0x69, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65,
+	0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x74, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+	0x73, 0x69, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x70, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f,
+	0x64, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x70, 0x69, 0x64, 0x65, 0x72,
+	0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49,
+	0x6e, 0x66, 0x6f, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x78, 0x63, 0x6f,
+	0x72, 0x65, 0x2e, 0x50, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+	0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x0a, 0x57, 0x69, 0x6e, 0x6e, 0x65, 0x72,
+	0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09,
+	0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x09, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x77, 0x69,
+	0x6e, 0x6e, 0x65, 0x72, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0c, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x1a,
+	0x0a, 0x08, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x77, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x83, 0x02, 0x0a, 0x05, 0x50,
+	0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x43,
+	0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f,
+	0x76, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76,
+	0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e,
+	0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x20,
+	0x0a, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x74, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x70, 0x74,
+	0x12, 0x24, 0x0a, 0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65,
+	0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76,
+	0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x70, 0x70,
+	0x72, 0x6f, 0x76, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x6a,
+	0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70,
+	0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x70,
+	0x70, 0x72, 0x6f, 0x76, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+	0x22, 0xc2, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74,
+	0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d,
+	0x65, 0x4f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65,
+	0x4f, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x61,
+	0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x12, 0x1e, 0x0a,
+	0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a,
+	0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75,
+	0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54,
+	0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63,
+	0x68, 0x54, 0x79, 0x70, 0x65, 0x22, 0x59, 0x0a, 0x0f, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c,
+	0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x5f,
+	0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x72, 0x72, 0x43,
+	0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x65, 0x72, 0x72, 0x5f, 0x6d, 0x73, 0x67, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x72, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x12, 0x0a, 0x04,
+	0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61,
+	0x32, 0x80, 0x01, 0x0a, 0x06, 0x42, 0x78, 0x43, 0x6f, 0x72, 0x65, 0x12, 0x36, 0x0a, 0x0d, 0x47,
+	0x65, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x62,
+	0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x1a,
+	0x12, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
+	0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x0b, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x6d,
+	0x69, 0x74, 0x12, 0x16, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61, 0x72,
+	0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x62, 0x78, 0x63,
 	0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52,
-	0x65, 0x71, 0x1a, 0x17, 0x2e, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x61, 0x72,
-	0x63, 0x68, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x42, 0x0a, 0x5a, 0x08, 0x2e,
-	0x2f, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x65, 0x73, 0x70, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x62, 0x78, 0x63, 0x6f, 0x72, 0x65, 0x62,
+	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (

+ 89 - 53
jyBXCore/rpc/util/search.go

@@ -22,49 +22,49 @@ import (
 )
 
 var (
-	ClearHtml    = regexp.MustCompile("<[^>]*>")
-	MatchSpace   = regexp.MustCompile("\\s+")
-	filterReg_3  = regexp.MustCompile("(项目|公告|公示)$")
-	filterReg_2  = regexp.MustCompile("^[)\\)>》】\\]}}〕,,;;::'\"“”。.\\??、/+=\\_—*&……\\^%$¥@!!`~·(\\(<《【\\[{{〔]+$")
-	filterReg_1  = regexp.MustCompile("^([0-9]{1,3}|[零一二三四五六七八九十]{1,2}|联系人?|电话|地址|编号|采购|政府采购|成交|更正|招标|中标|变更|结果)$")
-	filterReg    = regexp.MustCompile("^[的人号时元万公告项目地址电话邮编日期联系招标中结果成交项目项目采购采购项目政府采购公告更正公告]+$")
-	PhoneReg     = regexp.MustCompile("^[1][3-9][0-9]{9}$")
-	EmailPattern = regexp.MustCompile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")
+	ClearHtml  = regexp.MustCompile("<[^>]*>")
+	MatchSpace = regexp.MustCompile("\\s+")
+	filterReg3 = regexp.MustCompile("(项目|公告|公示)$")
+	filterReg2 = regexp.MustCompile("^[)\\)>》】\\]}}〕,,;;::'\"“”。.\\??、/+=\\_—*&……\\^%$¥@!!`~·(\\(<《【\\[{{〔]+$")
+	filterReg1 = regexp.MustCompile("^([0-9]{1,3}|[零一二三四五六七八九十]{1,2}|联系人?|电话|地址|编号|采购|政府采购|成交|更正|招标|中标|变更|结果)$")
+	filterReg  = regexp.MustCompile("^[的人号时元万公告项目地址电话邮编日期联系招标中结果成交项目项目采购采购项目政府采购公告更正公告]+$")
+	//PhoneReg     = regexp.MustCompile("^[1][3-9][0-9]{9}$")
+	//EmailPattern = regexp.MustCompile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")
 )
 
 // SearchHistory 格式化 关键词搜索历史记录
-func SearchHistory(history, searchValue, additionalWords string) (arrs []string) {
+func SearchHistory(history, searchValue, additionalWords string) (arrS []string) {
 	if searchValue != "" {
 		var searchKeys = []string{searchValue}
 		if additionalWords != "" {
 			searchKeys = append(searchKeys, strings.Split(additionalWords, ",")...)
 		}
-		arrs = strings.Split(history, ",")
+		arrS = strings.Split(history, ",")
 		//新增历史记录
 		if history == "" {
-			arrs = make([]string, 0)
+			arrS = make([]string, 0)
 		}
 		for _, sv := range searchKeys {
-			for k, v := range arrs {
+			for k, v := range arrS {
 				if v == strings.TrimSpace(sv) {
-					arrs = append(arrs[:k], arrs[k+1:]...)
+					arrS = append(arrS[:k], arrS[k+1:]...)
 					break
 				}
 			}
 		}
-		arrs = append(arrs, searchValue)
-		if len(arrs) > 10 {
-			arrs = arrs[len(searchKeys) : len(searchKeys)+10]
+		arrS = append(arrS, searchValue)
+		if len(arrS) > 10 {
+			arrS = arrS[len(searchKeys) : len(searchKeys)+10]
 		}
 	}
-	return arrs
+	return arrS
 }
 
 func FilterKey(k string) string {
 	k = strings.TrimSpace(k)
-	k = filterReg_3.ReplaceAllString(k, "")
-	k = filterReg_2.ReplaceAllString(k, "")
-	k = filterReg_1.ReplaceAllString(k, "")
+	k = filterReg3.ReplaceAllString(k, "")
+	k = filterReg2.ReplaceAllString(k, "")
+	k = filterReg1.ReplaceAllString(k, "")
 	k = filterReg.ReplaceAllString(k, "")
 	return k
 }
@@ -72,37 +72,37 @@ func FilterKey(k string) string {
 // InterceptSearchKW 超过keywordsLimit个字,截断
 //返回截取后的字符串和截取掉中的前3个字
 // b_word:截取后的关键词;a_word:截取后 后面三个字;s_word:已截取 处理过的关键词
-func InterceptSearchKW(word string, keywordsLimit int, isFilter bool) (b_word, a_word, s_word string) {
+func InterceptSearchKW(word string, keywordsLimit int, isFilter bool) (bWord, aWord, sWord string) {
 	if isFilter {
 		word = FilterKey(word)
 	}
 	word = MatchSpace.ReplaceAllString(strings.TrimSpace(word), " ")
 	words := []rune(word)
 	if len(words) > keywordsLimit {
-		b_word = string(words[:keywordsLimit])
-		b_word = strings.TrimSpace(b_word)
+		bWord = string(words[:keywordsLimit])
+		bWord = strings.TrimSpace(bWord)
 		if len(words) > keywordsLimit+3 {
-			a_word = string(words[keywordsLimit : keywordsLimit+3])
+			aWord = string(words[keywordsLimit : keywordsLimit+3])
 		} else {
-			a_word = string(words[keywordsLimit:])
+			aWord = string(words[keywordsLimit:])
 		}
 	} else {
-		b_word = word
+		bWord = word
 	}
-	a_word = strings.TrimSpace(a_word)
-	s_word = MatchSpace.ReplaceAllString(b_word, "+")
+	aWord = strings.TrimSpace(aWord)
+	sWord = MatchSpace.ReplaceAllString(bWord, IC.C.JYKeyMark)
 	return
 }
 
 func HttpEs(ques, analyzer, esAddress string) (res string) {
-	var addrs []string
-	surl := ""
+	var adders []string
+	curl := ""
 	for _, s := range strings.Split(esAddress, ",") {
-		addrs = append(addrs, s)
+		adders = append(adders, s)
 	}
-	i, _ := rand.Int(rand.Reader, big.NewInt(int64(len(addrs)))) //随机
-	surl = addrs[int(i.Int64())] + "/bidding/_analyze"
-	URL, _ := url.Parse(surl)
+	i, _ := rand.Int(rand.Reader, big.NewInt(int64(len(adders)))) //随机
+	curl = adders[int(i.Int64())] + "/bidding/_analyze"
+	URL, _ := url.Parse(curl)
 	Q := URL.Query()
 	Q.Add("text", ques)
 	Q.Add("analyzer", analyzer)
@@ -110,25 +110,25 @@ func HttpEs(ques, analyzer, esAddress string) (res string) {
 	resp, err := http.Get(URL.String())
 	if err != nil {
 		logx.Info("es连接失败 err1:", err)
-		resp, err = getESResp(ques, analyzer, addrs)
+		resp, err = getESResp(ques, analyzer, adders)
 		if err != nil {
 			return
 		}
 	}
-	result, err := ioutil.ReadAll(resp.Body)
-	if err == nil {
+	result, err1 := ioutil.ReadAll(resp.Body)
+	if err1 == nil {
 		defer resp.Body.Close()
-		var resmap map[string]interface{}
-		json.Unmarshal(result, &resmap)
-		if resmap != nil && resmap["tokens"] != nil {
-			tokens := MC.ObjArrToMapArr(resmap["tokens"].([]interface{}))
+		var resMap map[string]interface{}
+		json.Unmarshal(result, &resMap)
+		if resMap != nil && resMap["tokens"] != nil {
+			tokens := MC.ObjArrToMapArr(resMap["tokens"].([]interface{}))
 			for _, v := range tokens {
 				token := MC.ObjToString(v["token"])
 				if len([]rune(token)) == 1 && unicode.IsLetter([]rune(token)[0]) {
 					continue
 				}
-				if res != "" {
-					res += "+"
+				if res != "" && token != "" {
+					res += IC.C.JYKeyMark
 				}
 				res += token
 			}
@@ -138,10 +138,10 @@ func HttpEs(ques, analyzer, esAddress string) (res string) {
 }
 
 //
-func getESResp(ques, analyzer string, addrs []string) (resp *http.Response, err error) {
-	for _, v := range addrs {
-		surl := v + "/bidding/_analyze"
-		URL, _ := url.Parse(surl)
+func getESResp(ques, analyzer string, adds []string) (resp *http.Response, err error) {
+	for _, v := range adds {
+		curl := v + "/bidding/_analyze"
+		URL, _ := url.Parse(curl)
 		Q := URL.Query()
 		Q.Add("text", ques)
 		Q.Add("analyzer", analyzer)
@@ -155,10 +155,9 @@ func getESResp(ques, analyzer string, addrs []string) (resp *http.Response, err
 }
 
 const (
-	RedisName    = "other"
-	RedisNameNew = "newother"
-	//招标搜索分页--每页显示数量
-	SearchPageSize = 50
+	RedisName      = "other"
+	RedisNameNew   = "newother"
+	SearchPageSize = 50 //招标搜索分页--每页显示数量
 	//招标搜索分页--最大页数
 	SearchMaxPageNum       = 10  //免费用户500条记录
 	SearchMaxPageNum_PAYED = 100 //付费用户5000条记录
@@ -262,8 +261,8 @@ func SearchListFormat(industry string, repl *[]map[string]interface{}, b bool) (
 		if budget, ok := v["budget"].(float64); ok && budget > 0 {                                                  //预算
 			searchList.Budget = int64(budget)
 		}
-		if bidamount, ok := v["bidamount"].(float64); ok && bidamount > 0 { //中标金额
-			searchList.BidAmount = int64(bidamount)
+		if bidAmount, ok := v["bidamount"].(float64); ok && bidAmount > 0 { //中标金额
+			searchList.BidAmount = int64(bidAmount)
 		}
 		searchList.Buyer = MC.ObjToString(v["buyer"])                                                               //采购单位
 		searchList.BuyerTel = MC.ObjToString(v["buyertel"])                                                         //采购单位联系方式
@@ -351,3 +350,40 @@ func GetPublishTime(y, m int, publishTime string) string {
 }
 
 //20220114 P260搜索优化
+
+// GetSearchKeyWordsQueryStr 关键词处理 获取关键词查询条件
+func GetSearchKeyWordsQueryStr(in *bxcore.SearchReq) string {
+	var (
+		keyWords, searchWords []string
+	)
+	//主关键词词组
+	for _, mv := range strings.Split(in.KeyWords, IC.C.JYKeyMark) {
+		if strings.TrimSpace(mv) != "" {
+			keyWords = append(keyWords, mv)
+		}
+	}
+	//附加词组
+	//多组附加词,每组间,号隔开,每组内如果关键词中间有空格,自动分词
+	for _, agv := range strings.Split(in.AdditionalWords, ",") {
+		for _, av := range strings.Split(agv, IC.C.JYKeyMark) {
+			if strings.TrimSpace(av) != "" {
+				keyWords = append(keyWords, av)
+			}
+		}
+	}
+	// in.SearchMode 搜索模式:0:精准搜索;1:模糊搜索
+	// 精准搜索:不分词,完全匹配;(中间带空格的关键词组自动分词)
+	// 模糊搜索:对用户输入的单个关键词进行分词处理,但必须都存在;
+	if in.SearchMode == 1 {
+		for _, kv := range keyWords {
+			if strings.TrimSpace(kv) != "" {
+				if ikWords := HttpEs(kv, "ik_smart", IC.DB.Es.Addr); ikWords != "" {
+					searchWords = append(searchWords, ikWords)
+				}
+			}
+		}
+	} else {
+		searchWords = append(searchWords, keyWords...)
+	}
+	return strings.Join(searchWords, IC.C.JYKeyMark)
+}