wangchuanjin 5 ماه پیش
والد
کامیت
05d9477f61

+ 4 - 0
go.mod

@@ -12,6 +12,7 @@ require (
 )
 
 require (
+	app.yhyue.com/moapp/esv1 v0.0.0-20220414031211-3da4123e648d // indirect
 	app.yhyue.com/moapp/jyMarketing v0.0.2-0.20230304035551-21bb1eedf547 // indirect
 	app.yhyue.com/moapp/jyPoints v1.1.2-0.20231020023521-1a4b1bbf9736 // indirect
 	bp.jydev.jianyu360.cn/BaseService/entManageApplication v0.0.0-20231226074509-942d80dc34eb // indirect
@@ -64,8 +65,11 @@ require (
 	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/olekukonko/tablewriter v0.0.5 // indirect
+	github.com/olivere/elastic v6.2.37+incompatible // indirect
+	github.com/olivere/elastic/v7 v7.0.22 // indirect
 	github.com/openzipkin/zipkin-go v0.4.2 // indirect
 	github.com/pelletier/go-toml/v2 v2.2.0 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.18.0 // indirect
 	github.com/prometheus/client_model v0.5.0 // indirect
 	github.com/prometheus/common v0.45.0 // indirect

+ 4 - 0
go.sum

@@ -1,3 +1,4 @@
+app.yhyue.com/moapp/esv1 v0.0.0-20220414031211-3da4123e648d h1:WPsYuuptAd3UEgN+jPzpnsDe/OvcshDUUtOTZPYGSJ8=
 app.yhyue.com/moapp/esv1 v0.0.0-20220414031211-3da4123e648d/go.mod h1:91/lSD/hS+ckMVP3WdidRzDhC60lLMdyce9QHy0cSMA=
 app.yhyue.com/moapp/jyMarketing v0.0.2-0.20230304035551-21bb1eedf547 h1:cCmWQW8DUBD2nuZNDz9aIe6MrlioxTbdaA2YiJhlzjY=
 app.yhyue.com/moapp/jyMarketing v0.0.2-0.20230304035551-21bb1eedf547/go.mod h1:JvIs8uKjdT963+7JnZGIEcL4ctBiBjwkoz0kNyigE78=
@@ -171,6 +172,7 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
 github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
+github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -515,7 +517,9 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/olivere/elastic v6.2.37+incompatible h1:UfSGJem5czY+x/LqxgeCBgjDn6St+z8OnsCuxwD3L0U=
 github.com/olivere/elastic v6.2.37+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
+github.com/olivere/elastic/v7 v7.0.22 h1:esBA6JJwvYgfms0EVlH7Z+9J4oQ/WUADF2y/nCNDw7s=
 github.com/olivere/elastic/v7 v7.0.22/go.mod h1:VDexNy9NjmtAkrjNoI7tImv7FR4tf5zUA3ickqu5Pc8=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

+ 5 - 4
internal/controller/aiSearch/aiSearch_v1_chat.go

@@ -16,9 +16,10 @@ import (
 )
 
 func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatRes, err error) {
-	content := fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "prompt").String(), req.Content)
+	content := fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "doubaoPrompt").String(), gtime.Now().Format("Ymd"), req.Content)
 	query, largeModelReply, err := c.doubao(ctx, content)
 	if err != nil {
+		content = fmt.Sprintf(g.Cfg("ai_search.yaml").MustGet(ctx, "zhipuPrompt").String(), gtime.Now().Format("Ymd"), req.Content)
 		query, largeModelReply, err = c.zhipu(ctx, content)
 	}
 	log.Println(query, largeModelReply, err)
@@ -27,7 +28,7 @@ func (c *ControllerV1) Chat(ctx context.Context, req *v1.ChatReq) (res *v1.ChatR
 
 //调用豆包大模型
 func (c *ControllerV1) doubao(ctx context.Context, content string) (string, string, error) {
-	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf("aiSearch_doubaoCall_%s", gtime.Now().Format("YYYYmmdd")))
+	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf("aiSearch_doubaoCall_%s", gtime.Now().Format("Ymd")))
 	if err != nil {
 		g.Log().Error(ctx, "从redis获取doubao调用次数出错", err)
 		return "", "", err
@@ -53,7 +54,7 @@ func (c *ControllerV1) doubao(ctx context.Context, content string) (string, stri
 
 //调用智普大模型
 func (c *ControllerV1) zhipu(ctx context.Context, content string) (string, string, error) {
-	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf("aiSearch_doubaoCall_%s", gtime.Now().Format("YYYYmmdd")))
+	count, err := g.Redis("main").Incr(ctx, fmt.Sprintf("aiSearch_zhipuCall_%s", gtime.Now().Format("YYYYmmdd")))
 	if err != nil {
 		g.Log().Error(ctx, "从redis获取zhipu调用次数出错", err)
 		return "", "", err
@@ -93,7 +94,7 @@ func (c *ControllerV1) post(ctx context.Context, t, apiURL, pass string, request
 		return "", "", err
 	}
 	largeModelReply := string(b)
-	g.Log().Error(ctx, t, "请求回复", largeModelReply)
+	g.Log().Info(ctx, t, "请求回复", largeModelReply)
 	r, re := gjson.LoadJson(b)
 	if re != nil {
 		g.Log().Error(ctx, t, largeModelReply, "gjson.LoadJson出错", re)

+ 624 - 0
internal/model/bidSearch/bidSearch.go

@@ -0,0 +1,624 @@
+package bidSearch
+
+import (
+	"context"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+
+	. "app.yhyue.com/moapp/jybase/common"
+	. "app.yhyue.com/moapp/jybase/encrypt"
+	elastic "app.yhyue.com/moapp/jybase/es"
+	"github.com/gogf/gf/v2/encoding/gjson"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gtime"
+)
+
+const (
+	JYKeyMark               = "+"
+	MultiMatch              = `{"multi_match": {"query": "%s","type": "phrase", "fields": [%s]}}`
+	Query                   = `{"query":{"bool":{"must":[%s],"must_not":[%s]}}%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}}}]}}`
+	QueryBoolMustTermBool   = `{"bool": {"must": [{ "term": {"%s": %t }}]}}`
+	QueryBoolMustA          = `{"bool":{"must":[{"terms":{"%s":[%s]}}]}}`
+	queryExists             = `{"constant_score":{"filter":{"exists":{"field":"%s"}}}}`
+	gte                     = `"gte": %s`
+	lte                     = `"lte": %s`
+	INDEX                   = "bidding"
+	TYPE                    = "bidding"
+	BidSearchSort           = `{"dataweight":"desc","publishtime":"desc"}`
+	BidSearchFieldBase      = `"_id","title","publishtime","dataweight","toptype","subtype","type","area","city","s_subscopeclass","bidamount","budget","buyerclass","isValidFile","district"` //搜索列表基础字段
+)
+
+var (
+	//信息类型 一级类型参数和数据类型转换
+	topTypeMap = map[string]string{
+		"招标预告":   "预告",
+		"招标公告":   "招标",
+		"招标结果":   "结果",
+		"招标信用信息": "其它",
+		"拟建项目":   "拟建",
+		"采购意向":   "采购意向",
+	}
+)
+
+type BidSearch struct {
+	ctx             context.Context
+	PositionId      int64
+	PageNum         int64  //当前页码
+	PageSize        int64  //每页数量
+	Province        string //省份
+	City            string //城市
+	Subtype         string //信息类型-二级
+	TopType         string //信息类型-一级分类
+	PublishTime     string //发布时间
+	SelectType      string //搜索范围:标题;正文等
+	Price           string //价格
+	Industry        string //行业
+	BuyerClass      string //采购单位类型
+	BuyerTel        string //采购单位联系方式
+	WinnerTel       string //中标单位联系方式
+	FileExists      string //是否有附件
+	WordsMode       int64  //搜索关键词模式;默认0:包含所有,1:包含任意
+	KeyWords        string //关键词:多个空格隔开(主)
+	AdditionalWords string //关键词:附加关键词(副:五组,每组最多15个字符)
+	ExclusionWords  string //关键词:排除词(副:五组,每组最多15个字符)
+	District        string //区县
+	Buyer           string //采购单位
+	Winner          string //中标企业
+	Agency          string //代理机构
+}
+
+func NewBidSearch(ctx context.Context, positionId int64, content string) (*BidSearch, error) {
+	c, e := gjson.LoadJson([]byte(content))
+	if e != nil {
+		g.Log().Error(ctx, positionId, "查询条件转换出错", e)
+		return nil, e
+	}
+	keyWords, exclusionWords := []string{}, []string{}
+	if keyWordJson := c.GetJson("关键词"); keyWordJson != nil {
+		keyWords = keyWordJson.Get("选择").Strings()
+		exclusionWords = keyWordJson.Get("排除").Strings()
+	}
+	area, city := []string{}, []string{}
+	if areaJson := c.GetJson("地区"); areaJson != nil {
+		area = areaJson.Get("选择").Strings()
+		//exclusionArea = areaJson.Get("排除").Strings()
+	}
+	subtype, topType := []string{}, []string{}
+	publishTime := "lately-30"
+	var paramFilter = func(v string) string {
+		if v == "全部" || v == "不限" {
+			return ""
+		}
+		return strings.ReplaceAll(v, " ", "")
+	}
+	pt := paramFilter(c.Get("发布时间范围").String())
+	if pts := strings.Split(pt, "-"); len(pts) == 2 {
+		pt_s, pt_s_e := gtime.StrToTimeFormat(pts[0], "Ymd")
+		pt_e, pt_e_e := gtime.StrToTimeFormat(pts[1], "Ymd")
+		if pt_s_e != nil || pt_e_e != nil {
+			g.Log().Error(ctx, positionId, "发布时间转换出错", pt, pt_s_e, pt_e_e)
+		} else {
+			publishTime = fmt.Sprintf("%d-%d", pt_s.Unix(), pt_e.Unix())
+		}
+	}
+	price := strings.ReplaceAll(paramFilter(c.Get("金额").String()), "万", "")
+	industry := paramFilter(c.Get("industry").String())
+	buyerClass := paramFilter(c.Get("采购单位类型").String())
+	buyerTel := paramFilter(c.Get("采购单位联系方式").String())
+	winnerTel := paramFilter(c.Get("中标单位联系方式").String())
+	selectType := []string{}
+	for _, t := range strings.Split(paramFilter(c.Get("搜索范围").String()), ",") {
+		if t == "content" {
+			selectType = append(selectType, "detail")
+		} else if t == "buyer" {
+			selectType = append(selectType, "buyer.mbuyer")
+		} else if t == "winner" {
+			selectType = append(selectType, "s_winner.mwinner")
+		} else if t == "agency" {
+			selectType = append(selectType, "agency.magency")
+		} else if t == "title" {
+			selectType = append(selectType, "title")
+		} else if t == "ppa" {
+			selectType = append(selectType, []string{"purchasing", "projectnamb.pname"}...)
+		} else if t == "file" { //dev4.7.8 标讯优化:搜索范围附件-》全部用户可用
+			selectType = append(selectType, "filetext")
+		}
+	}
+	if len(selectType) == 0 {
+		selectType = []string{"title", "detail"}
+	}
+	var wordsMode int64
+	if c.Get("匹配模式").String() == "模糊匹配" {
+		wordsMode = 1
+	}
+	bs := &BidSearch{
+		PositionId:      positionId,
+		PageNum:         0,                                                                //当前页码
+		PageSize:        g.Cfg("ai_search.yaml").MustGet(ctx, "allBidListMaxLen").Int64(), //每页数量
+		Province:        strings.Join(area, ","),                                          //省份
+		City:            strings.Join(city, ","),                                          //城市
+		Subtype:         strings.Join(subtype, ","),                                       //信息类型-二级
+		TopType:         strings.Join(topType, ","),                                       //信息类型-一级分类
+		PublishTime:     publishTime,                                                      //发布时间
+		SelectType:      strings.Join(selectType, ","),                                    //搜索范围:标题;正文等
+		Price:           price,                                                            //价格
+		Industry:        industry,                                                         //行业
+		BuyerClass:      buyerClass,                                                       //采购单位类型
+		BuyerTel:        buyerTel,                                                         //采购单位联系方式
+		WinnerTel:       winnerTel,                                                        //中标单位联系方式
+		FileExists:      "",                                                               //是否有附件
+		WordsMode:       wordsMode,                                                        //搜索关键词模式;默认0:包含所有,1:包含任意
+		KeyWords:        strings.Join(keyWords, " "),                                      //关键词:多个空格隔开(主)
+		AdditionalWords: "",                                                               //关键词:附加关键词(副:五组,每组最多15个字符)
+		ExclusionWords:  strings.Join(exclusionWords, ","),                                //关键词:排除词(副:五组,每组最多15个字符)
+		District:        "",
+		Buyer:           paramFilter(c.Get("采购单位").String()),
+		Winner:          paramFilter(c.Get("中标企业").String()),
+		Agency:          paramFilter(c.Get("招标代理").String()),
+	}
+	return bs, nil
+}
+
+func (b *BidSearch) Search() (string, []map[string]interface{}) {
+	qstr := b.GetSearchQuery()
+	list := elastic.Get(INDEX, TYPE, qstr)
+	result := []map[string]interface{}{}
+	if list != nil {
+		for _, v := range *list {
+			m := map[string]interface{}{
+				"id":          EncodeArticleId2ByCheck(ObjToString(v["_id"])),                                     //ME.EncodeArticleId2ByCheck(ObjToString(v["_id"]))                                         //加密信息id
+				"area":        ObjToString(v["area"]),                                                             //地区
+				"buyerClass":  ObjToString(v["buyerclass"]),                                                       //采购单位类型
+				"city":        ObjToString(v["city"]),                                                             //城市
+				"district":    ObjToString(v["district"]),                                                         // 区县       //城市
+				"industry":    b.IndustryFormat(b.Industry, strings.Trim(ObjToString(v["s_subscopeclass"]), ",")), //行业
+				"publishTime": Int64All(v["publishtime"]),                                                         //发布时间
+				"subtype":     ObjToString(v["subtype"]),                                                          //信息类型
+				"title":       ObjToString(v["title"]),
+			}
+			m["fileExists"], _ = v["isValidFile"].(bool)               //是否有附件
+			if budget, ok := v["budget"].(float64); ok && budget > 0 { //预算
+				m["budget"] = int64(budget)
+			}
+			if bidAmount, ok := v["bidamount"].(float64); ok && bidAmount > 0 { //中标金额
+				m["bidamount"] = int64(bidAmount)
+			}
+			result = append(result, m)
+		}
+	}
+	return qstr, result
+}
+
+// GetSearchQuery  整理关键词等查询条件
+func (b *BidSearch) GetSearchQuery() (qstr string) {
+	mustQuery := b.MustQuery()
+	var (
+		//搜索范围是否只有附件
+		//搜索范围只选择附件,是否有附件条件无效;
+		isFileSearch                            = b.SelectType == "filetext"
+		wordsMusts, wordsShould, musts, mustNot []string
+		findFields                              string
+		selectTypeArr                           = strings.Split(b.SelectType, ",")
+	)
+	if selectTypeArr == nil || len(selectTypeArr) == 0 {
+		findFields = `"title"`
+	} else {
+		findFields = fmt.Sprintf(`"%s"`, strings.Join(selectTypeArr, "\",\""))
+	}
+	switchBool := strings.Contains(findFields, "detail") && strings.Contains(findFields, "title")
+	if mustQuery != "" {
+		musts = append(musts, mustQuery)
+	}
+	//采购单位
+	if b.Buyer != "" {
+		musts = append(musts, b.GetMatchArrSql("buyer.mbuyer", strings.Split(b.Buyer, ",")...))
+	}
+	//中标单位
+	if b.Winner != "" {
+		musts = append(musts, b.GetMatchArrSql("s_winner.mwinner", strings.Split(b.Winner, ",")...))
+	}
+	//代理机构
+	if b.Agency != "" {
+		musts = append(musts, b.GetMatchArrSql("agency.magency", strings.Split(b.Agency, ",")...))
+	}
+	//此时关键词中间有IC.C.JYKeyMark进行隔离
+	if b.KeyWords != "" {
+		var (
+			keyWordsMusts []string
+		)
+		for _, v := range strings.Split(b.KeyWords, JYKeyMark) {
+			if elastic.ReplaceYH(v) == "" {
+				continue
+			}
+			//单个字  搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+			//detail 正文不支持单字查询
+			if len([]rune(elastic.ReplaceYH(v))) == 1 && b.DetailFileORTitle(findFields) {
+				findFields += `,"title"`
+			} else 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)
+				}
+			}
+			keyWordsMusts = append(keyWordsMusts, fmt.Sprintf(fmt.Sprintf(MultiMatch, "%s", findFields), elastic.ReplaceYH(v)))
+		}
+		//搜索关键词模式;默认0:包含所有,1:包含任意
+		if b.WordsMode == 1 {
+			wordsShould = append(wordsShould, fmt.Sprintf(elastic.NgramMust, strings.Join(keyWordsMusts, ",")))
+		} else {
+			wordsMusts = append(wordsMusts, keyWordsMusts...)
+		}
+	}
+	//附加词
+	if b.AdditionalWords != "" {
+		//多组附加词,每组间,号隔开。每组内如果关键词中间有空格,自动分词
+		var (
+			addWordsMusts []string
+		)
+		for _, aws := range strings.Split(b.AdditionalWords, ",") {
+			var (
+				addWordsMust []string
+			)
+			for _, v := range strings.Split(aws, JYKeyMark) {
+				if elastic.ReplaceYH(v) == "" {
+					continue
+				}
+				//单个字  搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+				//detail 正文不支持单字查询
+				if len([]rune(elastic.ReplaceYH(v))) == 1 && b.DetailFileORTitle(findFields) {
+					findFields += `,"title"`
+				} else 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)
+					}
+				}
+				addWordsMust = append(addWordsMust, fmt.Sprintf(fmt.Sprintf(MultiMatch, "%s", findFields), elastic.ReplaceYH(v)))
+				addWordsMusts = append(addWordsMusts, addWordsMust...)
+				if b.WordsMode == 0 {
+					wordsMusts = append(wordsMusts, addWordsMust...)
+				}
+				addWordsMust = []string{}
+			}
+			//搜索关键词模式;默认0:包含所有,1:包含任意
+			if b.WordsMode == 1 {
+				wordsShould = append(wordsShould, fmt.Sprintf(elastic.NgramMust, strings.Join(addWordsMusts, ",")))
+				addWordsMusts = []string{}
+			}
+		}
+	}
+	//搜索关键词模式;默认0:包含所有,1:包含任意
+	//包含任意一组
+	if len(wordsShould) > 0 {
+		musts = append(musts, fmt.Sprintf(QueryBoolShould, strings.Join(wordsShould, ",")))
+	} else if len(wordsMusts) > 0 {
+		musts = append(musts, fmt.Sprintf(elastic.NgramMust, strings.Join(wordsMusts, ",")))
+	}
+	//排除词
+	if notKey := strings.TrimSpace(b.ExclusionWords); notKey != "" {
+		notKeyMultiMatch := fmt.Sprintf(MultiMatch, "%s", findFields)
+		var notKeyMustNot []string
+		//多组排除词
+		for _, nks := range strings.Split(notKey, ",") {
+			//单组排除词 空格分割
+			for _, v := range strings.Split(nks, JYKeyMark) {
+				v = strings.TrimSpace(v)
+				if v == "" {
+					continue
+				}
+				if len([]rune(elastic.ReplaceYH(v))) == 1 {
+					//单个字 搜索范围 有全文或者附件 无标题 例如:学 虚拟机 detail  搜索的时候加上标题
+					if b.DetailFileORTitle(findFields) {
+						notKeyMultiMatch = fmt.Sprintf(MultiMatch, "%s", findFields+`,"title"`)
+					}
+				}
+				notKeyMustNot = append(notKeyMustNot, fmt.Sprintf(notKeyMultiMatch, elastic.ReplaceYH(v)))
+			}
+		}
+		mustNot = append(mustNot, fmt.Sprintf(QueryBoolShould, strings.Join(notKeyMustNot, ",")))
+	}
+	//行业
+	if b.Industry != "" {
+		musts = append(musts, fmt.Sprintf(QueryBoolMustA, "s_subscopeclass", `"`+strings.ReplaceAll(b.Industry, ",", `","`)+`"`))
+	}
+	//价格
+	if b.Price != "" && len(strings.Split(b.Price, "-")) > 1 {
+		minPrice, maxPrice := strings.Split(b.Price, "-")[0], strings.Split(b.Price, "-")[1]
+		if minPrice != "" || maxPrice != "" {
+			sq := ``
+			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 minPrice != "" {
+				sq += fmt.Sprintf(gte, minPrice)
+			}
+			if minPrice != "" && maxPrice != "" {
+				sq += `,`
+			}
+			if maxPrice != "" {
+				sq += fmt.Sprintf(lte, maxPrice)
+			}
+			if minPrice != "" || maxPrice != "" {
+				query_price := fmt.Sprintf(QueryBoolShould, fmt.Sprintf(queryBoolMustBoolShould, sq, sq))
+				musts = append(musts, query_price)
+			}
+		}
+	}
+	//采购单位联系方式
+	hasBuyerTel := b.BuyerTel
+	if hasBuyerTel != "" {
+		if hasBuyerTel == "y" {
+			musts = append(musts, fmt.Sprintf(queryExists, "buyertel"))
+		} else {
+			mustNot = append(mustNot, fmt.Sprintf(queryExists, "buyertel"))
+		}
+	}
+	//中标企业联系方式
+	hasWinnerTel := b.WinnerTel
+	if hasWinnerTel != "" {
+		if hasWinnerTel == "y" {
+			musts = append(musts, fmt.Sprintf(queryExists, "winnertel"))
+		} else {
+			mustNot = append(mustNot, fmt.Sprintf(queryExists, "winnertel"))
+		}
+	}
+	//附件--非BI
+	fileExists := b.FileExists
+	if !isFileSearch && fileExists != "" {
+		if fileExists == "1" { //有附件
+			musts = append(musts, fmt.Sprintf(QueryBoolMustTermBool, "isValidFile", true))
+		} else if fileExists == "-1" { //无附件
+			mustNot = append(mustNot, fmt.Sprintf(QueryBoolMustTermBool, "isValidFile", true))
+		}
+	}
+	//b.BidField  剑鱼默认招标信息搜索 此参数为空**
+	qstr = fmt.Sprintf(Query, strings.Join(musts, ","), strings.Join(mustNot, ","), fmt.Sprintf(`,"_source":[%s],"sort":[%s],"from":%d,"size":%d`, BidSearchFieldBase, BidSearchSort, b.PageNum, b.PageSize))
+	return
+}
+
+// GetBidSearchQuery  整理地区、城市、发布时间、信息类型、采购单位类型 查询条件
+func (b *BidSearch) MustQuery() string {
+	query := ``
+	//省份
+	area := b.Province
+	if area != "" {
+		query += `{"terms":{"area":[`
+		for k, v := range strings.Split(area, ",") {
+			if k > 0 {
+				query += `,`
+			}
+			query += `"` + v + `"`
+		}
+		query += `]}}`
+	}
+	//市--未登录用户不能根据市和地区筛选
+	city := b.City
+	if city != "" {
+		if len(query) > 0 {
+			query += ","
+		}
+		query += `{"terms":{"city":[`
+		for k, v := range strings.Split(city, ",") {
+			if k > 0 {
+				query += `,`
+			}
+			query += `"` + v + `"`
+		}
+		query += `]}}`
+	}
+	district := b.District
+	if district != "" {
+		if len(query) > 0 {
+			query += ","
+		}
+		for k, v := range strings.Split(district, ",") {
+			if k > 0 {
+				query += `,`
+			}
+			cityName := strings.Split(v, "_")[0]
+			districtName := strings.Split(v, "_")[1]
+			queryBoolMustAndDistrict := `{"bool":{"must":[{"terms":{"city":["%s"]}},{"terms":{"district":["%s"]}}]}}`
+			query += fmt.Sprintf(queryBoolMustAndDistrict, cityName, districtName)
+		}
+	}
+	if query != "" {
+		query = fmt.Sprintf(QueryBoolShould, query)
+	}
+	//发布时间
+	publishTime := b.PublishTime
+	if publishTime != "" {
+		startTime, endTime := "", ""
+		now := time.Now()
+		switch publishTime {
+		case "lately-7":
+			startTime = fmt.Sprint(time.Date(now.Year(), now.Month(), now.Day()-7, 0, 0, 0, 0, time.Local).Unix())
+		case "lately-30":
+			startTime = fmt.Sprint(time.Date(now.Year(), now.Month(), now.Day()-30, 0, 0, 0, 0, time.Local).Unix())
+		case "thisyear":
+			startTime = fmt.Sprint(time.Date(now.Year()-1, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.Local).Unix())
+			endTime = fmt.Sprint(now.Unix())
+		case "threeyear":
+			startTime = fmt.Sprint(time.Date(now.Year()-3, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.Local).Unix())
+			endTime = fmt.Sprint(now.Unix())
+		case "fiveyear":
+			startTime = fmt.Sprint(time.Date(now.Year()-5, now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.Local).Unix())
+			endTime = fmt.Sprint(now.Unix())
+		default:
+			if len(strings.Split(publishTime, "-")) > 1 {
+				startTime = strings.Split(publishTime, "-")[0]
+				endTime = strings.Split(publishTime, "-")[1]
+				//电脑端 时间选择 开始时间当天和结束时间当天相同
+				if startTime == endTime {
+					et, _ := strconv.ParseInt(endTime, 0, 64)
+					etTime := time.Unix(et, 0)
+					endTime = fmt.Sprint(time.Date(etTime.Year(), etTime.Month(), etTime.Day()+1, 0, 0, 0, 0, time.Local).Unix())
+				}
+			}
+		}
+		if startTime != "" || endTime != "" {
+			if len(query) > 0 {
+				query += ","
+			}
+			query += `{"range":{"publishtime":{`
+			if startTime != "" {
+				query += `"gte":` + startTime
+			}
+			if startTime != "" && endTime != "" {
+				query += `,`
+			}
+			if endTime != "" {
+				query += `"lt":` + endTime
+			}
+			query += `}}}`
+		}
+	}
+	//信息类型-二级
+	subtype := b.Subtype
+	topType := If(b.TopType != "", strings.Split(b.TopType, ","), []string{}).([]string)
+	allType := ``
+	//二级分类
+	if subtype != "" {
+		var typeInt = 0
+		allType += `{"terms":{"subtype":[`
+		for k, v := range strings.Split(subtype, ",") {
+			if tType := If(topTypeMap[v] != "" && b.TopType == "", topTypeMap[v], "").(string); tType != "" {
+				topType = append(topType, tType)
+				typeInt += 1
+				continue
+			}
+			if k > typeInt {
+				allType += `,`
+			}
+			allType += `"` + v + `"`
+		}
+		allType += `]}}`
+		if typeInt == len(strings.Split(subtype, ",")) {
+			allType = ``
+		}
+	}
+	//信息类型  一级分类
+	if len(topType) > 0 {
+		if allType != "" {
+			allType += ","
+		}
+		allType += `{"terms":{"toptype":[`
+		for k, v := range topType {
+			if k > 0 {
+				allType += `,`
+			}
+			allType += `"` + v + `"`
+		}
+		allType += `]}}`
+	}
+
+	if allType != "" {
+		if query != "" {
+			query += ","
+		}
+		query += fmt.Sprintf(QueryBoolShould, allType)
+	}
+	//采购单位类型
+	buyerClass := b.BuyerClass
+	if buyerClass != "" {
+		if len(query) > 0 {
+			query += ","
+		}
+		query += `{"terms":{"buyerclass":[`
+		for k, v := range strings.Split(buyerClass, ",") {
+			if k > 0 {
+				query += `,`
+			}
+			query += `"` + v + `"`
+		}
+		query += `]}`
+	}
+	return query
+}
+
+// DetailFileORTitle 包含正文或 附件 不包含标题
+func (b *BidSearch) DetailFileORTitle(findFields string) bool {
+	return (strings.Contains(findFields, `"detail"`) || strings.Contains(findFields, `"filetext"`)) && !strings.Contains(findFields, `"title"`)
+}
+
+// 采购单位、中标企业、代理机构
+func (b *BidSearch) GetMatchArrSql(field string, val ...string) (sql string) {
+	if len(val) == 0 {
+		return
+	}
+	var (
+		arr []string
+		i   int
+	)
+	for _, s := range val {
+		if s == "" {
+			continue
+		}
+		if len([]rune(s)) > 30 {
+			s = string([]rune(s)[:30])
+		}
+		i++
+		arr = append(arr, fmt.Sprintf(`{"match_phrase": {"%s": "%s"}}`, field, s))
+		if i > 4 {
+			break
+		}
+	}
+	if len(arr) == 0 {
+		return ""
+	}
+	return fmt.Sprintf(`{"bool": {"should": [%s],"minimum_should_match": 1}}`, strings.Join(arr, ","))
+}
+
+// IndustryFormat 行业处理
+func (b *BidSearch) IndustryFormat(industry, subScopeClass string) (newIndustry string) {
+	commonSubstring := func(v string) (value string) {
+		bcs := strings.Split(v, "_")
+		if len(bcs) == 1 {
+			value = bcs[0]
+		} else if len(bcs) == 2 {
+			value = bcs[0]
+			if strings.TrimSpace(value) == "" {
+				value = bcs[0]
+			}
+		}
+		return
+	}
+	bct := strings.Split(subScopeClass, ",")
+	if bct == nil || len(bct) == 0 {
+		return
+	}
+	//搜索条件中没有行业的话,取查询结果中第一个行业
+	if industry == "" {
+		newIndustry = commonSubstring(bct[0])
+	} else { //搜索条件中有行业的话,取行业中和搜索条件相对应的第一个
+		industryArr := strings.Split(industry, ",")
+	L:
+		for _, bc := range bct {
+			for _, is := range industryArr {
+				if bc == is {
+					newIndustry = strings.TrimSpace(commonSubstring(bc))
+					break L
+				}
+			}
+		}
+	}
+	return
+}

+ 38 - 0
internal/model/bidSearch/bidSearch_test.go

@@ -0,0 +1,38 @@
+package bidSearch
+
+import (
+	"context"
+	"log"
+	"testing"
+
+	"app.yhyue.com/moapp/jybase/es"
+)
+
+func TestSearch(t *testing.T) {
+	es.NewEs("v7", "http://172.20.45.129:9206", 2, "", "")
+	bs, err := NewBidSearch(context.Background(), 0, `{
+"关键词": {
+"选择": ["软件"],
+"排除": []
+},
+"发布时间范围": "20210126-20250226",
+"搜索范围": ["标题", "正文"],
+"匹配模式": "精准匹配",
+"信息类型": "招标公告",
+"地区": {
+"选择": ["广东", "广西", "海南","北京"],
+"排除": []
+},
+"金额": "0-2000万",
+"采购单位联系方式": "不限",
+"中标单位联系方式": "不限",
+"附件": "不限",
+"采购单位": "不限",
+"中标单位": "不限",
+"招标代理": "不限"
+}`)
+	log.Println(err)
+	qstr, list := bs.Search()
+	log.Println(qstr)
+	log.Println(list)
+}

+ 7 - 0
internal/model/bidSearch/logs/2025-02-26.log

@@ -0,0 +1,7 @@
+2025-02-26 16:16:08.532 [ERRO] 0 发布时间转换出错 20250126-20250226 time.ParseInLocation failed for layout "2006/01/02" and value "20250126": parsing time "20250126" as "2006/01/02": cannot parse "0126" as "/" time.ParseInLocation failed for layout "2006/01/02" and value "20250226": parsing time "20250226" as "2006/01/02": cannot parse "0226" as "/" 
+Stack:
+1.  aiChat/internal/model/bidSearch.NewBidSearch
+    D:/workspace/go_project/SocialPlatform/aiChat/internal/model/bidSearch/bidSearch.go:105
+2.  aiChat/internal/model/bidSearch.TestSearch
+    D:/workspace/go_project/SocialPlatform/aiChat/internal/model/bidSearch/bidSearch_test.go:13
+

+ 117 - 20
manifest/config/ai_search.yaml

@@ -2,32 +2,129 @@ aaa: 111
 timeout: 30000
 doubaoCallMax: 100
 zhipuCallMax: 100
-prompt: "######
+bestBidListMaxLen: 5
+allBidListMaxLen: 100
+doubaoPrompt: '######
 背景知识
 《剑鱼标讯检索系统》具备信息检索能力,提供的检索字段如下:
 1. 关键词 ,是用户希望搜索的关键词汇,需要从用户意图中提炼,可以是物品名称、服务名称、产品名称、工程名称,公司名称,一些相关的其他品牌,如果是品牌词,请提供中文和英文2套,仅品牌词支持英文,关键词全部是中文;可以有多组关键词,1组关键词之间可以用空格连接起来,实现逻辑and 且的匹配;多组关键词之间是 or 或者的逻辑关系。
-2. 发布时间范围, 信息发布时间范围,如:最近7天、最近30天、最近一年、最近三年、最近五年,自定义日期范围;若没有明确要求,可以选择“最近30天”
+2. 发布时间范围, 根据用户需求时间进行减法推理,格式 YYYYMMDD-YYYYMMDD;若没有明确要求按照30天进行推理输出结果
 3. 信息类型,有以下选项:
 3.1、信息一级分类:拟建项目,采购意向,招标预告,招标公告,招标结果,招标信用信息
 3.2、信息二级分类:预告,预审,预审结果,论证意见,需求公示,招标,邀标,询价,竞谈,变更,中标,成交,废标,流标,合同,验收,违规
-4. 地区,全国省、市县标签;若没有明确要求,可以选择“全国”
-5. 行业,有以下选项一级分类:【全部、建筑工程、水利水电、能源化工、弱电安防、信息技术、行政办公、机械设备、交通工程、医疗卫生、市政设施、服务采购、农林牧渔、其他】;二级分类【勘察设计,工程施工,监理咨询,材料设备,水电安装,水利工程,发电工程,航运工程、其他工程,原材料,仪表仪器,新能源,化工产品,设备,综合布线,智能家居,智能系统,系统集成及安全,软件开发,运维服务,办公家具,通用办公设备,专业设备,生活用品,办公用品,矿山机械,工程机械,机械零部件,机床相关,车辆,其他机械设备,道路,轨道,桥梁,隧道,设备,耗材,药品,道路,绿化,线路管网,综合项目,法律咨询,会计,物业,审计,安保,仓储物流,广告宣传印发,生产物资,生产设备,相关服务,其他】若没有明确要求,可以选择“全部”
-6. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择“不限”
-7.采购单位类型: 党政机关事业单位: ['人大', '政协', '党委办', '组织', '宣传', '统战', '纪委', '政府办', '发改', '财政', '教育', '科技', '工信', '民政', '民宗', '人社', '公安', '检察院', '法院', '司法', '应急管理', '军队', '自然资源', '生态环境', '住建', '市政', '城管', '交通', '水利', '农业', '气象', '文旅', '卫健委', '医疗', '学校', '档案', '体育', '政务中心', '机关事务', '国资委', '海关', '税务', '市场监管', '商务', '人行', '银保监', '证监', '审计', '出版广电', '统计', '公共资源交易', '社会团体'], 企业: ['传媒', '采矿业', '电信行业', '金融业', '建筑业', '能源化工', '农林牧渔', '批发零售', '信息技术', '运输物流', '制造业', '住宿餐饮'] ,若没有明确要求,可以选择“全部”
+4. 地区:【全国、国内所有省市县名称(不在一一列举,输出具体省市县名称)】(注意:把用户的意图转换为标准的省市名称,如:华北地区转换为["北京","天津","河北","山西","内蒙古自治区"]);若没有明确要求,可以选择「全国」
+5. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择"不限"
+6. 搜索范围:标题,正文,附件,中标企业,项目名称/标的物,采购单位,招标代理机构。若没有明确要求,可以选择["标题","正文"]
+7. 附件:有附件,无附件,默认"不限"
+8.匹配模式:精准匹配,模糊匹配,若没有明确要求,可以选择"精准匹配"
+9.中标单位:中标单位/企业名称,如:xxx的中标信息,若没有明确要求,可以选择"不限"
+10.采购单位:发布招标信息,采买货物、服务、工程的企业/机构名称或简称,若没有明确要求,可以选择"不限"
+注意:我是xx公司的采销员,xx公司并非采购单位,注意排除
 ######
-%s
+你的能力,熟练使用《剑鱼标讯检索系统》检索能力,可以根据用户提出的需求,进行分析提炼,并精准对齐行业以及采购单位类型,理解用户关键业务需求,结合《剑鱼标讯检索系统》要求,输出检索条件。我希望能根据我说的物品来精准检索,并给出能够对齐上述知识的关键词,排除词,目的是为了用户能够迅速且精准的招投标,以及成交
+
+######
+分析举例:
+1、近一个月拓普公司的中标信息有多少?
+分析:发布时间范围:20250101-20250201,关键词:拓普,信息类型:招标结果,中标单位:拓普公司
+2、华为发布的招投标信息有哪些?
+分析:关键词:华为,信息类型:招标公告,采购单位:华为
+3、我要查看关于打印机销售的信息,排除标题含有"进口"的标讯信息
+分析:"关键词": {
+        "选择": ["打印机"],
+        "排除": ["进口"]
+    },搜索范围:标题
+4、我想要河南省新乡市原阳县、延津县的笔记本销售信息
+分析:关键词:笔记本,"地区": {
+"选择": ["原阳县", "延津县"],
+"排除": []
+},
+
+
 ######
 输出要求,不需要说明,不需要解释,直接输出结果。以JSON格式输出《剑鱼标讯检索系统》各个字段应该填充值,并进行JSON格式化。
-例如:{“关键词”:[”考勤机 得力”,“考勤系统”],
-“发布时间范围”:”2022/01/01 - 2023/01/01”,
-“信息类型”:”全部”,
-“地区”:”全国”,
-”采购单位类型”:”信息技术”,
-”金额”:”不限”,
-“排除词”:“”,
-“采购单位联系方式”:“不限”,
-“中标单位联系方式”:“不限”,
-“采购单位”:“河南科技大学”,
-“中标企业”:“洛阳理工大学”,
-“招标代理”:“洛阳工程有线公司”
-}"
+例如:{"关键词":{"选择":["考勤机 得力","考勤系统"],
+               "排除":[]},
+"发布时间范围":"20220101-20230101",
+"搜索范围":["标题"],
+"匹配模式":精准匹配
+"信息类型":"全部",
+"地区":{
+    "选择":"全国",
+    "排除":[],
+},
+"金额":"不限",
+"采购单位联系方式":"不限",
+"中标单位联系方式":"不限",
+"附件":"不限"
+"采购单位":"河南科技大学",
+"中标单位":"洛阳理工大学",
+"招标代理":"洛阳工程有线公司",
+}
+
+######
+用户需求:
+当前时间:%s
+%s'
+zhipuPrompt: '######
+背景知识
+《剑鱼标讯检索系统》具备信息检索能力,提供的检索字段如下:
+1. 关键词 ,是用户希望搜索的关键词汇,需要从用户意图中提炼,可以是物品名称、服务名称、产品名称、工程名称,公司名称,一些相关的其他品牌,如果是品牌词,请提供中文和英文2套,仅品牌词支持英文,关键词全部是中文;可以有多组关键词,1组关键词之间可以用空格连接起来,实现逻辑and 且的匹配;多组关键词之间是 or 或者的逻辑关系。
+2. 发布时间范围, 根据用户需求时间进行减法推理,格式 YYYYMMDD-YYYYMMDD;若没有明确要求按照30天进行推理输出结果
+3. 信息类型,有以下选项:
+3.1、信息一级分类:拟建项目,采购意向,招标预告,招标公告,招标结果,招标信用信息
+3.2、信息二级分类:预告,预审,预审结果,论证意见,需求公示,招标,邀标,询价,竞谈,变更,中标,成交,废标,流标,合同,验收,违规
+4. 地区:【全国、国内所有省市县名称(不在一一列举,输出具体省市县名称)】(注意:把用户的意图转换为标准的省市名称,如:华北地区转换为["北京","天津","河北","山西","内蒙古自治区"]);若没有明确要求,可以选择「全国」
+5. 金额,项目金额范围,如:0-10万,10-20万,20-50万,50-100万,100万-200万,200万-500万,500万-1000万,1000万以上,自定义范围。若没有明确要求,可以选择"不限"
+6. 搜索范围:标题,正文,附件,中标企业,项目名称/标的物,采购单位,招标代理机构。若没有明确要求,可以选择["标题","正文"]
+7. 附件:有附件,无附件,默认"不限"
+8.匹配模式:精准匹配,模糊匹配,若没有明确要求,可以选择"精准匹配"
+9.中标单位:中标单位/企业名称,如:xxx的中标信息,若没有明确要求,可以选择"不限"
+10.采购单位:发布招标信息,采买货物、服务、工程的企业/机构名称或简称,若没有明确要求,可以选择"不限"
+注意:我是xx公司的采销员,xx公司并非采购单位,注意排除
+######
+你的能力,熟练使用《剑鱼标讯检索系统》检索能力,可以根据用户提出的需求,进行分析提炼,并精准对齐行业以及采购单位类型,理解用户关键业务需求,结合《剑鱼标讯检索系统》要求,输出检索条件。我希望能根据我说的物品来精准检索,并给出能够对齐上述知识的关键词,排除词,目的是为了用户能够迅速且精准的招投标,以及成交
+
+######
+分析举例:
+1、近一个月拓普公司的中标信息有多少?
+分析:发布时间范围:20250101-20250201,关键词:拓普,信息类型:招标结果,中标单位:拓普公司
+2、华为发布的招投标信息有哪些?
+分析:关键词:华为,信息类型:招标公告,采购单位:华为
+3、我要查看关于打印机销售的信息,排除标题含有"进口"的标讯信息
+分析:"关键词": {
+        "选择": ["打印机"],
+        "排除": ["进口"]
+    },搜索范围:标题
+4、我想要河南省新乡市原阳县、延津县的笔记本销售信息
+分析:关键词:笔记本,"地区": {
+"选择": ["原阳县", "延津县"],
+"排除": []
+},
+
+
+######
+输出要求,不需要说明,不需要解释,直接输出结果。以JSON格式输出《剑鱼标讯检索系统》各个字段应该填充值,并进行JSON格式化。
+例如:{"关键词":{"选择":["考勤机 得力","考勤系统"],
+               "排除":[]},
+"发布时间范围":"20220101-20230101",
+"搜索范围":["标题"],
+"匹配模式":精准匹配
+"信息类型":"全部",
+"地区":{
+    "选择":"全国",
+    "排除":[],
+},
+"金额":"不限",
+"采购单位联系方式":"不限",
+"中标单位联系方式":"不限",
+"附件":"不限"
+"采购单位":"河南科技大学",
+"中标单位":"洛阳理工大学",
+"招标代理":"洛阳工程有线公司",
+}
+
+######
+用户需求:
+当前时间:%s
+%s'

+ 6 - 0
manifest/config/config.yaml

@@ -82,3 +82,9 @@ logger:
 history:
   time: 10 # 多少秒之内的数据
   limit: 10 # 多少条
+elasticsearch:
+  address: "http://172.20.45.129:9206"
+  size: 3
+  version: "v7"
+  userName: ""
+  password: ""

+ 16 - 7
utility/elastic.go

@@ -1,14 +1,23 @@
 package utility
 
+import (
+	"app.yhyue.com/moapp/jybase/es"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gctx"
+)
+
 type esConf struct {
-	Address string `json:"address"`
-	Size    int    `json:"size"`
+	Address  string `json:"address"`
+	Size     int    `json:"size"`
+	Version  string `json:"version"`
+	UserName string `json:"userName"`
+	Password string `json:"password"`
 }
 
 func init() {
-	//var EsConf esConf
-	//ctx := gctx.New()
-	//_ = g.Cfg().MustGet(ctx, "elasticsearch", "").Scan(&EsConf)
-	//elastic.InitElasticSize(EsConf.Address, EsConf.Size)
-	//g.Log().Info(ctx, "初始化 elasticsearch", EsConf)
+	var EsConf esConf
+	ctx := gctx.New()
+	_ = g.Cfg().MustGet(ctx, "elasticsearch", "").Scan(&EsConf)
+	es.NewEs(EsConf.Version, EsConf.Address, EsConf.Size, EsConf.UserName, EsConf.Password)
+	g.Log().Info(ctx, "初始化 elasticsearch", EsConf)
 }