Initial commit: web_hghl_server
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/esmanager"
|
||||
)
|
||||
|
||||
// SearchActress 根据关键字搜索媒体
|
||||
func SearchActress(content string, from int64, size int64, sort string) (int64, []*ESActress, *srvdef.SrvErr) {
|
||||
fields := []string{FN.ESActress.Alias, FN.ESActress.Office, FN.ESActress.Region, FN.ESActress.Desc}
|
||||
must := esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESActress.Status: true}},
|
||||
},
|
||||
},
|
||||
}
|
||||
switch sort {
|
||||
case string(proto.SearchSortTypeHot):
|
||||
must = esmanager.M{
|
||||
"function_score": esmanager.M{
|
||||
"query": esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESActress.Status: true}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"functions": esmanager.A{
|
||||
esmanager.M{
|
||||
"field_value_factor": esmanager.M{
|
||||
"field": FN.ESActress.Real.WatchTimes,
|
||||
"factor": 1.0,
|
||||
"modifier": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"score_mode": "sum",
|
||||
"boost_mode": "multiply",
|
||||
},
|
||||
}
|
||||
case string(proto.SearchSortTypeNew):
|
||||
must = esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESActress.Status: true}},
|
||||
},
|
||||
"should": esmanager.A{
|
||||
{"range": esmanager.M{FN.ESActress.CreatedAt: esmanager.M{"gte": "now-30d/d", "boost": 2.0}}}, //7天内提升4倍权重
|
||||
{"range": esmanager.M{FN.ESActress.CreatedAt: esmanager.M{"gte": "now-180d/d", "boost": 1.5}}}, // 30天内提升3倍权重
|
||||
{"range": esmanager.M{FN.ESActress.CreatedAt: esmanager.M{"gte": "now-365d/d", "boost": 1.1}}}, // 90天内提升1.5倍权重
|
||||
},
|
||||
"minimum_should_match": 0, // 允许不匹配任何should条件
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
query := esmanager.M{
|
||||
"query": must,
|
||||
"sort": esmanager.A{
|
||||
esmanager.M{"_score": esmanager.M{"order": "desc"}},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
actressList := &ESActressHits{}
|
||||
err := esmanager.Instance.Search(actressIndex, actressList, query)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf(
|
||||
"(esmod:SearchActress) Search failed! err:%+v:", err)
|
||||
log.Warn(info,
|
||||
log.Any("keywords", content),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size))
|
||||
return 0, nil, srvdef.New(srvdef.ErrElsOperError, "", "")
|
||||
}
|
||||
total := int64(0)
|
||||
rslData := make([]*ESActress, 0)
|
||||
if actressList != nil && actressList.Hits != nil && len(actressList.Hits) > 0 {
|
||||
total = actressList.Total.Value
|
||||
for _, video := range actressList.Hits {
|
||||
rslData = append(rslData, video.Source)
|
||||
}
|
||||
}
|
||||
return total, rslData, nil
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
const (
|
||||
FiveMinuteScale = 5 //对齐时间(分钟)
|
||||
)
|
||||
|
||||
var (
|
||||
videoIndex = "webhjsq_video_index_v1"
|
||||
playletIndex = "webhjsq_playlet_index_v1"
|
||||
actressIndex = "webhjsq_actress_index_v1"
|
||||
)
|
||||
|
||||
func GetVideoIndex() string {
|
||||
return videoIndex
|
||||
}
|
||||
func GetPlayletIndex() string {
|
||||
return playletIndex
|
||||
}
|
||||
func GetActressIndex() string {
|
||||
return actressIndex
|
||||
}
|
||||
|
||||
func GetRecordByESIndex(ctx context.Context, esIndex string) (
|
||||
*ESTimestamp, *srvdef.SrvErr) {
|
||||
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
esRecord, serr := FindOneESRecord(ctx, filter)
|
||||
if serr != nil {
|
||||
if serr.Code != srvdef.ErrNoData {
|
||||
return nil, serr
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return &esRecord.Timestamp, nil
|
||||
}
|
||||
|
||||
func SetOneEsRecord(ctx context.Context, esIndex string,
|
||||
timestamp *ESTimestamp) *srvdef.SrvErr {
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
upsertDoc := bson.M{
|
||||
"$set": bson.M{
|
||||
FN.ESRecord.Timestamp.T: timestamp.T,
|
||||
FN.ESRecord.Timestamp.I: timestamp.I,
|
||||
FN.ESRecord.UpdatedAt: time.Now(),
|
||||
},
|
||||
"$setOnInsert": bson.M{
|
||||
FN.ESRecord.Id: primitive.NewObjectID(),
|
||||
FN.ESRecord.CreatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
serr := UpsertOneESRecord(ctx, filter, upsertDoc)
|
||||
return serr
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"videoweb/pub/esmanager"
|
||||
"videoweb/pub/mongos"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var db *mongos.Collection
|
||||
|
||||
// Init 初始化数据
|
||||
func Init(ctx context.Context) {
|
||||
initDBIndex(ctx)
|
||||
initIndex()
|
||||
return
|
||||
}
|
||||
|
||||
// initIndex 初始化索引
|
||||
func initIndex() {
|
||||
if esmanager.Instance == nil {
|
||||
return
|
||||
}
|
||||
initVideoIndex(videoIndex)
|
||||
initPlayletIndex(playletIndex)
|
||||
initActressIndex(actressIndex)
|
||||
}
|
||||
|
||||
// initDBIndex 初始化数据库索引
|
||||
func initDBIndex(ctx context.Context) {
|
||||
//获取数据库表
|
||||
db = mongos.Shop.Coll(TN.ESRecord)
|
||||
// 获取数据库表
|
||||
indexes := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{
|
||||
{Key: FN.ESRecord.EsIndex, Value: 1},
|
||||
},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
}
|
||||
if _, err := db.CreateIndex(ctx, indexes); err != nil {
|
||||
panic(fmt.Sprintf("(esmod:initDBIndex) Create es_record Index failed! err:%+v:", err))
|
||||
}
|
||||
}
|
||||
|
||||
func initVideoIndex(esIndex string) {
|
||||
var setting = esmanager.M{
|
||||
"settings": esmanager.M{
|
||||
"number_of_shards": esmanager.NumberOfShards,
|
||||
"number_of_replicas": esmanager.NumberOfReplicas,
|
||||
"analysis": esmanager.M{
|
||||
"analyzer": esmanager.M{
|
||||
"ik": esmanager.M{
|
||||
"tokenizer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
FN.ESVideo.Title: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.MediaType: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.Remark: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Desc: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Keyworlds: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.CreatorName: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Bango: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.IssuedBrand: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESVideo.Status: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
//FN.ESVideo.IsHot: esmanager.M{
|
||||
// "type": "boolean",
|
||||
//},
|
||||
//FN.ESVideo.Sort: esmanager.M{
|
||||
// "type": "integer",
|
||||
//},
|
||||
FN.ESVideo.WatchTimes: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.ShowTimes: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.Comments: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESVideo.AddedTime: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESVideo.IssuedAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
//FN.ESVideo.CreatedAt: esmanager.M{
|
||||
// "type": "date",
|
||||
// "format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
//},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
|
||||
panic(fmt.Sprintf("ElasticSearch Index %s initMediaIndex error", esIndex))
|
||||
}
|
||||
}
|
||||
|
||||
func initPlayletIndex(esIndex string) {
|
||||
var setting = esmanager.M{
|
||||
"settings": esmanager.M{
|
||||
"number_of_shards": esmanager.NumberOfShards,
|
||||
"number_of_replicas": esmanager.NumberOfReplicas,
|
||||
"analysis": esmanager.M{
|
||||
"analyzer": esmanager.M{
|
||||
"ik": esmanager.M{
|
||||
"tokenizer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
FN.ESPlaylet.Id: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.Status: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESPlaylet.IsFeatured: esmanager.M{
|
||||
"type": "boolean",
|
||||
},
|
||||
FN.ESPlaylet.IsRecommend: esmanager.M{
|
||||
"type": "boolean",
|
||||
},
|
||||
FN.ESPlaylet.ShowOnBanner: esmanager.M{
|
||||
"type": "boolean",
|
||||
},
|
||||
FN.ESPlaylet.Banner: esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
FN.ESPlaylet.OnlineAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESPlaylet.CategoryIds: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.CategoryNames: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.ThemeIds: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.ThemeNames: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Title: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Desc: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Anchor: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.Cover: esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
FN.ESPlaylet.TagIds: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.TagNames: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkMaxWord,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESPlaylet.TotalEpisode: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.UpdateStatus: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESPlaylet.CountBrowse: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.HeatValue: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.CountCollect: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.CountLike: esmanager.M{
|
||||
"type": "long",
|
||||
},
|
||||
FN.ESPlaylet.SeoInfo: esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
"title": esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
"keyworld": esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
"description": esmanager.M{
|
||||
"type": "keyword",
|
||||
"index": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
FN.ESPlaylet.UpdatedAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESPlaylet.CreatedAt: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
|
||||
panic(fmt.Sprintf("ElasticSearch Index %s initPlayletIndex error", esIndex))
|
||||
}
|
||||
}
|
||||
|
||||
func initActressIndex(esIndex string) {
|
||||
var setting = esmanager.M{
|
||||
"settings": esmanager.M{
|
||||
"number_of_shards": esmanager.NumberOfShards,
|
||||
"number_of_replicas": esmanager.NumberOfReplicas,
|
||||
"analysis": esmanager.M{
|
||||
"analyzer": esmanager.M{
|
||||
"ik": esmanager.M{
|
||||
"tokenizer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": esmanager.M{
|
||||
"properties": esmanager.M{
|
||||
FN.ESActress.Alias: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Desc: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Office: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Region: esmanager.M{
|
||||
"type": "text",
|
||||
"analyzer": esmanager.AnalyzerIkSmart,
|
||||
"search_analyzer": esmanager.AnalyzerIkSmart,
|
||||
},
|
||||
FN.ESActress.Rank: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Status: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Works: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.HotValue: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Real.WatchTimes: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Real.WeekWatchs: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.Real.MonthWatchs: esmanager.M{
|
||||
"type": "integer",
|
||||
},
|
||||
FN.ESActress.DebutDate: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
FN.ESActress.DebutDate: esmanager.M{
|
||||
"type": "date",
|
||||
"format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := esmanager.Instance.InitIndices(esIndex, setting); err != nil {
|
||||
panic(fmt.Sprintf("ElasticSearch Index %s initMediaIndex error", esIndex))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/esmanager"
|
||||
"videoweb/pub/models/playletmod"
|
||||
)
|
||||
|
||||
// SearchPlaylet 根据关键字搜索短剧
|
||||
func SearchPlaylet(content string, from int64, size int64, sort string) (int64, []*ESPlaylet, *srvdef.SrvErr) {
|
||||
fields := []string{
|
||||
FN.ESPlaylet.Title,
|
||||
FN.ESPlaylet.Desc,
|
||||
FN.ESPlaylet.Anchor,
|
||||
FN.ESPlaylet.CategoryNames,
|
||||
FN.ESPlaylet.ThemeNames,
|
||||
FN.ESPlaylet.TagNames,
|
||||
}
|
||||
must := esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESPlaylet.Status: playletmod.StatusUp}},
|
||||
},
|
||||
},
|
||||
}
|
||||
switch sort {
|
||||
case string(proto.SearchSortTypeHot):
|
||||
must = esmanager.M{
|
||||
"function_score": esmanager.M{
|
||||
"query": esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESPlaylet.Status: playletmod.StatusUp}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"functions": esmanager.A{
|
||||
esmanager.M{
|
||||
"field_value_factor": esmanager.M{
|
||||
"field": FN.ESPlaylet.CountBrowse,
|
||||
"factor": 1.0,
|
||||
"modifier": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"score_mode": "sum",
|
||||
"boost_mode": "multiply",
|
||||
},
|
||||
}
|
||||
case string(proto.SearchSortTypeNew):
|
||||
must = esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESPlaylet.Status: playletmod.StatusUp}},
|
||||
},
|
||||
"should": esmanager.A{
|
||||
{"range": esmanager.M{FN.ESPlaylet.OnlineAt: esmanager.M{"gte": "now-30d/d", "boost": 2.0}}},
|
||||
{"range": esmanager.M{FN.ESPlaylet.OnlineAt: esmanager.M{"gte": "now-180d/d", "boost": 1.5}}},
|
||||
{"range": esmanager.M{FN.ESPlaylet.OnlineAt: esmanager.M{"gte": "now-365d/d", "boost": 1.1}}},
|
||||
},
|
||||
"minimum_should_match": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
query := esmanager.M{
|
||||
"query": must,
|
||||
"sort": esmanager.A{
|
||||
esmanager.M{"_score": esmanager.M{"order": "desc"}},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
"terminate_after": 1000,
|
||||
}
|
||||
|
||||
playletList := &ESPlayletHits{}
|
||||
err := esmanager.Instance.Search(playletIndex, playletList, query)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf("(esmod:SearchPlaylet) Search failed! err:%+v:", err)
|
||||
log.Warn(info, log.Any("keywords", content), log.Any("from", from), log.Any("size", size))
|
||||
return 0, nil, srvdef.New(srvdef.ErrElsOperError, "", "")
|
||||
}
|
||||
total := int64(0)
|
||||
result := make([]*ESPlaylet, 0)
|
||||
if playletList != nil && playletList.Hits != nil && len(playletList.Hits) > 0 {
|
||||
total = playletList.Total.Value
|
||||
for _, item := range playletList.Hits {
|
||||
if item != nil && item.Source != nil {
|
||||
result = append(result, item.Source)
|
||||
}
|
||||
}
|
||||
}
|
||||
return total, result, nil
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"time"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// InsertOneESRecord 插入ES操作记录
|
||||
func InsertOneESRecord(ctx context.Context, esRecord *ESRecord) *srvdef.SrvErr {
|
||||
if _, err := db.InsertOne(ctx, esRecord); err != nil {
|
||||
log.Warn("esmod:InsertOneESRecord db.InsertOne failed", log.E(err))
|
||||
return srvdef.New(srvdef.ErrDbInsertError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelOneESRecord 删除一个ES操作记录
|
||||
func DelOneESRecord(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.DeleteOne(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("esmod:DelOnAppTag db.DeleteOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// FindOneESRecord 查找一个ES操作记录
|
||||
func FindOneESRecord(ctx context.Context, filter bson.M) (
|
||||
*ESRecord, *srvdef.SrvErr) {
|
||||
var esRecord ESRecord
|
||||
if err := db.FindOneEx(
|
||||
ctx, &esRecord, filter); err != nil {
|
||||
if err != mongo.ErrNoDocuments {
|
||||
log.Info("esmod:FindOnESRecord db.FindOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
||||
}
|
||||
return &esRecord, nil
|
||||
}
|
||||
|
||||
// CountESRecords 统计ES操作记录
|
||||
func CountESRecords(ctx context.Context, filter bson.M) (
|
||||
int64, *srvdef.SrvErr) {
|
||||
count, err := db.Count(ctx, filter)
|
||||
if err != nil {
|
||||
log.Warn("esmod:CountMediaCats db.Count failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// UpdateOneESRecord 更新ES操作记录
|
||||
func UpdateOneESRecord(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateOne(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("esmod:UpdateOnESRecord db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount != 1 {
|
||||
log.Warn("esmod:UpdateOnESRecord db.UpdateOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrMediaRecordNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpsertOneESRecord 插入或更新一条ES操作记录
|
||||
func UpsertOneESRecord(ctx context.Context,
|
||||
filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
if _, err := db.UpsertOne(ctx, filter, update); err != nil {
|
||||
log.Info("esmod:UpsertOneESRecord db.InsertOne failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateManyESRecord 更新一批ES操作记录
|
||||
func UpdateManyESRecord(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
|
||||
result, err := db.UpdateMMany(ctx, filter, update)
|
||||
if err != nil {
|
||||
log.Warn("esmod:UpdateManyMediaCat db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
|
||||
}
|
||||
if result.MatchedCount <= 0 {
|
||||
log.Warn("esmod:UpdateManyMediaCat db.UpdateMMany failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
//return srvdef.New(srvdef.ErrMediaTagNotExsit, "", "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindManyESRecord 查找一批ES操作记录
|
||||
func FindManyESRecord(ctx context.Context, filter bson.M,
|
||||
opts ...*options.FindOptions) (ESRecordList, *srvdef.SrvErr) {
|
||||
data := make(ESRecordList, 0)
|
||||
if err := db.Find(ctx, &data, filter, opts...); err != nil {
|
||||
log.Warn("esmod:FindManyESRecord db.Find failed",
|
||||
log.E(err), log.Any("filter", filter))
|
||||
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func GetRecordTimeByESIndex(ctx context.Context, esIndex string) (*ESRecord, *srvdef.SrvErr) {
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
esRecord, serr := FindOneESRecord(ctx, filter)
|
||||
if serr != nil {
|
||||
if serr.Code != srvdef.ErrNoData {
|
||||
return nil, serr
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
return esRecord, nil
|
||||
}
|
||||
func SetOneEsRecordTime(ctx context.Context, esIndex string, recordTime time.Time) *srvdef.SrvErr {
|
||||
filter := bson.M{FN.ESRecord.EsIndex: esIndex}
|
||||
upsertDoc := bson.M{
|
||||
"$set": bson.M{
|
||||
FN.ESRecord.RecordTime: recordTime,
|
||||
FN.ESRecord.UpdatedAt: time.Now(),
|
||||
},
|
||||
"$setOnInsert": bson.M{
|
||||
FN.ESRecord.Id: primitive.NewObjectID(),
|
||||
FN.ESRecord.CreatedAt: time.Now(),
|
||||
},
|
||||
}
|
||||
serr := UpsertOneESRecord(ctx, filter, upsertDoc)
|
||||
return serr
|
||||
}
|
||||
Executable
+227
@@ -0,0 +1,227 @@
|
||||
package esmod
|
||||
|
||||
type TagESRecord struct {
|
||||
CreatedAt string
|
||||
EsIndex string
|
||||
Id string
|
||||
RecordTime string
|
||||
Timestamp struct {
|
||||
I string
|
||||
T string
|
||||
}
|
||||
UpdatedAt string
|
||||
}
|
||||
type TagESVideo struct {
|
||||
Id string
|
||||
Title string
|
||||
MediaType string
|
||||
AddedTime string
|
||||
CreatorName string
|
||||
Keyworlds string
|
||||
Desc string
|
||||
Remark string
|
||||
Status string
|
||||
IsHot string
|
||||
Sort string
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
UpdatedAt string
|
||||
CreatedAt string
|
||||
|
||||
Keyworld string
|
||||
CreatorId string
|
||||
FirstTag string
|
||||
SecondTags string
|
||||
CoverImg string
|
||||
Nodes string
|
||||
Video string
|
||||
CategoryIds string
|
||||
Tags string
|
||||
Real struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}
|
||||
IssuedAt string
|
||||
IssuedBrand string
|
||||
Bango string
|
||||
}
|
||||
type TagESPlaylet struct {
|
||||
Id string
|
||||
Status string
|
||||
IsFeatured string
|
||||
IsRecommend string
|
||||
ShowOnBanner string
|
||||
Banner string
|
||||
OnlineAt string
|
||||
CategoryIds string
|
||||
CategoryNames string
|
||||
ThemeIds string
|
||||
ThemeNames string
|
||||
Title string
|
||||
Desc string
|
||||
Anchor string
|
||||
Cover string
|
||||
TagIds string
|
||||
TagNames string
|
||||
TotalEpisode string
|
||||
UpdateStatus string
|
||||
CountBrowse string
|
||||
HeatValue string
|
||||
CountCollect string
|
||||
CountLike string
|
||||
SeoInfo string
|
||||
UpdatedAt string
|
||||
CreatedAt string
|
||||
}
|
||||
type TagESActress struct {
|
||||
Id string
|
||||
Alias string
|
||||
Avatar string
|
||||
Meas string
|
||||
Office string
|
||||
DebutDate string
|
||||
BornDate string
|
||||
Region string
|
||||
Score string
|
||||
Works string
|
||||
HotValue string
|
||||
Real struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}
|
||||
Desc string
|
||||
Status string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
Rank string
|
||||
}
|
||||
|
||||
var FN struct {
|
||||
ESRecord TagESRecord
|
||||
ESVideo TagESVideo
|
||||
ESPlaylet TagESPlaylet
|
||||
ESActress TagESActress
|
||||
}
|
||||
|
||||
var TN struct {
|
||||
ESRecord string
|
||||
ESVideo string
|
||||
ESPlaylet string
|
||||
ESActress string
|
||||
}
|
||||
|
||||
func init() {
|
||||
FN.ESRecord = TagESRecord{
|
||||
CreatedAt: "createdAt",
|
||||
EsIndex: "esIndex",
|
||||
Id: "_id",
|
||||
RecordTime: "recordTime",
|
||||
Timestamp: struct {
|
||||
I string
|
||||
T string
|
||||
}{
|
||||
I: "i",
|
||||
T: "t",
|
||||
},
|
||||
UpdatedAt: "updatedAt",
|
||||
}
|
||||
FN.ESVideo = TagESVideo{
|
||||
Id: "_id",
|
||||
Title: "title",
|
||||
Desc: "desc",
|
||||
Status: "status",
|
||||
AddedTime: "addedTime",
|
||||
MediaType: "mediaType",
|
||||
CreatorName: "creatorName",
|
||||
Keyworlds: "keyworlds",
|
||||
Remark: "remark",
|
||||
IsHot: "isHot",
|
||||
Sort: "sort",
|
||||
UpdatedAt: "updatedAt",
|
||||
CreatedAt: "createdAt",
|
||||
WatchTimes: "watchTimes",
|
||||
ShowTimes: "showTimes",
|
||||
Comments: "comments",
|
||||
IssuedAt: "issuedAt",
|
||||
IssuedBrand: "issuedBrand",
|
||||
Bango: "bango",
|
||||
Real: struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}{WatchTimes: "watchTimes", ShowTimes: "showTimes", Comments: "comments", WeekWatchs: "weekWatchs", MonthWatchs: "monthWatchs", TodayWatchs: "todayWatchs"},
|
||||
}
|
||||
|
||||
FN.ESPlaylet = TagESPlaylet{
|
||||
Id: "id",
|
||||
Status: "status",
|
||||
IsFeatured: "isFeatured",
|
||||
IsRecommend: "isRecommend",
|
||||
ShowOnBanner: "showOnBanner",
|
||||
Banner: "banner",
|
||||
OnlineAt: "onlineAt",
|
||||
CategoryIds: "categoryIds",
|
||||
CategoryNames: "categoryNames",
|
||||
ThemeIds: "themeIds",
|
||||
ThemeNames: "themeNames",
|
||||
Title: "title",
|
||||
Desc: "desc",
|
||||
Anchor: "anchor",
|
||||
Cover: "cover",
|
||||
TagIds: "tagIds",
|
||||
TagNames: "tagNames",
|
||||
TotalEpisode: "totalEpisode",
|
||||
UpdateStatus: "updateStatus",
|
||||
CountBrowse: "countBrowse",
|
||||
HeatValue: "heatValue",
|
||||
CountCollect: "countCollect",
|
||||
CountLike: "countLike",
|
||||
SeoInfo: "seoInfo",
|
||||
UpdatedAt: "updatedAt",
|
||||
CreatedAt: "createdAt",
|
||||
}
|
||||
|
||||
FN.ESActress = TagESActress{
|
||||
Id: "_id",
|
||||
Alias: "alias",
|
||||
Avatar: "avatar",
|
||||
Meas: "meas",
|
||||
Office: "office",
|
||||
DebutDate: "debutDate",
|
||||
BornDate: "bornDate",
|
||||
Region: "region",
|
||||
Score: "score",
|
||||
Works: "works",
|
||||
HotValue: "hotValue",
|
||||
Real: struct {
|
||||
WatchTimes string
|
||||
ShowTimes string
|
||||
Comments string
|
||||
WeekWatchs string
|
||||
MonthWatchs string
|
||||
TodayWatchs string
|
||||
}{WatchTimes: "watchTimes", ShowTimes: "showTimes", Comments: "comments", WeekWatchs: "weekWatchs", MonthWatchs: "monthWatchs", TodayWatchs: "todayWatchs"},
|
||||
Desc: "desc",
|
||||
Status: "status",
|
||||
CreatedAt: "createdAt",
|
||||
UpdatedAt: "updatedAt",
|
||||
Rank: "rank",
|
||||
}
|
||||
|
||||
TN.ESRecord = "es_record"
|
||||
TN.ESVideo = "es_video"
|
||||
TN.ESPlaylet = "es_playlet"
|
||||
TN.ESActress = "es_actress"
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
//go:generate gen_bson_tag -m esmod
|
||||
//esmod essearch数据结构定义
|
||||
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
"videoweb/pub/models/actress"
|
||||
"videoweb/pub/models/playletmod"
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/pub/pubdef"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type ESTimestamp struct {
|
||||
T uint32 `json:"t" bson:"t"`
|
||||
I uint32 `json:"i" bson:"i"`
|
||||
}
|
||||
|
||||
func (v *ESTimestamp) IsZero() bool {
|
||||
if v == nil {
|
||||
return true
|
||||
}
|
||||
return v.T == 0 && v.I == 0
|
||||
}
|
||||
|
||||
// ESOperator es操作记录
|
||||
// @table:es_record
|
||||
type ESRecord struct {
|
||||
Id primitive.ObjectID `json:"id" bson:"_id"`
|
||||
EsIndex string `json:"esIndex" bson:"esIndex"` //es索引名称
|
||||
Timestamp ESTimestamp `json:"timestamp" bson:"timestamp"` //操作时间
|
||||
RecordTime time.Time `json:"recordTime" bson:"recordTime"` // 操作记录时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //更新时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
}
|
||||
|
||||
type ESRecordList []*ESRecord
|
||||
|
||||
// ESVideo es中存储的media数据
|
||||
// @table:es_video
|
||||
type ESVideo struct {
|
||||
Id int64 `json:"id" bson:"_id,omitempty"`
|
||||
Title string `json:"title" bson:"title"` // 帖子标题
|
||||
MediaType videoinformationmod.MediaType `json:"mediaType" bson:"mediaType"` // 资源类型
|
||||
AddedTime time.Time `json:"addedTime" bson:"addedTime"` // 帖子上架时间
|
||||
CreatorName string `json:"creatorName" bson:"creatorName"` // 作者名称
|
||||
Keyworlds string `bson:"keyworlds,omitempty" json:"keyworlds"` // 关键字
|
||||
Desc string `bson:"desc,omitempty" json:"desc"` // 详细描述
|
||||
Remark string `bson:"remark,omitempty" json:"remark"` // 备注
|
||||
Status pubdef.InformationStatus `json:"status" bson:"status"` // 帖子上架状态
|
||||
IsHot bool `json:"isHot" bson:"isHot"` // 是否热门
|
||||
Sort int64 `json:"sort" bson:"sort"` // 排序
|
||||
WatchTimes int64 `json:"watchTimes" bson:"watchTimes"` // 观看次数
|
||||
ShowTimes int64 `json:"showTimes" bson:"showTimes"` // 展示次数
|
||||
Comments int64 `json:"comments" bson:"comments"` // 评论条数
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
Keyworld []string `bson:"keyworld,omitempty" json:"keyworld"` // 关键字
|
||||
CreatorId int64 `json:"creatorId" bson:"creatorId"` // 作者Id
|
||||
FirstTag string `bson:"firstTag,omitempty" json:"firstTag"` // 一级标签
|
||||
SecondTags []string `bson:"secondTags,omitempty" json:"secondTags"` // 二级标签标签
|
||||
CoverImg string `bson:"coverImg,omitempty" json:"coverImg"` // 封面
|
||||
Nodes []videoinformationmod.Node `json:"nodes" bson:"nodes"` // 节点
|
||||
Video videoinformationmod.VideoInfo `json:"video" bson:"video"` // 视频
|
||||
Tags []int64 `json:"tags" bson:"tags"` // 标签
|
||||
Real pubdef.Flow `json:"real" bson:"real"` // 真实流量
|
||||
VideoCount int64 `json:"videoCount" bson:"videoCount"` // 合集视频数量
|
||||
IssuedAt time.Time `json:"issuedAt" bson:"issuedAt"` // 发行时间
|
||||
IssuedBrand string `json:"issuedBrand" bson:"issuedBrand"` // 发行商
|
||||
Bango string `bson:"bango,omitempty" json:"bango"` // 番号,唯一
|
||||
}
|
||||
|
||||
type ESVideoList []*ESVideo
|
||||
type ESTotal struct {
|
||||
Value int64 `json:"value"`
|
||||
}
|
||||
|
||||
type ESVideoSource struct {
|
||||
ID string `json:"_id"`
|
||||
Score float32 `json:"_score"`
|
||||
Source *ESVideo `json:"_source"`
|
||||
}
|
||||
|
||||
// ESVideoHits search media hits
|
||||
type ESVideoHits struct {
|
||||
Total ESTotal `json:"total"`
|
||||
Hits []*ESVideoSource `json:"hits"`
|
||||
}
|
||||
|
||||
// ESPlaylet es中存储的短剧搜索数据
|
||||
// @table:es_playlet
|
||||
type ESPlaylet struct {
|
||||
Id int64 `json:"id" bson:"id"` // 短剧ID
|
||||
Status playletmod.Status `json:"status" bson:"status"` // 状态: 0下架 1上架
|
||||
IsFeatured bool `json:"isFeatured" bson:"isFeatured"` // 是否爆剧
|
||||
IsRecommend bool `json:"isRecommend" bson:"isRecommend"` // 是否推荐
|
||||
ShowOnBanner bool `json:"showOnBanner" bson:"showOnBanner"` // 是否显示在首页banner
|
||||
Banner string `json:"banner" bson:"banner"` // banner图
|
||||
OnlineAt time.Time `json:"onlineAt" bson:"onlineAt"` // 上架时间
|
||||
CategoryIds []int64 `json:"categoryIds" bson:"categoryIds"` // 分类ID集合
|
||||
CategoryNames []string `json:"categoryNames" bson:"categoryNames"` // 分类名称集合
|
||||
ThemeIds []int64 `json:"themeIds" bson:"themeIds"` // 题材ID集合
|
||||
ThemeNames []string `json:"themeNames" bson:"themeNames"` // 题材名称集合
|
||||
Title string `json:"title" bson:"title"` // 剧名
|
||||
Desc string `json:"desc" bson:"desc"` // 简介
|
||||
Anchor string `json:"anchor" bson:"anchor"` // 作者/演员
|
||||
Cover string `json:"cover" bson:"cover"` // 封面
|
||||
TagIds []int64 `json:"tagIds" bson:"tagIds"` // 标签ID集合
|
||||
TagNames []string `json:"tagNames" bson:"tagNames"` // 标签名称集合
|
||||
TotalEpisode int64 `json:"totalEpisode" bson:"totalEpisode"` // 总集数
|
||||
UpdateStatus int `json:"updateStatus" bson:"updateStatus"` // 更新状态 1-连载中 2-已完结
|
||||
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` // 观看量
|
||||
HeatValue int64 `json:"heatValue" bson:"heatValue"` // 热度值
|
||||
CountCollect int64 `json:"countCollect" bson:"countCollect"` // 收藏数
|
||||
CountLike int64 `json:"countLike" bson:"countLike"` // 展示点赞数
|
||||
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 修改时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
}
|
||||
|
||||
type ESPlayletList []*ESPlaylet
|
||||
|
||||
type ESPlayletSource struct {
|
||||
ID string `json:"_id"`
|
||||
Score float32 `json:"_score"`
|
||||
Source *ESPlaylet `json:"_source"`
|
||||
}
|
||||
|
||||
// ESPlayletHits search playlet hits
|
||||
type ESPlayletHits struct {
|
||||
Total ESTotal `json:"total"`
|
||||
Hits []*ESPlayletSource `json:"hits"`
|
||||
}
|
||||
|
||||
// ESActress es中存储的actress数据
|
||||
// @table:es_actress
|
||||
type ESActress struct {
|
||||
Id int64 `json:"id" bson:"_id"` // Id
|
||||
Alias string `bson:"alias" json:"alias"` // 别名
|
||||
Avatar string `bson:"avatar" json:"avatar"` // 头像
|
||||
Meas actress.Meas `bson:"meas" json:"meas"` // 三围
|
||||
Desc string `bson:"desc" json:"desc"` // 详细描述
|
||||
Office string `json:"office" bson:"office"` // 事务所
|
||||
DebutDate time.Time `bson:"debutDate" json:"debutDate" ` // 出道日期
|
||||
BornDate time.Time `bson:"bornDate" json:"bornDate"` // 出生日期
|
||||
Region string `json:"region" bson:"region"` // 地区/国家
|
||||
Score string `json:"score" bson:"score"` // 评分
|
||||
Works int64 `json:"works" bson:"works"` // 作品数
|
||||
HotValue int64 `json:"hotValue" bson:"hotValue"` // 热度值
|
||||
Real pubdef.Flow `json:"real" bson:"real"` // 真实流量
|
||||
Status bool `json:"status" bson:"status"` // 状态
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
|
||||
TranslationCategoryId int64 `bson:"translationCategoryId" json:"translationCategoryId"` // 关联导航分类id
|
||||
Rank int64 `json:"rank" bson:"rank"` // 排序
|
||||
}
|
||||
|
||||
type ESActressList []*ESActress
|
||||
|
||||
type ESActressSource struct {
|
||||
ID string `json:"_id"`
|
||||
Score float32 `json:"_score"`
|
||||
Source *ESActress `json:"_source"`
|
||||
}
|
||||
|
||||
// ESActressHits search media hits
|
||||
type ESActressHits struct {
|
||||
Total ESTotal `json:"total"`
|
||||
Hits []*ESActressSource `json:"hits"`
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package esmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/esmanager"
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/pub/pubdef"
|
||||
)
|
||||
|
||||
// SearchVideo 根据关键字搜索媒体
|
||||
func SearchVideo(content string, from int64, size int64, sort string, isAv bool) (int64, []*videoinformationmod.VideoInformation, *srvdef.SrvErr) {
|
||||
fields := []string{FN.ESVideo.Title, FN.ESVideo.Bango, FN.ESVideo.IssuedBrand, FN.ESVideo.Keyworlds, FN.ESVideo.Desc}
|
||||
mediaType := videoinformationmod.MediaType_Video
|
||||
if isAv {
|
||||
mediaType = videoinformationmod.MediaType_AV
|
||||
}
|
||||
must := esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESVideo.Status: pubdef.InformationStatusVerifyOK}},
|
||||
{"term": esmanager.M{FN.ESVideo.MediaType: mediaType}},
|
||||
},
|
||||
},
|
||||
}
|
||||
switch sort {
|
||||
case string(proto.SearchSortTypeHot):
|
||||
must = esmanager.M{
|
||||
"function_score": esmanager.M{
|
||||
"query": esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields,
|
||||
}},
|
||||
{"term": esmanager.M{FN.ESVideo.Status: pubdef.InformationStatusVerifyOK}},
|
||||
{"term": esmanager.M{FN.ESVideo.MediaType: mediaType}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"functions": esmanager.A{
|
||||
esmanager.M{
|
||||
"field_value_factor": esmanager.M{
|
||||
"field": FN.ESVideo.WatchTimes,
|
||||
"factor": 1.0,
|
||||
"modifier": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"score_mode": "sum",
|
||||
"boost_mode": "multiply",
|
||||
},
|
||||
}
|
||||
case string(proto.SearchSortTypeNew):
|
||||
must = esmanager.M{
|
||||
"bool": esmanager.M{
|
||||
"must": esmanager.A{
|
||||
{"multi_match": esmanager.M{
|
||||
"query": content,
|
||||
"type": "best_fields",
|
||||
"fields": fields},
|
||||
},
|
||||
{"term": esmanager.M{FN.ESVideo.Status: pubdef.InformationStatusVerifyOK}},
|
||||
{"term": esmanager.M{FN.ESVideo.MediaType: mediaType}},
|
||||
},
|
||||
"should": esmanager.A{
|
||||
{"range": esmanager.M{FN.ESVideo.AddedTime: esmanager.M{"gte": "now-30d/d", "boost": 2.0}}}, //7天内提升4倍权重
|
||||
{"range": esmanager.M{FN.ESVideo.AddedTime: esmanager.M{"gte": "now-180d/d", "boost": 1.5}}}, // 30天内提升3倍权重
|
||||
{"range": esmanager.M{FN.ESVideo.AddedTime: esmanager.M{"gte": "now-365d/d", "boost": 1.1}}}, // 90天内提升1.5倍权重
|
||||
},
|
||||
"minimum_should_match": 0, // 允许不匹配任何should条件
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
query := esmanager.M{
|
||||
"query": must,
|
||||
"sort": esmanager.A{
|
||||
esmanager.M{"_score": esmanager.M{"order": "desc"}},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
}
|
||||
|
||||
log.Info("(esmod:SearchVideo) 执行搜索",
|
||||
log.Any("index", videoIndex),
|
||||
log.Any("keywords", content),
|
||||
log.Any("sort", sort),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size))
|
||||
videos := &ESVideoHits{}
|
||||
err := esmanager.Instance.Search(videoIndex, videos, query)
|
||||
if err != nil {
|
||||
info := fmt.Sprintf(
|
||||
"(esmod:SearchVideo) Search failed! err:%+v:", err)
|
||||
log.Warn(info,
|
||||
log.Any("keywords", content),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size))
|
||||
return 0, nil, srvdef.New(srvdef.ErrElsOperError, "", "")
|
||||
}
|
||||
total := int64(0)
|
||||
rslData := make([]*videoinformationmod.VideoInformation, 0)
|
||||
if videos != nil && videos.Hits != nil && len(videos.Hits) > 0 {
|
||||
total = videos.Total.Value
|
||||
for _, video := range videos.Hits {
|
||||
rslData = append(rslData, EsVideoInfoToData(video.Source))
|
||||
}
|
||||
}
|
||||
log.Info("(esmod:SearchVideo) 搜索完成",
|
||||
log.Any("index", videoIndex),
|
||||
log.Any("keywords", content),
|
||||
log.Any("total", total),
|
||||
log.Any("hits", len(rslData)))
|
||||
return total, rslData, nil
|
||||
}
|
||||
|
||||
func EsVideoInfoToData(esInfo *ESVideo) *videoinformationmod.VideoInformation {
|
||||
info := &videoinformationmod.VideoInformation{
|
||||
Id: esInfo.Id,
|
||||
Title: esInfo.Title,
|
||||
MediaType: esInfo.MediaType,
|
||||
AddedTime: esInfo.AddedTime,
|
||||
CreatorId: esInfo.CreatorId,
|
||||
CreatorName: esInfo.CreatorName,
|
||||
Keyworld: esInfo.Keyworld,
|
||||
FirstTag: esInfo.FirstTag,
|
||||
SecondTags: esInfo.SecondTags,
|
||||
CoverImg: esInfo.CoverImg,
|
||||
Desc: esInfo.Desc,
|
||||
Remark: esInfo.Remark,
|
||||
Nodes: esInfo.Nodes,
|
||||
Status: esInfo.Status,
|
||||
Video: esInfo.Video,
|
||||
Tags: esInfo.Tags,
|
||||
IsHot: esInfo.IsHot,
|
||||
Sort: esInfo.Sort,
|
||||
Real: esInfo.Real,
|
||||
VideoCount: esInfo.VideoCount,
|
||||
UpdatedAt: esInfo.UpdatedAt,
|
||||
CreatedAt: esInfo.CreatedAt,
|
||||
}
|
||||
return info
|
||||
}
|
||||
Reference in New Issue
Block a user