Browse Source

新增es搜索

xiexiaoyuan 3 years ago
parent
commit
c4c8742e54

+ 19 - 0
config/config.go

@@ -1,11 +1,14 @@
 package config
 
+import "time"
+
 type Config struct {
 	Log    Log    `mapstructure:"log" json:"log" yaml:"log"`
 	Serve  Serve  `mapstructure:"serve" json:"serve" yaml:"serve"`
 	Mysql  Mysql  `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
 	Redis  Redis  `mapstructure:"redis" json:"redis" yaml:"redis"`
 	AliOss AliOss `mapstructure:"ali-oss" json:"ali-oss" yaml:"ali-oss"`
+	EsClient     EsClient `mapstructure:"es_client" json:"es_client" yaml:"es_client"`
 }
 
 // Serve gin服务配置
@@ -64,3 +67,19 @@ type AliOss struct {
 	AccessKeyId     string `mapstructure:"access-key-id" json:"access-key-id" yaml:"access-key-id" description:"access-key-id"`
 	AccessKeySecret string `mapstructure:"access-key-secret" json:"access-key-secret" yaml:"access-key-secret" description:"access-key-secret"`
 }
+
+// EsClient es客户端配置
+type EsClient struct {
+	// 终端地址
+	Endpoints string `json:"endpoints" yaml:"endpoints"`
+	// 用户
+	Username string `json:"username" yaml:"username"`
+	// 密码
+	Password string `json:"password" yaml:"password"`
+	// 超时时间,单位ms
+	Timeout time.Duration `json:"timeout" yaml:"timeout"`
+	// es日志目录
+	Log string `json:"log" yaml:"log"`
+	// 索引前缀
+	Prefix  string `json:"prefix" yaml:"prefix"`
+}

+ 1 - 5
controller/company/company_permission.go

@@ -39,11 +39,7 @@ func GetPermissionList(c *gin.Context)  {
 
 func GetHomeFiccPermissions(c *gin.Context) {
 	userinfo := userService.GetInfoByClaims(c)
-	// 判断用户是否有已购权限
-	if userinfo.CompanyID == 0 {
-		response.Fail("无权操作", c)
-		return
-	}
+
 	list, err := company.GetHomeFiccPermissions(userinfo)
 	if err !=nil {
 		response.Fail(err.Error(), c)

+ 31 - 0
controller/report/report.go

@@ -137,4 +137,35 @@ func CollectReportList(c *gin.Context) {
 	}
 	response.OkData("查询成功", list, c )
 	return
+}
+
+func Search(c *gin.Context) {
+	keyWord := c.DefaultQuery("key_word", "")
+	reqPageIndex := c.DefaultQuery("current_index", "1")
+	reqPageSize := c.DefaultQuery("page_size", strconv.Itoa(utils.PageSize20))
+
+	pageIndex, err := strconv.Atoi(reqPageIndex)
+	if err != nil {
+		response.Fail("请输入正确的条数限制", c)
+		return
+	}
+
+	pageSize, err := strconv.Atoi(reqPageSize)
+	if err != nil {
+		response.Fail("请输入正确的页码", c)
+		return
+	}
+
+	if keyWord == ""{
+		response.Fail("请输入搜索词", c)
+		return
+	}
+	userinfo := userService.GetInfoByClaims(c)
+	data, err := report.SearchReport(userinfo, keyWord, pageIndex, pageSize)
+	if err != nil {
+		response.Fail(err.Error(), c)
+		return
+	}
+	response.OkData("查询成功", data, c)
+	return
 }

+ 2 - 1
core/run_server.go

@@ -16,7 +16,8 @@ func RunServe() {
 		//初始化redis
 		init_serve.Redis()
 	}
-
+	//初始化elasticSearch 搜索客户端
+	init_serve.NewEsClient()
 	// 3.监听端口,默认在8080
 	// Run("里面不指定端口号默认为8080")
 	err := r.Run(fmt.Sprint("0.0.0.0:", global.CONFIG.Serve.Port)) // 监听并在 0.0.0.0:8080 上启动服务

+ 2 - 0
global/global.go

@@ -2,6 +2,7 @@ package global
 
 import (
 	"github.com/go-redis/redis/v8"
+	"github.com/olivere/elastic/v7"
 	oplogging "github.com/op/go-logging"
 	"gorm.io/gorm"
 	"hongze/hongze_yb/config"
@@ -15,4 +16,5 @@ var (
 	MYSQL_LOG     io.Writer
 	DEFAULT_MYSQL *gorm.DB      //默认数据库连接配置
 	Redis         *redis.Client //redis链接
+	EsClient      *elastic.Client
 )

+ 2 - 1
go.mod

@@ -18,6 +18,7 @@ require (
 	github.com/mattn/go-isatty v0.0.14 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
+	github.com/olivere/elastic/v7 v7.0.31
 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
 	github.com/satori/go.uuid v1.2.0 // indirect
 	github.com/shopspring/decimal v1.2.0
@@ -28,7 +29,7 @@ require (
 	github.com/yidane/formula v0.0.0-20210902154546-0782e1736717
 	golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
 	golang.org/x/image v0.0.0-20190802002840-cff245a6509b
-	golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 // indirect
+	golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42
 	golang.org/x/text v0.3.7 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df

+ 33 - 0
init_serve/EsClient.go

@@ -0,0 +1,33 @@
+package init_serve
+
+import (
+	"github.com/olivere/elastic/v7"
+	"hongze/hongze_yb/global"
+	"log"
+	"os"
+)
+
+func NewEsClient()  {
+	esConfig := global.CONFIG.EsClient
+	client, err := elastic.NewClient(
+		elastic.SetURL(esConfig.Endpoints),                         // 支持多个地址,用逗号分隔即可
+		elastic.SetBasicAuth(esConfig.Username, esConfig.Password), // 基于http base auth 验证机制的账号密码
+		elastic.SetSniff(false),                                    // 是否应该定期检查集群
+		elastic.SetHealthcheck(false),                              // 是否开启健康检查
+	//	elastic.SetInfoLog(newEsLog(esConfig.Log+"/es_info.log", "Info")),
+	//	elastic.SetErrorLog(newEsLog(esConfig.Log+"/es_error.log", "Error")),
+	//	elastic.SetTraceLog(newEsLog(esConfig.Log+"/es_trace.log", "trace")),
+	)
+	if err != nil {
+		global.LOG.Error("newEsClient init error,err=", err)
+		panic("newEsClient 初始化失败:" + err.Error())
+	}
+
+	//全局赋值redis链接
+	global.EsClient = client
+}
+
+func newEsLog(file string, level string) *log.Logger {
+	logFile, _ := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
+	return log.New(logFile, "ES-"+level+": ", 0)
+}

+ 15 - 0
models/response/report.go

@@ -116,4 +116,19 @@ type ReportCollectListItem struct {
 type ReportCollectResp struct {
 	Paging     *PagingItem  		`json:"paging"`
 	List []*ReportCollectListItem `json:"list"`
+}
+
+type EsReportItem struct {
+	Author             string `description:"作者"`
+	BodyContent        string `description:"内容"`
+	Categories         string `description:"品种名称"`
+	ClassifyIdFirst    int    `description:"一级分类id"`
+	ClassifyNameFirst  string `description:"一级分类名称"`
+	ClassifyIdSecond   int    `description:"二级分类id"`
+	ClassifyNameSecond string `description:"二级分类名称"`
+	PublishState       int    `description:"1:未发布,2:已发布"`
+	PublishTime        string `description:"发布时间"`
+	ReportChapterId    int    `description:"报告章节Id"`
+	ReportId           int    `description:"报告Id"`
+	Title              string `description:"标题"`
 }

+ 22 - 0
models/tables/report_chapter_type_permission/query.go

@@ -0,0 +1,22 @@
+package report_chapter_type_permission
+
+import (
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+// GetTypeIdsByChartPermissionId 根据权限查询对应的章节
+func GetTypeIdsByChartPermissionId(chartPermissionId int) (typeIds []int, err error)  {
+	var list []*ReportChapterTypePermission
+	err = global.DEFAULT_MYSQL.Model(ReportChapterTypePermission{}).Where("chart_permission_id = ?", chartPermissionId).Scan(&list).Error
+	if err == utils.ErrNoRow {
+		err = nil
+	}
+	if err != nil {
+		return
+	}
+	for _, v := range list {
+		typeIds = append(typeIds, int(v.ReportChapterTypeId))
+	}
+	return
+}

+ 13 - 0
models/tables/report_chapter_type_permission/report_chapter_type_permission.go

@@ -0,0 +1,13 @@
+package report_chapter_type_permission
+
+type ReportChapterTypePermission struct {
+	Id                     int
+	ChartPermissionID      uint64
+	ResearchType           string
+	ReportChapterTypeId    uint64
+}
+
+func (r *ReportChapterTypePermission) TableName() string {
+	return "report_chapter_type_permission"
+}
+

+ 2 - 0
routers/report.go

@@ -12,6 +12,7 @@ func InitReport(r *gin.Engine)  {
 	rGroup.GET("/chapter/detail", report.ChapterDetail)
 	rGroup.GET("/list", report.List)
 	rGroup.GET("/collect", report.CollectReportList)
+	rGroup.GET("/search", report.Search)
 
 	rGroup2 := r.Group("api/classify").Use(middleware.Token())
 	rGroup2.GET("/", report.ClassifyFirstList)
@@ -20,4 +21,5 @@ func InitReport(r *gin.Engine)  {
 	rGroup2.GET("/detail", report.ClassifyDetail)
 	rGroup2.GET("/detail/reports", report.ClassifyDetailReports)
 
+
 }

+ 138 - 0
services/elastic/report.go

@@ -0,0 +1,138 @@
+package elastic
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"github.com/olivere/elastic/v7"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+func SearchReport(keyWord string, pageIndex, pageSize int) (searchResp *elastic.SearchResult, total int64, err error) {
+	indexName := global.CONFIG.EsClient.Prefix+utils.ES_INDEX_RDDP_REPORT
+	var must  []map[string]interface{}
+
+	shouldSub := []map[string]interface{}{
+		map[string]interface{}{
+			"match": map[string]interface{}{
+				"Title": map[string]interface{}{
+					"query": keyWord,
+				//"minimum_should_match": "60%",
+					"boost": 3,
+				},
+			},
+		},
+		map[string]interface{}{
+			"match": map[string]interface{}{
+				"Categories": map[string]interface{}{
+					"query": keyWord,
+					//"minimum_should_match": "60%",
+					"boost": 2,
+				},
+			},
+		},
+		map[string]interface{}{
+			"match": map[string]interface{}{
+				"BodyContent": map[string]interface{}{
+					"query": keyWord,
+					//"minimum_should_match": "60%",
+					"boost": 1,
+				},
+			},
+		},
+	}
+	mustMap := map[string]interface{}{
+		"bool": map[string]interface{}{
+			"should": shouldSub,
+		},
+	}
+	must = append(must, mustMap)
+
+	must = append(must, map[string]interface{}{
+		"match": map[string]interface{}{
+			"PublishState": 2,
+		},
+	})
+	should := []map[string]interface{}{
+		map[string]interface{}{
+			"match_phrase": map[string]interface{}{
+				"Title": map[string]interface{}{
+					"query": keyWord,
+					"slop": "50",
+				},
+			},
+		},
+		map[string]interface{}{
+			"match_phrase": map[string]interface{}{
+				"Categories": map[string]interface{}{
+					"query": keyWord,
+					"slop": "50",
+				},
+			},
+		},
+		map[string]interface{}{
+			"match_phrase": map[string]interface{}{
+				"BodyContent": map[string]interface{}{
+					"query": keyWord,
+					"slop": "50",
+				},
+			},
+		},
+	}
+	source := map[string]interface{}{
+		"query": map[string]interface{}{
+			"bool": map[string]interface{}{
+				"must": must,
+				"should": should,
+			},
+		},
+	}
+	source["from"] = (pageIndex - 1) * pageSize
+	source["size"] = pageSize
+	source["highlight"] = map[string]interface{}{
+		"fields": map[string]interface{}{
+			"Title":map[string]interface{}{},
+			"Categories":map[string]interface{}{},
+			"BodyContent":map[string]interface{}{},
+		},
+		"pre_tags" : "<font size='4.5' color='#473BFF'>",
+		"post_tags": "</font>",
+	}
+
+	source["sort"] = []map[string]interface{}{
+		map[string]interface{}{
+			"_score":map[string]interface{}{
+				"order":"desc",
+			},
+		},
+		map[string]interface{}{
+			"PublishTime.keyword":map[string]interface{}{
+				"order":"desc",
+			},
+		},
+	}
+	fmt.Println(source)
+	/*highlight := elastic.NewHighlight()
+	highlight = highlight.Fields(elastic.NewHighlighterField("content"), elastic.NewHighlighterField("title"))
+	highlight = highlight.PreTags("<font color='red'>").PostTags("</font>")*/
+	request := global.EsClient.Search(indexName).Source(source) // sets the JSON request
+
+//	searchMap := make(map[string]string)
+
+	searchResp, err = request.Do(context.Background())
+	if err != nil {
+		fmt.Print("结果err:")
+		fmt.Println(err.Error())
+		return
+	}
+
+	fmt.Print("结果正常:")
+	fmt.Println(searchResp.Hits)
+	fmt.Println(searchResp.Status)
+	if searchResp.Status != 0 {
+		err = errors.New("查询失败")
+	}
+	total = searchResp.TotalHits()
+	return
+}

+ 68 - 1
services/report/report.go

@@ -1,6 +1,7 @@
 package report
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 	"hongze/hongze_yb/global"
@@ -13,9 +14,13 @@ import (
 	"hongze/hongze_yb/models/tables/rddp/report"
 	"hongze/hongze_yb/models/tables/rddp/report_chapter"
 	"hongze/hongze_yb/models/tables/report_chapter_type"
+	"hongze/hongze_yb/models/tables/report_chapter_type_permission"
 	"hongze/hongze_yb/services/company"
+	elasticService "hongze/hongze_yb/services/elastic"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
+	"html"
+	"time"
 )
 
 func GetLatestClassReport(permissionIds []int, userId uint64) (purchaseList []*purchase.PurchaseListItem, err error)  {
@@ -482,7 +487,7 @@ func GetCollectReportList(user user.UserInfo, chartPermissionId, pageIndex, page
 	}
 
 	// 查询晨报和周报相对应的章节ID
-	reportChapterTypeIds, err := report_chapter_type.GetTypeIDByReportChapterTypeName(permissionInfo.PermissionName)
+	reportChapterTypeIds, err := report_chapter_type_permission.GetTypeIdsByChartPermissionId(chartPermissionId)
 	if err != nil {
 		errMsg = err.Error()
 		err = errors.New("查询权限对应的章节出错")
@@ -510,4 +515,66 @@ func GetCollectReportList(user user.UserInfo, chartPermissionId, pageIndex, page
 	ret.List = reportList
 	ret.Paging = response.GetPaging(pageIndex, pageSize, int(total))
 	return
+}
+
+func SearchReport(user user.UserInfo, keyWord string, pageIndex, pageSize int)(ret *response.ReportCollectResp, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("SearchReport: userId=%d, err:%s, errMsg:%s", user.UserID, err.Error(), errMsg))
+		}
+	}()
+	searchResp, total, err := elasticService.SearchReport(keyWord, pageIndex, pageSize)
+	if err != nil {
+		errMsg = err.Error()
+		err = errors.New("查询失败")
+		return
+	}
+	var reportList []*response.ReportCollectListItem
+	if searchResp.Hits != nil {
+		for _, v := range searchResp.Hits.Hits {
+			temp := new(response.ReportCollectListItem)
+			itemJson, tmpErr := v.Source.MarshalJSON()
+			if tmpErr != nil {
+				errMsg = tmpErr.Error()
+				err = errors.New("解析出错")
+				return
+			}
+			reportItem := new(response.EsReportItem)
+			tmpErr = json.Unmarshal(itemJson, &reportItem)
+			if tmpErr != nil {
+				errMsg = tmpErr.Error()
+				err = errors.New("解析json出错")
+				return
+			}
+			temp.ReportId = reportItem.ReportId
+			temp.ClassifyIdFirst = reportItem.ClassifyIdFirst
+			temp.ClassifyNameFirst = reportItem.ClassifyNameFirst
+			temp.ClassifyIdSecond = reportItem.ClassifyIdSecond
+			temp.ClassifyNameSecond = reportItem.ClassifyNameSecond
+			temp.Title = reportItem.Title
+			temp.ContentSub = reportItem.BodyContent
+			temp.PublishTime, err = time.Parse("2006-01-02 15:04:05", reportItem.PublishTime)
+			fmt.Println(*reportItem)
+			if len(v.Highlight["Title"]) > 0 {
+				temp.Title = v.Highlight["Title"][0]
+			}
+			if len(v.Highlight["BodyContent"]) > 0 {
+				temp.ContentSub = v.Highlight["BodyContent"][0]
+			}
+			if len(v.Highlight["Categories"]) > 0 {
+				if temp.ClassifyNameSecond != "" {
+					temp.ClassifyNameSecond = html.EscapeString("<font size='4.5' color='#473BFF'>"+temp.ClassifyNameSecond+"</font>")
+				}
+				if temp.ClassifyNameFirst != "" {
+					temp.ClassifyNameFirst = html.EscapeString("<font size='4.5' color='#473BFF'>"+temp.ClassifyNameFirst+"</font>")
+				}
+			}
+			reportList = append(reportList, temp)
+		}
+	}
+	ret = new(response.ReportCollectResp)
+	ret.List = reportList
+	ret.Paging = response.GetPaging(pageIndex, pageSize, int(total))
+	return
 }

+ 7 - 0
utils/constants.go

@@ -104,3 +104,10 @@ var PermissionFiccClassifyArr = [...]string{"宏观经济", "化工产业", "黑
 const (
 	CACHE_KEY_USER_VIEW = "user_view_record" //用户阅读数据
 )
+
+
+// es相关
+
+const (
+	ES_INDEX_RDDP_REPORT = "research_report_v1"                //报告
+)