kobe6258 7 months ago
parent
commit
477669ded4

+ 225 - 65
common/component/es/es.go

@@ -9,6 +9,8 @@ import (
 	"eta_mini_ht_api/common/contants"
 	"github.com/elastic/go-elasticsearch/v7"
 	"github.com/elastic/go-elasticsearch/v7/esapi"
+	"io"
+	"strings"
 	"sync"
 )
 
@@ -25,6 +27,14 @@ type ESClient struct {
 	esOp *elasticsearch.Client
 }
 
+type SearchType string
+
+const (
+	MatchAll = "match_all"
+	Match    = "match"
+	Range    = "range"
+)
+
 func GetInstance() *ESClient {
 	esOnce.Do(func() {
 		// 检查是否成功获取到RedisConfig实例,没有配置则不进行redis初始化
@@ -63,44 +73,6 @@ func init() {
 	logger.Info("es初始化成功")
 }
 
-//
-//func CreateIndex(indexName string) error {
-//	resp, err := esClient.es().Indices.
-//		Create(indexName).
-//		Do(context.Background())
-//	if err != nil {
-//		logger.Error("创建ES索引失败:%v", err)
-//		return err
-//	}
-//	fmt.Printf("index:%#v\n", resp.Index)
-//	return nil
-//}
-
-// DeleteIndex 删除索引
-//func DeleteIndex(indexName string) error {
-//	_, err := esClient.es().Indices. // 表明是对索引的操作,而Index则表示是要操作具体索引下的文档
-//						Delete(indexName).
-//						Do(context.Background())
-//	if err != nil {
-//		fmt.Printf("delete index failed,err:%v\n", err)
-//		return err
-//	}
-//	fmt.Printf("delete index successed,indexName:%s", indexName)
-//	return nil
-//}
-//
-//// CreateDocument 创建文档
-//func CreateDocument(indexName string, id string, doc interface{}) {
-//	// 添加文档
-//	resp, err := esClient.esOp.Index(indexName).Id(id).Document(doc).Do(context.Background())
-//	if err != nil {
-//		logger.Error("indexing document failed, err:%v\n", err)
-//		return
-//	}
-//	logger.Info("result:%#v\n", resp.Result)
-//	return
-//}
-
 // BulkInsert 批量创建文档
 func (es *ESClient) BulkInsert(indexName string, docs []ESBase) (err error) {
 	// 创建批量请求
@@ -141,36 +113,187 @@ func (es *ESClient) BulkInsert(indexName string, docs []ESBase) (err error) {
 	return
 }
 
-///*
-//*
+type ESResponse struct {
+	Took     int        `json:"took"`
+	TimedOut bool       `json:"timed_out"`
+	Hits     Hits       `json:"hits"`
+	_Shards  ShardsInfo `json:"_shards"`
+}
+
+type Hits struct {
+	Total    TotalHits `json:"total"`
+	MaxScore float64   `json:"max_score"`
+	Hits     []Hit     `json:"hits"`
+}
+
+type TotalHits struct {
+	Value    int    `json:"value"`
+	Relation string `json:"relation"`
+}
+
+type Hit struct {
+	Index     string          `json:"_index"`
+	Type      string          `json:"_type"`
+	ID        string          `json:"_id"`
+	Score     float64         `json:"_score"`
+	Source    json.RawMessage `json:"_source"`
+	Highlight json.RawMessage `json:"highlight"`
+}
+
+type ShardsInfo struct {
+	Total      int `json:"total"`
+	Successful int `json:"successful"`
+	Skipped    int `json:"skipped"`
+	Failed     int `json:"failed"`
+}
+type ESQueryRequest struct {
+	IndexName   string
+	From        int
+	Size        int
+	Key         string
+	Column      string
+	Sorts       []string
+	Type        SearchType
+	RangeColumn string
+	Max         interface{}
+	Min         interface{}
+}
+
+func (req *ESQueryRequest) CreateESQueryRequest(index string, column string, key string, from int, size int, sorts []string, searchType SearchType) *ESQueryRequest {
+	return &ESQueryRequest{
+		IndexName: index,
+		Type:      searchType,
+		From:      from,
+		Size:      size,
+		Key:       key,
+		Column:    column,
+		Sorts:     sorts,
+	}
+}
+
+func (req *ESQueryRequest) Range(from int64, to int64, column string) *ESQueryRequest {
+	req.RangeColumn = column
+	req.Max = to
+	req.Min = from
+	return req
+}
+
+func (req *ESQueryRequest) parseJsonQuery() (queryMap map[string]interface{}) {
+	switch req.Type {
+	case MatchAll:
+		queryMap = map[string]interface{}{
+			"query": map[string]interface{}{
+				"match_all": map[string]interface{}{},
+			},
+		}
+		return
+	case Match:
+		queryMap = map[string]interface{}{
+			"query": map[string]interface{}{
+				"match": map[string]interface{}{
+					req.Column: req.Key,
+				},
+			},
+			"highlight": map[string]interface{}{
+				"fields": map[string]interface{}{
+					req.Column: map[string]interface{}{},
+				},
+				"pre_tags":  []string{"<span style='color:red'>"},
+				"post_tags": []string{"</span>"},
+			},
+		}
+		return
+	case Range:
+		queryMap = map[string]interface{}{
+			"query": map[string]interface{}{
+				"match": map[string]interface{}{
+					req.Column: req.Key,
+				},
+			},
+			"highlight": map[string]interface{}{
+				"fields": map[string]interface{}{
+					req.Column: map[string]interface{}{},
+				},
+				"pre_tags":  []string{"<span style='color:red'>"},
+				"post_tags": []string{"</span>"},
+			},
+			"post_filter": map[string]interface{}{
+				"range": map[string]interface{}{
+					req.RangeColumn: map[string]interface{}{
+						"gte": req.Min,
+						"lte": req.Max,
+					},
+				},
+			},
+		}
+		return
+	default:
+		queryMap = map[string]interface{}{}
+		return
+	}
+}
+
+// /*
+// *
 //
 //	搜索
 //
-//indexName 访问索引名
-//query	搜索条件
-//from    开始搜索位置
-//size	搜索条数
-//sort 	排序
-//*/
-//func EsSearch(indexName string, query map[string]interface{}, from int, size int, sort []map[string]string) HitsData {
-//	searchQuery := map[string]interface{}{
-//		"query": query,
-//		"from":  from,
-//		"size":  size,
-//		"sort":  sort,
-//	}
-//	esClient.esOp.Create()
-//	req := httplib.Post(esUrl + indexName + "/_search")
-//	req.JSONBody(searchQuery)
-//	str, err := req.String()
-//	if err != nil {
-//		fmt.Println("elasticsearch is error ", err)
-//	}
-//	fmt.Println(str)
-//	var stb ReqSearchData
-//	err = json.Unmarshal([]byte(str), &stb)
-//	return stb.Hits
-//}
+// indexName 访问索引名
+// query	搜索条件
+// from    开始搜索位置
+// size	搜索条数
+// sort 	排序
+// */
+
+func (es *ESClient) Search(params *ESQueryRequest) (response ESResponse, err error) {
+	queryMap := params.parseJsonQuery()
+	jsonQuery, _ := json.Marshal(queryMap)
+	request := esapi.SearchRequest{
+		Index: []string{params.IndexName},
+		Body:  strings.NewReader(string(jsonQuery)),
+		From:  &params.From,
+		Size:  &params.Size,
+		Sort:  params.Sorts,
+	}
+	res, err := request.Do(context.Background(), esClient.esOp)
+
+	defer res.Body.Close()
+	if err != nil {
+		logger.Error("es查询失败: %s", err)
+	}
+	if res.IsError() {
+		var e map[string]interface{}
+		if err = json.NewDecoder(res.Body).Decode(&e); err != nil {
+			logger.Error("解析es应答失败: %v", err)
+		} else {
+			// Print the response status and error information.
+			logger.Error("es请求失败: %s: %v\n", res.Status(), err)
+		}
+	}
+	body, err := io.ReadAll(res.Body)
+	if err != nil {
+		logger.Error("获取es应答失败: %v", err)
+	}
+	return parseESResponse(body)
+}
+func parseESResponse(body []byte) (ESResponse, error) {
+	var response ESResponse
+	if err := json.Unmarshal(body, &response); err != nil {
+		return ESResponse{}, err
+	}
+	for _, hit := range response.Hits.Hits {
+		var source map[string]interface{}
+		if err := json.Unmarshal(hit.Source, &source); err != nil {
+			return ESResponse{}, err
+		}
+	}
+	return response, nil
+}
+
+func (es *ESClient) GetSource(hits Hits) []Hit {
+	return hits.Hits
+}
+
 //
 ///*
 //*
@@ -227,3 +350,40 @@ func (es *ESClient) BulkInsert(indexName string, docs []ESBase) (err error) {
 //	return true
 //
 //}
+//
+//func CreateIndex(indexName string) error {
+//	resp, err := esClient.es().Indices.
+//		Create(indexName).
+//		Do(context.Background())
+//	if err != nil {
+//		logger.Error("创建ES索引失败:%v", err)
+//		return err
+//	}
+//	fmt.Printf("index:%#v\n", resp.Index)
+//	return nil
+//}
+
+// DeleteIndex 删除索引
+//func DeleteIndex(indexName string) error {
+//	_, err := esClient.es().Indices. // 表明是对索引的操作,而Index则表示是要操作具体索引下的文档
+//						Delete(indexName).
+//						Do(context.Background())
+//	if err != nil {
+//		fmt.Printf("delete index failed,err:%v\n", err)
+//		return err
+//	}
+//	fmt.Printf("delete index successed,indexName:%s", indexName)
+//	return nil
+//}
+//
+//// CreateDocument 创建文档
+//func CreateDocument(indexName string, id string, doc interface{}) {
+//	// 添加文档
+//	resp, err := esClient.esOp.Index(indexName).Id(id).Document(doc).Do(context.Background())
+//	if err != nil {
+//		logger.Error("indexing document failed, err:%v\n", err)
+//		return
+//	}
+//	logger.Info("result:%#v\n", resp.Result)
+//	return
+//}

+ 6 - 0
common/exception/exc_enums.go

@@ -59,6 +59,9 @@ const (
 	ReportRecordClickCountFailed
 	GetHotRandListFailed
 	QueryReportPageFailed
+	SearchReportPageFailed
+	GetReportFailed
+	SearchKeyEmptyError
 )
 
 // ErrorMap 用于存储错误码和错误信息的映射
@@ -91,6 +94,9 @@ var ErrorMap = map[int]string{
 	ReportRecordClickCountFailed: "添加点击访问次数失败",
 	GetHotRandListFailed:         "获取热门研报列表失败",
 	QueryReportPageFailed:        "分页查询报告列表失败",
+	SearchReportPageFailed:       "分页搜索报告列表失败",
+	GetReportFailed:              "获取研报详情失败",
+	SearchKeyEmptyError:          "搜索关键字不能为空",
 }
 
 func Equals(code int, message string) bool {

+ 6 - 0
common/utils/page/page_utils.go

@@ -22,3 +22,9 @@ func StartIndex(page, pagesize int) int {
 	}
 	return 0
 }
+
+func (p *PageInfo) Reset() {
+	p.Current = 0
+	p.PageSize = 0
+	p.LatestId = 0
+}

+ 7 - 3
controllers/list_contoller.go

@@ -11,9 +11,9 @@ type ListController struct {
 }
 
 func (l *ListController) Prepare() {
-	pageSize, _ := l.GetInt("page_size")
-	currentIndex, _ := l.GetInt("current_index")
-	LatestId, _ := l.GetInt64("latest_id")
+	pageSize, _ := l.GetInt("pageSize")
+	currentIndex, _ := l.GetInt("currentIndex")
+	LatestId, _ := l.GetInt64("latestId")
 	if pageSize <= 0 {
 		pageSize = contants.PageSizeDefault
 	}
@@ -29,3 +29,7 @@ func (l *ListController) Prepare() {
 		PageSize: pageSize,
 	}
 }
+
+func (l *ListController) Finish() {
+	l.PageInfo.Reset()
+}

+ 43 - 3
controllers/report/report_controller.go

@@ -20,9 +20,32 @@ type ReportController struct {
 // @router /search [get]
 func (r *ReportController) Search(key string) {
 	controllers.Wrap(&r.BaseController, func() (result *controllers.WrapData, err error) {
-		fmt.Println(key)
-		result = r.InitWrapData("查询报告列表失败")
-		r.SuccessResult("查询报告列表成功", r.PageInfo, result)
+		result = r.InitWrapData("分页搜索报告列表失败")
+		if key == "" {
+			err = exception.New(exception.SearchKeyEmptyError)
+			r.FailedResult("分页搜索报告列表失败", result)
+			return
+		}
+		pageReq := page.Page{
+			Current:  r.PageInfo.Current,
+			PageSize: r.PageInfo.PageSize,
+		}
+		if r.PageInfo.LatestId == 0 {
+			pageReq.LatestId = report.SearchMaxReportId()
+			r.PageInfo.LatestId = pageReq.LatestId
+		} else {
+			pageReq.LatestId = r.PageInfo.LatestId
+		}
+		pageReq.Total = pageReq.LatestId
+		list, err := report.SearchReportList(key, r.PageInfo)
+		if err != nil {
+			r.FailedResult("分页搜索报告列表失败", result)
+			return
+		}
+		reports := new(page.PageResult)
+		reports.Data = list
+		reports.Page = pageReq
+		r.SuccessResult("分页搜索报告列表成功", reports, result)
 		return
 	})
 }
@@ -148,6 +171,23 @@ func (r *ReportController) Count() {
 	})
 }
 
+// GetReport 获取研报详情
+// @Description 获取研报详情
+// @Success 200 {object}
+// @router /report [get]
+func (r *ReportController) GetReport(reportId int) {
+	controllers.Wrap(&r.BaseController, func() (result *controllers.WrapData, err error) {
+		result = r.InitWrapData("获取研报详情失败")
+		fmt.Println(reportId)
+		reportDetail, err := report.GetReportById(reportId)
+		if err != nil {
+			err = exception.New(exception.GetReportFailed)
+			return
+		}
+		r.SuccessResult("获取研报详情成功", reportDetail, result)
+		return
+	})
+}
 func convertToRecordCount(req *RecordCountReq) report.RecordCount {
 	additionStr, _ := json.Marshal(req.Additional)
 	return report.RecordCount{

+ 76 - 12
domian/report/report_service.go

@@ -1,6 +1,7 @@
 package report
 
 import (
+	"encoding/json"
 	"eta_mini_ht_api/common/component/es"
 	logger "eta_mini_ht_api/common/component/log"
 	"eta_mini_ht_api/common/utils/page"
@@ -20,6 +21,14 @@ const (
 
 	DESC models.Order = "desc"
 	ASC  models.Order = "asc"
+
+	ESIndex       = "report_index"
+	ESColumn      = "abstract"
+	ESRangeColumn = "report_id"
+)
+
+var (
+	sortField = []string{"_score:desc"}
 )
 
 func elastic() *es.ESClient {
@@ -28,12 +37,13 @@ func elastic() *es.ESClient {
 
 // ESReport Report ES研报mapping
 type ESReport struct {
-	ReportID int                    `json:"report_id"`
-	OrgId    int                    `json:"org_id"`
-	Author   string                 `json:"author"`
-	Source   reportDao.ReportSource `json:"source"`
-	Abstract string                 `json:"abstract"`
-	Status   reportDao.ReportStatus `json:"status"`
+	ReportID      int                    `json:"report_id"`
+	OrgId         int                    `json:"org_id"`
+	Author        string                 `json:"author"`
+	Source        reportDao.ReportSource `json:"source"`
+	Abstract      string                 `json:"abstract"`
+	Status        reportDao.ReportStatus `json:"status"`
+	PublishedTime string                 `json:"published_time"`
 }
 
 type ReportDTO struct {
@@ -45,6 +55,7 @@ type ReportDTO struct {
 	Abstract        string      `json:"abstract"`
 	PublishedTime   string      `json:"published_time"`
 	PermissionNames interface{} `json:"permissionNames,omitempty"`
+	Highlight       []string    `json:"highlight,omitempty"`
 }
 
 type PermissionDTO struct {
@@ -66,6 +77,48 @@ type RecordCountDTO struct {
 func GetTotalPageCount() (total int64) {
 	return reportDao.GetTotalPageCount()
 }
+func SearchMaxReportId() (reportId int64) {
+	sortField = []string{"report_id:desc"}
+	request := matchAll(sortField)
+	//同步es
+	re, err := elastic().Search(request)
+	if err != nil {
+		logger.Error("es:%v", err)
+	}
+	hits := elastic().GetSource(re.Hits)
+	data := hits[0].Source
+	report := ReportDTO{}
+	err = json.Unmarshal(data, &report)
+	if err != nil {
+		logger.Error("获取当前最大研报id失败:%v", err)
+		return 0
+	}
+	return int64(report.ReportID)
+}
+
+func SearchReportList(key string, from int, size int, max int64) (reports []ReportDTO, err error) {
+	//同步es
+	sorts := append(sortField, "report_id:desc")
+	request := matchRange(key, from, size, max, sorts)
+	re, err := elastic().Search(request)
+	if err != nil {
+		logger.Error("es:%v", err)
+	}
+	hits := elastic().GetSource(re.Hits)
+	for _, hit := range hits {
+		var content map[string][]string
+		err = json.Unmarshal(hit.Highlight, &content)
+		report := ReportDTO{}
+		report.Highlight = content[ESColumn]
+		err = json.Unmarshal(hit.Source, &report)
+		if err != nil {
+			logger.Error("解析研报数据失败:%v", err)
+			continue
+		}
+		reports = append(reports, report)
+	}
+	return
+}
 func GetReportPage(pageInfo page.PageInfo) (list []ReportDTO, err error) {
 	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
 	reports, err := reportDao.GetReportPage(pageInfo.LatestId, pageInfo.PageSize, offset)
@@ -169,12 +222,13 @@ func convertEtaReport(etaRp eta.ETAReport) reportDao.Report {
 }
 func convertEsReport(report reportDao.Report) ESReport {
 	return ESReport{
-		ReportID: report.ID,
-		OrgId:    report.OrgID,
-		Author:   report.Author,
-		Source:   report.Source,
-		Abstract: report.Abstract,
-		Status:   report.Status,
+		ReportID:      report.ID,
+		OrgId:         report.OrgID,
+		Author:        report.Author,
+		Source:        report.Source,
+		Abstract:      report.Abstract,
+		Status:        report.Status,
+		PublishedTime: report.PublishedTime,
 	}
 }
 
@@ -194,3 +248,13 @@ func convertReportDTO(report reportDao.Report) (reportDTO ReportDTO) {
 	}
 	return
 }
+
+func matchAll(sorts []string) (request *es.ESQueryRequest) {
+	req := new(es.ESQueryRequest)
+	return req.CreateESQueryRequest(ESIndex, "", "", 0, 1, sorts, es.MatchAll)
+}
+
+func matchRange(key string, from int, to int, max int64, sorts []string) (request *es.ESQueryRequest) {
+	req := new(es.ESQueryRequest)
+	return req.CreateESQueryRequest(ESIndex, ESColumn, key, from, to, sorts, es.Range).Range(0, max, ESRangeColumn)
+}

+ 11 - 0
routers/commentsRouter.go

@@ -52,6 +52,17 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/report:ReportController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/report:ReportController"],
+        beego.ControllerComments{
+            Method: "GetReport",
+            Router: `/report`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(
+				param.New("reportId"),
+			),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_mini_ht_api/controllers/report:ReportController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/report:ReportController"],
         beego.ControllerComments{
             Method: "Search",

+ 15 - 0
service/report/report_service.go

@@ -44,9 +44,24 @@ type RecordCount struct {
 	Additional string
 }
 
+func GetReportById(reportId int) (report reportService.ReportDTO, err error) {
+	return
+}
 func GetTotalPageCount() (total int64) {
 	return reportService.GetTotalPageCount()
 }
+func SearchReportList(key string, pageInfo page.PageInfo) (reports []reportService.ReportDTO, err error) {
+	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
+	reports, err = reportService.SearchReportList(key, offset, pageInfo.PageSize, pageInfo.LatestId)
+	if err != nil {
+		err = exception.New(exception.SearchReportPageFailed)
+	}
+	return
+}
+
+func SearchMaxReportId() (id int64) {
+	return reportService.SearchMaxReportId()
+}
 
 // GetReportPage 分页获取报告列表
 func GetReportPage(pageInfo page.PageInfo) (list []reportService.ReportDTO, err error) {

+ 1 - 1
task/sms/code_expired_task.go

@@ -27,6 +27,6 @@ type SMSTask struct {
 }
 
 func init() {
-	smsTask := base.NewTask(taskName, cron, new(SMSTask), base.DEV)
+	smsTask := base.NewTask(taskName, cron, new(SMSTask), base.PROD)
 	base.RegisterTask(&smsTask)
 }